Linux/Unix命令确定进程是否正在运行?

Hig*_*ife 93 unix linux bash shell process

我需要一个独立于平台(Linux/Unix | OSX)的shell/bash命令来确定特定进程是否正在运行.例如mysqld,httpd...最简单的方法/命令是什么?

Cal*_*ray 165

虽然pidof并且pgrep是用于确定正在运行的内容的绝佳工具,但遗憾的是,它们在某些操作系统上都不可用.明确的失败保障是使用以下内容:ps cax | grep command

Gentoo Linux上的输出:

14484 ?        S      0:00 apache2
14667 ?        S      0:00 apache2
19620 ?        Sl     0:00 apache2
21132 ?        Ss     0:04 apache2

OS X上的输出:

42582   ??  Z      0:00.00 (smbclient)
46529   ??  Z      0:00.00 (smbclient)
46539   ??  Z      0:00.00 (smbclient)
46547   ??  Z      0:00.00 (smbclient)
46586   ??  Z      0:00.00 (smbclient)
46594   ??  Z      0:00.00 (smbclient)

在Linux和OS X上,grep都会返回退出代码,因此很容易检查是否找到了进程:

#!/bin/bash
ps cax | grep httpd > /dev/null
if [ $? -eq 0 ]; then
  echo "Process is running."
else
  echo "Process is not running."
fi
Run Code Online (Sandbox Code Playgroud)

此外,如果您想要PID列表,您也可以轻松地为这些列表进行grep:

ps cax | grep httpd | grep -o '^[ ]*[0-9]*'

Linux和OS X上的输出相同:

3519 3521 3523 3524

以下输出为空字符串,使此方法对于未运行的进程安全:

echo ps cax | grep aasdfasdf | grep -o '^[ ]*[0-9]*'
Run Code Online (Sandbox Code Playgroud)

这种方法适用于编写简单的空字符串测试,甚至可以迭代已发现的PID.

#!/bin/bash
PROCESS=$1
PIDS=`ps cax | grep $PROCESS | grep -o '^[ ]*[0-9]*'`
if [ -z "$PIDS" ]; then
  echo "Process not running." 1>&2
  exit 1
else
  for PID in $PIDS; do
    echo $PID
  done
fi
Run Code Online (Sandbox Code Playgroud)

您可以通过将其保存到具有执行权限(chmod + x running)的文件(名为"running")并使用参数执行它来测试它: ./running "httpd"

#!/bin/bash
ps cax | grep httpd
if [ $? -eq 0 ]; then
  echo "Process is running."
else
  echo "Process is not running."
fi
Run Code Online (Sandbox Code Playgroud)

警告!!!

请记住,您只是解析其输出,ps ax这意味着,如Linux输出中所示,它不仅仅是对进程匹配,而且还是传递给该程序的参数.我强烈建议在使用此方法时尽可能具体(例如,./running "mysql"也将匹配'mysqld'进程).我强烈建议which尽可能使用完整路径进行检查.


参考文献:

http://linux.about.com/od/commands/l/blcmdl1_ps.htm

