使用单个 shell 脚本防止多个 python 脚本崩溃?

使用单个 shell 脚本防止多个 python 脚本崩溃?

我想创建一个 shell 脚本来防止 python 脚本在 Raspberry Pi 中崩溃。这个 python 脚本在重新启动时自动启动,但是,有时它会在运行时崩溃。

目前我的 shell 脚本如下:

#!/bin/sh

COMMAND='python home/pi/projects/mypythonscript.py'
LOGFILE=restart.txt

writelog() {
  now=`date`
  echo "$now $*" >> $LOGFILE
}

writelog "Starting"
while true ; do
  $COMMAND
  writelog "Exited with status $?"
  writelog "Restarting"
done

我想问我是否可以创建两个命令行,以确保可以防止两个独立的脚本使用这个shell脚本崩溃?或者我是否必须为第二个 python 脚本创建一个新的 shell 脚本文件?

我正在考虑这样修改:

#!/bin/sh

COMMAND1='python home/pi/projects/mypythonscript1.py'
COMMAND2='python home/pi/projects/mypythonscript2.py'
LOGFILE=restart.txt

writelog() {
  now=`date`
  echo "$now $*" >> $LOGFILE
}

writelog "Starting"
while true ; do
  $COMMAND1
  $COMMAND2
  writelog "Exited with status $?"
  writelog "Restarting"
  done

这个修改会起作用吗?我很感激任何建议,因为我对 Linux(debian)平台还很陌生。

答案1

如果您使用 systemd,您可以为每个命令创建一个服务,然后让 systemd 在崩溃时重新启动它。

就像是:

[Unit]
Description='description of script'

[Service]
ExecStart=/path/too/script
Restart=always

[Install]
WantedBy=multi-user.target

然后可以将其放入/etc/systemd/system,运行后就systemctl daemon-reload可以启动服务了。它也会在重新启动后启动。

答案2

如果您想从一个控制脚本处理任意数量的异步进程,可以使用以下方法:

#!/bin/sh
COMMAND1=(python home/pi/projects/mypythonscript1.py)
COMMAND2=(python home/pi/projects/mypythonscript2.py)
rm -f COMMAND1_failed; ("${COMMAND1[@]}"; touch COMMAND1_failed)&
rm -f COMMAND2_failed; ("${COMMAND2[@]}"; touch COMMAND2_failed)&
while true
do
        if [ -e COMMAND1_failed ]
        then
                # Restart Command1
                rm -f COMMAND1_failed; ("${COMMAND1[@]}"; touch COMMAND1_failed)&
        fi
        if [ -e COMMAND2_failed ]
        then
                # Restart Command2
                rm -f COMMAND2_failed; ("${COMMAND2[@]}"; touch COMMAND2_failed)&
        fi
        sleep 60
done
  • COMMAND1=(python home/pi/projects/mypythonscript1.py) 定义COMMAND1为一个数组。这允许命令包含包含空格的单词;例如,类似的东西 COMMAND1=(python "home/pi/projects/my python script1.py")
  • "${COMMAND1[@]}"类似于您使用$COMMAND1;它运行您的第一个命令,并引用其组成词。
  • (commandA; commandB) 本质上创建一个临时的两行脚本:
    命令A
    命令B
    所以("${COMMAND1[@]}"; touch COMMAND1_failed)说“运行命令 #1,等待它完成,然后触摸(创建)一个名为COMMAND1_failed.整个迷你脚本在后台运行,因此主脚本可以继续运行命令 #2,等等。
  • 实际上,您可能应该使用failed文件的完整路径名,并且可能将它们的名称放入变量中。
  • 启动所有后台作业后,主脚本进入无限(永远)循环。如果该COMMAND1_failed文件存在,则意味着命令 #1 需要重新启动。 ETC。
  • sleep根据需要调整。值太低,控制脚本可能会频繁运行,从而影响系统的性能。值太高,异步任务将无法及时重新启动,因此系统的响应能力会受到影响。

上面启动了所有进程,然后进入无限循环。这是一个简单的优化:

#!/bin/sh
touch COMMAND1_failed
while true
do
        if [ -e COMMAND1_failed ]
        then
                # (Re)start Command1
                rm -f COMMAND1_failed; ("${COMMAND1[@]}"; touch COMMAND1_failed)&
        fi
        sleep 60
done

在创建所有必要的文件以使其看起来需要(重新)启动进程之后,它会在循环的第一次迭代时启动后台进程。唯一的区别是它列出了启动进程一次而不是两次的命令。COMMANDn_failed

也可以看看:

相关内容