注意:这个问题通常适用于 Linux 以及当前版本的 Ubuntu(而不仅仅是某些人评论说的不受支持的旧版本)
在部署新代码时,我们使用 pkill 来检查程序是否正在运行,以便在重新启动之前将其终止。
pkill --signal 15 --pidfile programname.pid
这通常有效,但是当出现问题并且应用程序挂起时,信号 15 不会终止该进程。 pkill 的退出代码为:
EXIT STATUS
0 One or more processes matched the criteria. For pkill and pidwait, one or more processes must also have been successfully signalled or waited for.
1 No processes matched or none of them could be signalled.
2 Syntax error in the command line.
3 Fatal error: out of memory etc.
出于显而易见的原因,经过一番思考,我发现它无法返回代码来表明进程终止成功,因为 pkill 只向它发送了一个信号,仅此而已。因此,我必须检查进程是否已终止,如果没有终止,则再次尝试信号 9,如果尚未终止,则尝试信号 6(或其他信号)。
因此,我想做一些 if/elif/else/fi 来测试这一点就足够了:
#!/bin/bash
pkill --signal 15 --pidfile programname.pid
result1=$?
echo 'result1 is ' $result1
if [ "$result1" -eq 0 ]
then
echo "programname found running"
pgrep --pidfile programname.pid
result2=$?
if [ "$result2" -eq 1 ]
then
# happens if pid# is not found
echo "programname killed successfully with signal 15"
# restart the program that was killed
else
pkill --signal 9 --pidfile programname.pid
result3=$?
if [ "result3" -eq 0 ]
then
pgrep --pidfile programname.pid
result4=$?
if [ "result4" -eq 1 ]
then
echo "programname killed successfully with signal 9"
# restart the pgram that was killed
fi
fi
fi
elif [ $result1 -eq 1 ]
then
echo "programname pid# not found. Is the system running?"
else
echo "pkill exited with error" $result1
fi
echo 'Continue...'
这一切似乎有点复杂,还是我只是在吹毛求疵?有没有更好的方法在脚本中实现此结果?
答案1
我认为创建一个函数来执行此操作是更好的选择。此外,使用 for 循环似乎是一个更简洁的解决方案:
#!/bin/bash
trykill () {
timeout=${2:-5}
# echo "wait =" $timeout
# Run the loop for signal 15, 9 and 6
for n in 15 9 6;
do
if [[ -f "$1.pid" ]]; then
pkill --signal $n --pidfile $1.pid
result1=$?
else
result1=1
fi
#echo 'result1 is ' $result1
if [ "$result1" -eq 0 ]
then
echo $1 "found running, waiting" $timeout "seconds for process to die."
sleep $timeout # Wait # seconds set by second parameter
pgrep --pidfile $1.pid
result2=$?
if [ "$result2" -eq 1 ]
then
# happens if pid# is not found
echo $1 "killed successfully with signal" $n"."
return 0
fi
elif [ $result1 -eq 1 ]
then
echo $1".pid # not found." $1 "doesn't seem to be running. Starting it anyway."
return 0
else
echo "pkill exited with error" $result1
return 1
fi
done
}
我为每个要重启的服务调用该函数。下面是执行此操作的示例脚本。
#!/bin/bash
source trykill.sh
trykill $1
result1=$?
#echo 'result1 is ' $result1
if [ "$result1" -eq 0 ]
then
echo 'Start' $1 'again'
fi
echo 'Done.'