我必须修复一个bash启动/停止脚本,但我对bash不是很了解。
脚本就像这样开始
name='basename $0'
pid_file="/home/$name.pid"
dir="/home/somedir"
user="someuser"
cmd="somecmd"
get_pid() {
cat "$pid_file"
}
is_running() {
[ -f "$pid_file" ] && ps `get_pid` > /dev/null 2>&1
}
case "$1" in
start)
if is_running; then
echo "Already started"
else
echo "Starting $name"
cd $dir
sudo -u "$user" $cmd >> "$stdout_log" 2>> "$dtderr_log" &
echo $! > "$pid_file"
if ! is_running; then
echo "Unable to start, see $stdout_log" 2>> "$stderr_log" &
exit 1
fi
fi
is_running()如何运作?它似乎返回一个布尔值,但我不理解逻辑。 sudo命令正确启动进程,但它总是报告它无法启动,因为is_running为false
答案 0 :(得分:2)
正如约翰库格曼指出的那样,你可以从他的链接中得到一些暗示,尽管不是一切。函数is_running中的逻辑很简单,首先检查具有进程id(pid)的文件是否存在:
[ -f "$pid_file" ]
如果确实存在,则返回0,否则返回1。和&&然后检查前一个命令是否成功(返回0)并执行&&当且仅当前一个命令返回0.下一个命令:
ps 'get_pid'
使用函数get_pid(文件中的文本)列出使用pid运行的进程。如果使用提供的pid的进程正在运行,则此命令的计算结果为0;如果没有,则此计算结果为1。功能的最后一部分:
> /dev/null 2>&1
重定向命令ps' get_pid'的输出。 to null和终端的任何错误(标准输出)。
总之,如果存储pid的文件,则is_running将返回0(如true),并且此文件中的pid是ps所见的当前正在运行的进程。
答案 1 :(得分:2)
实际上你想知道三件事:1。如果给定的PID正在运行,2。如果它是你的进程,3。如果它是正确的程序。请使用-s
获取非空文件。
is_running() {
[ -s "$pid_file" ] && kill -0 $(< $pid_file)
}
kill -0检查,如果进程正在运行且是否是您的进程。
$ kill -0 $$ # checking for the current bash - this should always work
$ kill -0 12345 # this process does not exist
bash: kill: (12345) - No such process
$
另一种选择是pgrep,这将涵盖所有三件事。请使用-s
获取非空文件。
is_running() {
[ -s "$pid_file" ] && pgrep -U "$user" -fl "$cmd" -P $(< $pid_file)
}
如果你开始一个新的过程,最好使用像这样的包装器
#!/bin/bash
echo $$ > pidfile
exec process
魔术#!启动bash,bash知道自己的PID,并将此PID写入文件。 现在exec用新的替换bash进程 - 这样,进程id(PID)保持不变!
改进了变体pidstarter.bash
#!/bin/bash
echo $$ > "$1"
shift
exec "$@"
现在这个开始新进程,第一个参数是pidfile。
所以不是这两行
sudo -u "$user" $cmd >> "$stdout_log" 2>> "$dtderr_log" &
echo $! > "$pid_file"
我会用
sudo -u "$user" pidstarter.bash "$pid_file" $cmd &
sleep 1 # let there enough time to start bash and write pidfile