如何在Linux中检查进程是否正在运行

13

我正在尝试自动检测进程是否正在运行,并根据需要执行下一步操作。我曾经编写了一个bash脚本,但似乎它不起作用。

if ps aux | grep [M]yProcessName > /dev/null
then
  echo "Running"
else
  echo "Not running"
fi

我的if语句用错了吗?


你的 if 看起来很好。为什么不运行它并自己找出答案呢?我花了一分钟将 if 复制到文件中并启动它。 - Olaf Dietsche
我已经运行了它,但它没有工作,这就是为什么我问的原因。 - noMAD
抱歉,请关闭此问题。我的错误。 - noMAD
1
@noMAD正是为此而设计的,而且不会生成额外的子shell。 - jordanm
6
作为将来参考,发布一个带有毫无意义的“它不起作用”陈述,并且没有提供关于“它不起作用”是什么意思的信息的问题,会使问题非常糟糕,很可能会损害你的声誉。 - Ken White
显示剩余6条评论
10个回答

11

您不想知道特定进程(已知pid)是否正在运行(可以通过测试/proc/1234/是否存在来实现,其中1234是pid),而是要知道某个进程是否正在运行给定的命令(或给定的可执行文件)。

请注意,kill(2)系统调用可被可移植地用于检查给定进程是否正在运行(使用0信号,例如kill(pid,0))。从程序内部,这是一种常见的方法,用于检查已知pid的进程是否仍然存在和运行(或等待)。

您可以使用pidof命令查找运行某个可执行文件的进程,例如pidof zsh查找所有zsh进程。您还可以使用killall -s 0 zsh

您可能会对pgrep实用程序和/proc文件系统感兴趣。


8
ps aux | grep [M]yProcessName | grep -v grep

请问您能否解释为什么需要三个grep命令? - Amit Kohli
grep -v grep 过滤掉包含 "grep" 的行。这是必要的,因为 ps aux | grep foo 将捕获列出当前运行的所有包含字符串 "foo" 的进程的行,其中包括命令本身!换句话说,您将始终在结果中有一行,无论是否运行 foo 进程。使用 grep -v grep,当没有 foo 进程运行时,您将得到 0 行,并且只会得到与实际 foo 进程相关的行,而不是您的命令。 - 6equj5
1
这个答案是错误的,应该被删除。[M] 已经过滤掉了 grep 进程,因此在这种情况下不需要第二个 grep。模式 [M]yProcessName 只匹配字符串 MyProcessName,而 grep 在进程列表中显示为 grep [M]yProcessName,因此它不匹配也不会被包含。 - Fonic

2

使用-z来检查字符串是否为空,类似这样的代码可以实现:

line=$(ps aux | grep [M]yProcessName)
if [ -z "$line" ]
then
    echo "Not Running"
else
    echo $line > /dev/null
    echo "Rinnung"
fi

他的第一次实现更好。当grep不匹配时,返回非零值,因此不需要测试。在M周围的[]消除了对grep -v grep的需求。 - jordanm

2
有一个解决方案:
if [ "$(ps aux | grep "what you need" | awk '{print $11}')" == "grep" ]; then ... elif [ ... ]; then ... else ... fi

在Debian 6中,这个命令可以正常工作。需要使用'{print $11}',因为系统同样将grep视为一个进程。


-1 这是非常糟糕的新手代码,而且效率低下。它没有解决原帖作者的问题(一开始就不清楚),并且与原始、更优雅和正确的代码相比,也没有提供任何额外的功能。 - tripleee

2
processid =$(ps aux | grep 'ProcessName' | grep -v grep| awk '{print $2}')

上述命令将给出进程ID。将该进程ID分配给一个变量,然后执行以下操作-->
if cat /proc/$processid/status | grep "State:  R (running)" > /dev/null
then
  echo "Running"
else
  echo "Not running"
fi

太晚撤销我的+1了:在搜索状态“R(运行中)”时存在问题,因为通常当进程处于空闲状态时,你认为它在运行的进程实际上会处于“睡眠”状态。 - necromancer
是的。但问题是要检查进程是否正在运行。 可以根据自己的需要扩展上述代码。这只是为了给出一个引导。 - Yogeesh Seralathan

1
SMBD=$(pidof smbd)
if [ "$SMBD" == "" ];
then
   /etc/init.d/samba start;
else
   /etc/init.d/samba restart;
fi

1

只是为了明确提到this answer所暗示的一种方法,pgrep是按进程名称执行此操作的最佳方法:

pgrep [M]yProcessName

如果正在运行的进程名称匹配“[M]yProcessName”,则pgrep将其PID打印到stdout并以代码0退出。否则,它将不打印任何内容并以代码1退出。

0
在我的系统上,ps aux | grep 进程名称 总是会得到一个类似于那个grep进程的行:
edw4rd     9653  0.0  0.0   4388   832 pts/1    S+   21:09   0:00 grep --color=auto ProcessName

所以,退出状态始终为0。也许这就是你的脚本无法工作的原因。


这就是为什么OP的grep使用了一个不匹配自身的正则表达式。 - tripleee

0

返回0代表成功,而其他数字则表示失败。

kill -0 `pid`; echo $?

-1

试一下这个

ps aux | grep [M]yProcessName | grep -v grep

4
在这里写[M]y而不是My使得grep -v grep变得不必要,因为[M]y不会匹配自身。 - zwol
谢谢@Zack :-) 我会开始这样使用它 :-) 我也认为那些[]围绕M是无用的。真是个很棒的解决方法 :-) - anishsane

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接