如果想检查某个进程是否正在运行,如果没有,则启动它。下面的脚本有问题,总是显示进程正在运行。哪里出了问题?
$ ./check_n_run thisisnotrunning
./check_n_run: thisisnotrunning is already running
脚本如下:
$ cat check_n_run
#!/bin/sh
USAGE="usage: $0 processname"
if [ $# -ne 1 ] ; then
echo "$USAGE" >&2
exit 1
fi
ps ax | grep -v grep | grep $1> /dev/null
if [ $? -eq 1 ]
then
echo "$1 not running"
# start here
else
echo "$0: $1 is already running" >&2
fi
exit 0
答案1
脚本中的问题是(使用您正在使用的 shell)在管道中,每个命令都在单独的子 shell 中运行,并且它们的状态都不会传播到父进程。因此command1 | command2
,之后$?
始终为 0。
即使您修复了它,您的脚本也非常不可靠:它会匹配名称中包含您的进程作为子字符串的进程。Linux 提供的命令pidof
可以完全按照您的要求执行操作。
但是这仍然不是理想的,因为可能存在另一个同名进程。最好使用适当的服务管理器,例如 Debian/Ubuntu 的start-stop-daemon
,或 upstart 服务。Wrikkenlockfile
提到的(来自 procmail)也是一种可能性。
答案2
只要 ps / grep 没有出错,$? 就应该是 0。
编辑:根据 Gilles 的说法(我现在没有可用的 shell):
在 ksh/zsh 中,如果 grep 既未找到匹配项也未出错,则 $? 将为 1
我通常倾向于lockfile
在这些进程的启动中使用......
lockfile /path/to/lockfile && (do_something; rm -f /path/to/lockfile)
尽管你的脚本可以更改为:
procs=`ps ax | grep -v grep | grep -c $1`
if [ $procs -lt 1 ]
then
....
答案3
问题:如果你的系统和我的类似,输出ps ax
不仅包括进程名称,还包括用于运行它的整个命令行。因此,当你运行
./check_n_run thisisnotrunning
的输出ps ax
将确实包含该行,因此grep
始终会找到 的结果thisisnotrunning
。这解释了为什么您的脚本总是报告程序正在运行。
为了解决这个问题,有几个选择。正如 Gilles 提到的,最好的方法是使用start-stop-daemon
来启动和停止你的脚本。如果这不可能,你可以使用 来pidof
检测给定的可执行文件是否正在运行。如果由于某种原因不可用,你可以使用
ps -C thisisnotrunning
仅打印具有给定命令名称的进程。
答案4
我认为您尝试了困难的方法。我不知道您使用什么发行版,但请尝试查看路径/var/run
。它是一个包含每个进程的 pid 的目录。
试试看ls *something*
。如果有返回结果,则表示您的进程正在运行。否则则不是。