http://linux.about.com/od/commands/l/blcmdl1_grep.htm

  • `grep`也会发现自己正在运行(例如`ps cax | grep randomname`将始终返回0,因为`grep`找到`grep randomname`(希望这很清楚......).一个修复是在第一个周围添加方括号进程名称的字母,例如`ps cax | grep [r] andomname`. (6认同)
  • 啊! 优秀的grep退出代码使用. (2认同)
  • 对不起,虽然答案肯定是从语义的角度来看,但我完全反对尝试通过进程arg向量上的模式匹配来查找进程.任何这样的方法迟早都注定要失败(你实际上自己承认,需要更多的检查).我在一个单独的答案中添加了我自己的建议. (2认同)

pet*_*erh 24

你应该知道PID!

通过尝试对流程参数(如pgrep "mysqld")进行某种模式识别来查找流程是一种注定要迟早失败的策略.如果你有两个mysqld运行怎么办?忘记这种方法.你可以暂时把它弄好,它可能会工作一两年,但之后会发生一些你没想过的事情.

只有进程ID(pid)才是真正独特的.

在后台启动时始终存储pid.在Bash中,这可以使用$!Bash变量完成.这样做会让你自己省下很多麻烦.

如何确定进程是否正在运行(通过pid)

所以现在问题就变成了如何知道pid是否正在运行.

简单地说:

ps -o pid= -p <pid>

这是POSIX,因此是便携式的.如果进程正在运行,它将返回pid本身,如果进程未运行,则返回任何内容.严格地说该命令将返回一列,在pid,但由于我们考虑到一个空标题头(东东紧接等号),这是要求再ps命令不会用头在所有的唯一列.这是我们想要的,因为它使解析更容易.

这适用于Linux,BSD,Solaris等.

另一种策略是测试上述ps命令的退出值.如果进程正在运行,它应该为零,如果不是,则应为非零.POSIX规范说ps如果发生错误必须退出> 0,但我不清楚是什么构成了"错误".因此我并不是个人使用该策略,尽管我很确定它在所有Unix/Linux平台上都能正常工作.

  • 错误.我的评论的全部意义是退一步说,如果你第一次发现自己处于某种形式的`grep <sometext>`以找到一个给定的过程然后你做错了什么的时候你开始这个过程,恕我直言.我从OP的问题中得出结论,他确实控制了这个过程是如何开始的. (2认同)
  • OP 问题更正确的“术语”应该是“确定服务是否正在运行的跨平台命令”,它不是运行检查的同一系统,而是外部系统,因此 PID 不会是完全知道。 (2认同)
  • 这不是万无一失的。您感兴趣的进程可能在系统运行了足够长的时间以使PID能够绕回之后就死掉了,然后又可能为另一个进程分配了您要检查的相同PID。http://stackoverflow.com/questions/11323410/linux-pid-recycling (2认同)

Fré*_*idi 14

在大多数Linux发行版中,您可以使用pidof(8).

它将打印指定进程的所有正在运行的实例的进程ID,如果没有实例正在运行,则不会打印任何内容.

例如,在我的系统上(我有四个实例bash和一个remmina运行实例):

$ pidof bash remmina
6148 6147 6144 5603 21598
Run Code Online (Sandbox Code Playgroud)

在其他Unices上,pgrep或者其他人已经正确指出的ps并且grep将会实现同样的事情.


Joh*_*web 7

这应该适用于大多数Unix,BSD和Linux:

PATH=/usr/ucb:${PATH} ps aux | grep httpd | grep -v grep
Run Code Online (Sandbox Code Playgroud)

测试:

  • SunOS 5.10 [因此PATH=...]
  • Linux 2.6.32(CentOS)
  • Linux 3.0.0(Ubuntu)
  • 达尔文11.2.0
  • FreeBSD 9.0-STABLE
  • 红帽企业Linux ES版本4
  • 红帽企业Linux服务器版本5

  • +1是简单的`ps`.为了避免第二个'grep`,我建议:`ps aux | grep [h] ttpd` (2认同)

小智 6

最简单的方法是使用ps和grep:

command="httpd"
running=`ps ax | grep -v grep | grep $command | wc -l`
if [ running -gt 0 ]; then
    echo "Command is running"
else
    echo "Command is not running"
fi
Run Code Online (Sandbox Code Playgroud)

如果您的命令有一些命令参数,那么您还可以在'grep $ command'之后添加更多'grep cmd_arg1'来过滤掉您不感兴趣的其他可能进程.

示例:显示是否有任何带有提供参数的java进程:

-Djava.util.logging.config.file = logging.properties

在跑

ps ax | grep -v grep | grep java | grep java.util.logging.config.file=logging.properties | wc -l
Run Code Online (Sandbox Code Playgroud)

  • 实际上,使用`ps cax`消除了使用`grep -v`的需要.例如,您可以使用:`ps cax | grep java>/dev/null || echo"Java not running"`. (2认同)
  • 第3行有一个错误。请将“正在运行”更改为“$正在运行”。 (2认同)

Tat*_*ser 5

只是一个小小的补充:如果你将-c标志添加到ps,你不需要删除包含grep进程的行grep -v.即

ps acux | grep cron
Run Code Online (Sandbox Code Playgroud)

是bsd-ish系统所需的所有打字(包括MacOSX)-u如果您需要更少的信息,可以离开.

在本机ps命令的遗传学指向SysV的系统上,您将使用

ps -e |grep cron
Run Code Online (Sandbox Code Playgroud)

要么

ps -el |grep cron 
Run Code Online (Sandbox Code Playgroud)

对于包含不仅仅是pid和进程名称的列表.当然,您可以使用该-o <field,field,...>选项选择要打印的特定字段.


gle*_*her 5

将各种建议放在一起,我能够提出的最干净的版本(没有不可靠的grep触发部分单词)是:

kill -0 $(pidof mysql) 2> /dev/null || echo "Mysql ain't runnin' message/actions"
Run Code Online (Sandbox Code Playgroud)

kill -0不会终止进程但会检查它是否存在然后返回true,如果你的系统上没有pidof,则在启动进程时存储pid:

$ mysql &
$ echo $! > pid_stored
Run Code Online (Sandbox Code Playgroud)

然后在脚本中:

kill -0 $(cat pid_stored) 2> /dev/null || echo "Mysql ain't runnin' message/actions"
Run Code Online (Sandbox Code Playgroud)