【问题标题】:Different behaviour of bash script on supervisor start and restart主管启动和重新启动时 bash 脚本的不同行为
【发布时间】:2017-08-31 10:22:54
【问题描述】:

我有 bash 脚本可以做一些事情,(例如:)

[program:long_script]
command=/usr/local/bin/long.sh
autostart=true
autorestart=true
stderr_logfile=/var/log/long.err.log
stdout_logfile=/var/log/long.out.log

并且它绑定到主管。 我想添加 if 检查此脚本以确定它是否由以下人员执行:

  • 主管> 启动 long_script

  • supervisor>重启long_script

我想要这样的东西:

if [ executed by start command ]
then
    echo "start"
else
    echo "restart"
fi

但我不知道 if 子句中应该包含什么。 有可能确定这一点吗? 如果没有,如何为启动和重启命令实现不同的脚本行为? 请帮忙。

【问题讨论】:

  • supervisor>...命令是手动执行的吗?
  • 这在很大程度上取决于 start 和 restart 的作用,以及它们是什么(bash 函数、外部程序)。如果它们是一个 progeam 并产生一个新进程,您应该能够找到它的父进程。

标签: linux bash shell supervisord


【解决方案1】:

在代码中,重新启动和停止/启动之间没有当前区别。在 supervisorctl 调用中重新启动:

self.do_stop(arg)
self.do_start(arg)

虽然有一些关于允许不同信号的讨论,但应用程序中没有“重启”状态。主管已经能够向进程发送不同的信号。 (允许更多地控制重新加载/重启是long standing "gap"

这意味着您至少有两个选择,但使这项工作成功的关键是该进程需要在 shutdown

时记录一些状态

选项 1. 最简单的选项是使用 supervisorctl signal <singal> <process> 而不是调用 supervisorctl restart <process> 并在某处记录发送的信号,以便在启动时读取最后一个信号。

选项 2。 然而,更有趣的解决方案是不要期望任何上游更改,即继续允许使用重新启动并区分停止、崩溃和重新启动

在这种情况下,启动和重新启动之间唯一不同的信息是重新启动应该在旧进程关闭和新进程启动之间的时间要短得多过程。因此,如果在关机时记录了时间戳,那么在启动时,现在和上次关机之间的差异将区分启动和重启

为此,我有一个类似你的定义,但定义了停止信号:

[program:long_script]
command=/usr/local/bin/long.sh
autostart=true
autorestart=true
stderr_logfile=/var/log/long.err.log
stdout_logfile=/var/log/long.out.log
stopsignal=SIGUSR1

通过将来自 supervisord 的停止设为特定信号,您可以区分崩溃和正常停止事件,并且不会干扰正常的终止或中断信号

然后作为 bash 脚本的第一行,我为这个信号设置了一个陷阱:

trap "mkdir -p /var/run/long/; date +%s > /var/run/long/last.stop; exit 0" SIGUSR1

这意味着每次我们从 supervisord 发送停止时,作为纪元的日期将记录在文件 /var/run/long/last.stop 中

然后作为脚本中的下一行,计算最后一站和现在之间的差异

stopdiff=0
if [ -e /var/run/long/last.stop ]; then
    curtime=$(date +%s)
    stoptime=$(cat /var/run/long/last.stop | grep "[0-9]*")
    if [ -n "${stoptime}" ]; then
            stopdiff=$[ ${curtime} - ${stoptime} ]
    fi
else
    stopdiff=9999
fi

stopdiff 现在将包含停止和启动之间的秒数差异,如果停止文件不存在,则为 9999。

这可以用来决定做什么:

if [ ${stopdiff} -gt 2 ]; then
    echo "Start detected (${stopdiff} sec difference)"
elif [ ${stopdiff} -ge 0 ]; then
    echo "Restart detected (${stopdiff} sec difference)"
else
    echo "Error detected (${stopdiff} sec difference)"
fi

您必须选择从发送停止到实际开始脚本实际需要多长时间:这里,我只允许 2 秒,任何更长的时间都被视为“开始”。如果需要以特定方式关闭脚本,则需要在陷阱语句中增加一点复杂性(而不仅仅是exit 0

由于崩溃不应在停止文件中记录任何时间戳,因此如果您还定期在某处记录运行时间戳,您应该能够判断出由于崩溃而正在发生启动。

【讨论】:

    【解决方案2】:

    我了解您的问题。但我不知道主管。请检查这个想法是否有效。

    实例化一个全局字符串变量,并在输入主管命令之前将值放入变量中。在这里,我将您的每个启动和重新启动命令作为两个 bash 程序。

    程序:supervisor_start.sh

    #!/bin/bash
    echo "Starting.."
    supervisor> start long_script
    supervisor_started_command="start" # This is the one
    echo "Started.."
    

    程序:supervisor_restart.sh

    #!/bin/bash
    echo "ReStarting.."
    supervisor> restart long_script
    supervisor_started_command="restart" # This is the one
    echo "ReStarted.."
    

    现在你可以看到“supervisor_started_command”变量中的内容了:)

    #!/bin/bash
    if [ $supervisor_started_command == "start" ]
    then
        echo "start"
    elif [ $supervisor_started_command == "restart" ]
        echo "restart"
    fi
    

    好吧,我不知道这个想法是否适合你..

    【讨论】:

      猜你喜欢
      • 2021-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多