【发布时间】:2016-03-26 18:35:55
【问题描述】:
我有一个脚本启动器 (bash),它在后台执行 Python 脚本,所以我可以启动它,然后关闭终端/ssh 连接,让脚本继续工作。
它接受要运行的脚本的名称和传递的可选参数。然后它启动 Python 脚本(已分离)并在同一目录中创建一个带有(Python 脚本的)PID 的文件,因此我稍后可以重新连接到服务器并使用该文件中的 PID 终止该后台进程。
此外,此 PID 文件用于防止相同的脚本在已经运行(单例)时被启动。
问题是我不知道在 Python 脚本完成工作后如何删除这个 PID 文件。我需要在 bash 脚本中实现它,没有 Python 解决方案(因为我想在所有情况下都使用它)或 screen 工具。这个主管(将在脚本完成工作后删除 PID 文件)也应该在后台运行(!),所以我可以做同样的事情:关闭终端会话。
到目前为止我已经尝试过:
#!/bin/bash
PIDFILE=$1.pid
if [ -f $PIDFILE ]; then
echo "Process is already running, PID: $(< $PIDFILE)"
exit 1
else
nohup python $1 "${@:2}" > /dev/null 2>&1 &
PID=$!
echo $PID > $PIDFILE
# supervisor
nohup sh -c "wait $PID; rm -f $PIDFILE" > /dev/null 2>&1 &
fi
在这个例子中 PID 文件被立即删除,因为 wait 命令立即返回(我认为这是因为新进程不是当前进程的子进程,所以 wait strong> 在这种情况下不起作用)。
您对如何实现它有任何想法吗? 基本上,我需要一些东西来替换这条线
nohup sh -c "wait $PID; rm -f $PIDFILE" > /dev/null 2>&1 &
这将等到前一个脚本(在本例中为 Python)完成其工作,然后删除 PID 文件。
UPD:好的,问题出在 wait 命令上,因为它不能等待非子进程。可行的解决方案是用 while 循环替换它:
#!/bin/bash
function cleanup {
while [ -e /proc/$1 ]; do
sleep 1;
done
rm -f $PIDFILE
}
PIDFILE=$1.pid
if [ -f $PIDFILE ]; then
echo "Process is already running, PID: $(< $PIDFILE)"
exit 1
else
python $1 "${@:2}" > /dev/null 2>&1 &
PID=$!
echo $PID > $PIDFILE
cleanup $PID > /dev/null 2>&1 &
disown
fi
【问题讨论】: