Linux / Unix命令来确定进程是否正在运行?
我需要一个独立于平台的(Linux / Unix | OSX)shell / bash命令来确定特定进程是否正在运行。 例如mysqld
, httpd
…什么是最简单的方法/命令来做到这一点?
虽然pidof
和pgrep
是确定正在运行的很好的工具,但是在某些操作系统上,它们都是不可用的。 一个确定的故障安全将是使用以下: ps cax | grep command
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都会返回一个退出代码,所以很容易检查是否find进程:
#!/bin/bash ps cax | grep httpd > /dev/null if [ $? -eq 0 ]; then echo "Process is running." else echo "Process is not running." fi
而且,如果你想要PID的列表,你也可以很容易地理解这些:
ps cax | grep httpd | grep -o'^ [] * [0-9] *'
在Linux和OS X上,其输出是相同的:
3519 3521 3523 3524
下面的输出是一个空string,使得这个方法对于没有运行的进程是安全的:
回声ps cax | grep aasdfasdf | grep -o '^[ ]*[0-9]*'
ps cax | grep aasdfasdf | grep -o '^[ ]*[0-9]*'
这种方法适用于编写简单的空stringtesting,然后遍历发现的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
您可以通过将其保存到具有执行许可权的文件(命名为“running”)(chmod + x running)并使用参数执行它进行testing: ./running "httpd"
#!/bin/bash ps cax | grep httpd if [ $? -eq 0 ]; then echo "Process is running." else echo "Process is not running." fi
警告!!!
请记住,您只是parsingps ax
的输出,这意味着,如在Linux输出中所看到的,它不是简单地匹配进程,而是传递给该程序的参数。 我强烈build议使用这种方法尽可能具体(例如./running "mysql"
也将匹配'mysqld'进程)。 我强烈build议在可能的情况下使用which
检查完整path。
参考文献:
你应该知道PID!
通过尝试对进程参数(如pgrep "mysqld"
)进行某种模式识别来寻找进程是一种注定迟早会失败的策略。 如果你有两个mysqld运行? 忘记这个办法。 你可能暂时得到它,它可能会工作一年或两年,但然后发生了一些事情,你没有想过。
只有进程ID(PID)是真正独特的。
当您在后台启动某些内容时,请始终存储该pid。 在Bash中,这可以用$!
来完成 Bashvariables。 你这样做可以省去很多麻烦。
如何确定进程是否正在运行(通过pid)
所以现在问题变成如何知道一个PID是否正在运行。
简单地做:
ps -o pid = -p <pid>
这是POSIX,因此是便携式的。 如果进程正在运行,它将返回pid本身,如果进程没有运行,它将返回任何内容。 严格地说,命令会返回一个单独的列,即pid
,但是由于我们已经给出了一个空的标题头(等号之前的东西),这是唯一请求的列,所以ps命令根本不会使用头。 这是我们想要的,因为它使parsing更容易。
这将在Linux,BSD,Solaris等上运行
另一个策略是testing上面ps
命令的退出值。 如果进程正在运行,它应该是零,如果不是,则应该是非零。 POSIX规范说,如果出现错误, ps
必须退出> 0,但是我不清楚什么是“错误”。 所以我不是亲自使用这个策略,虽然我很确定它在所有Unix / Linux平台上都能正常工作。
在大多数Linux发行版上,可以使用pidof
(8)。
它将打印指定进程的所有正在运行的实例的进程标识符,如果没有实例正在运行,则不显示任何内容。
例如,在我的系统上(我有四个bash
实例和一个remmina
运行实例):
$ pidof bash remmina 6148 6147 6144 5603 21598
在其他Unices上, pgrep
或者ps
和grep
的组合可以达到同样的效果,正如其他人正确地指出的那样。
只是一个小的增加:如果你添加-c
标志到ps,你不需要用grep -v
去除包含grep进程的行。 即
ps acux | grep cron
是您在bsd-ish系统(包括MacOSX)上所需的全部input。如果您需要较less的信息,则可以将-u
离开。
在本地ps
命令的遗传学指向SysV的系统上,您可以使用
ps -e |grep cron
要么
ps -el |grep cron
对于包含不仅仅是pid和进程名称的列表。 当然,您可以使用-o <field,field,...>
选项来select要打印的特定字段。
这应该适用于大多数Unix,BSD和Linux:
PATH=/usr/ucb:${PATH} ps aux | grep httpd | grep -v grep
testing:
- 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
最简单的方法是使用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
如果你的命令有一些命令参数,那么你也可以在'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
把各种各样的build议放在一起,我能够想到的最干净的版本(没有不可靠的grep,触发部分文字)是:
kill -0 $(pidof mysql) 2> /dev/null || echo "Mysql ain't runnin' message/actions"
kill -0不会终止进程,而是检查它是否存在,然后返回true,如果您的系统上没有pidof,请在启动进程时存储pid:
$ mysql & $ echo $! > pid_stored
那么在脚本中:
kill -0 $(cat pid_stored) 2> /dev/null || echo "Mysql ain't runnin' message/actions"
我使用pgrep -l httpd
但不确定它是否存在于任何平台上…
谁可以在OSX上确认?
你应该知道你的过程的PID。
当你启动它时,它的PID将被logging在$!
variables。 将这个PID保存到一个文件中。
那么你将需要检查这个PID是否对应一个正在运行的进程。 这是一个完整的框架脚本:
FILE="/tmp/myapp.pid" if [ -f $FILE ]; then PID=$(cat $FILE) else PID=1 fi ps -o pid= -p $PID if [ $? -eq 0 ]; then echo "Process already running." else echo "Starting process." run_my_app & echo $! > $FILE fi
基于peterh
的答案 。 知道给定PID是否运行的技巧是在ps -o pid= -p $PID
指令中。
这种方法可用于命令'ps','pidof'和rest不可用的情况。 我个人在我的工具/脚本/程序中经常使用procfs。
egrep -m1 "mysqld$|httpd$" /proc/[0-9]*/status | cut -d'/' -f3
小解释发生了什么事情:
- -m1 – 第一场比赛停止进程
- “mysqld $ | httpd $” – grep将匹配以mysqld或httpd结尾的行
- / proc / [0-9] * – bash将匹配以任何数字开头的行
- 剪切 – 只是通过分隔符“/”分割输出,并提取字段3
这将打印基本名称为“铬浏览器”的进程数量:
ps -e -o args= | awk 'BEGIN{c=0}{ if(!match($1,/^\[.*\]$/)){sub(".*/","",$1)} # Do not strip process names enclosed by square brackets. if($1==cmd){c++} }END{print c}' cmd="chromium-browser"
如果这打印“0”,进程不运行。 该命令假定进程path不包含中断空间。 我没有testing过这个暂停进程或僵尸进程。
在Linux中使用gwak
作为awk
替代方法进行testing。
以下是一些用途较为全面的解决scheme:
#!/bin/sh isProcessRunning() { if [ "${1-}" = "-q" ]; then local quiet=1; shift else local quiet=0; fi ps -e -o pid,args= | awk 'BEGIN{status=1}{ name=$2 if(name !~ /^\[.*\]$/){sub(".*/","",name)} # strip dirname, if process name is not enclosed by square brackets. if(name==cmd){status=0; if(q){exit}else{print $0}} }END{exit status}' cmd="$1" q=$quiet } process='chromium-browser' printf "Process \"${process}\" is " if isProcessRunning -q "$process" then printf "running.\n" else printf "not running.\n"; fi printf "Listing of matching processes (PID and process name with command line arguments):\n" isProcessRunning "$process"
下面的shell函数,只是基于POSIX标准的命令和选项,应该在Unix和linux系统上的大多数(如果没有的话)工作。 :
isPidRunning() { cmd=` PATH=\`getconf PATH\` export PATH ps -e -o pid= -o comm= | awk '$2 ~ "^.*/'"$1"'$" || $2 ~ "^'"$1"'$" {print $1,$2}' ` [ -n "$cmd" ] && printf "%s is running\n%s\n\n" "$1" "$cmd" || printf "%s is not running\n\n" $1 [ -n "$cmd" ] }
$ isPidRunning httpd httpd is running 586 /usr/apache/bin/httpd 588 /usr/apache/bin/httpd $ isPidRunning ksh ksh is running 5230 ksh $ isPidRunning bash bash is not running
请注意,当传递可疑的“0”命令名称时它会窒息,并且也将无法识别其名称中具有embedded空间的进程。
还要注意,最有利的和被接受的解决scheme要求不可移植的ps
选项,并无偿地使用一个shell,尽pipe它受欢迎,但不能保证在每个Unix / Linux机器( bash
)