如何检查/启动进程|shell 脚本中的错误

如何检查/启动进程|shell 脚本中的错误

如果想检查某个进程是否正在运行,如果没有,则启动它。下面的脚本有问题,总是显示进程正在运行。哪里出了问题?

$ ./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*。如果有返回结果,则表示您的进程正在运行。否则则不是。

相关内容