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

时间:2012-02-02 18:05:28

标签: linux bash shell unix process

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

15 个答案:

答案 0 :(得分:160)

虽然pidofpgrep是确定正在运行的内容的绝佳工具,但遗憾的是,它们在某些操作系统上都不可用。明确的失败保障是使用以下内容: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

此外,如果您想要PID列表,您也可以轻松地查找这些内容:

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

Linux和OS X上的输出相同:

3519 3521 3523 3524

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

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

这种方法适用于编写简单的空字符串测试,甚至可以迭代已发现的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

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

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

警告!!!

请记住,您只是解析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

答案 1 :(得分: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必须退出&gt; 0,但我不清楚是什么构成了“错误”。因此,虽然我非常确定它在所有Unix / Linux平台上都能正常运行,但我并不是在使用该策略。

答案 2 :(得分:13)

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

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

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

$ pidof bash remmina
6148 6147 6144 5603 21598

在其他Unices上,pgreppsgrep的组合将实现同样的目标,正如其他人正确指出的那样。

答案 3 :(得分:6)

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

PATH=/usr/ucb:${PATH} ps aux | grep httpd | grep -v grep

经过测试:

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

答案 4 :(得分: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

如果您的命令有一些命令参数,那么您还可以在'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

答案 5 :(得分:5)

只是一个小小的补充:如果你向ps添加-c标志,那么之后你不需要删除包含grep进程的行grep -v。即。

ps acux | grep cron

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

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

ps -e |grep cron

ps -el |grep cron 

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

答案 6 :(得分:5)

将各种建议放在一起,我能够提出的最干净的版本(没有不可靠的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"

答案 7 :(得分:3)

我使用pgrep -l httpd但不确定它是否存在于任何平台上...
谁可以在OSX上确认?

答案 8 :(得分:1)

您应该知道您的过程的PID。

启动时,其PID将记录在$!变量中。将此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的{​​{3}}。知道给定PID是否正在运行的技巧在ps -o pid= -p $PID指令中。

答案 9 :(得分:0)

这种方法可用于命令'ps','pidof'和rest不可用的情况。 我个人经常在我的工具/脚本/程序中使用procfs。

   egrep -m1  "mysqld$|httpd$" /proc/[0-9]*/status | cut -d'/' -f3

很少解释发生了什么:

  1. -m1 - 第一场比赛停止进程
  2. “mysqld $ | httpd $” - grep将匹配以mysqld或httpd
  3. 结尾的行
  4. / proc / [0-9] * - bash将匹配以任意数字开头的行
  5. cut - 只需通过分隔符'/'拆分输出并提取字段3

答案 10 :(得分:0)

这将打印其basename为“chromium-browser”的进程数:

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”,则进程未运行。该命令假定进程路径不包含中断空间。我没有使用暂停进程或僵尸进程对此进行测试。

使用gwak作为Linux中的awk替代方案进行测试。

这是一个更通用的解决方案,有一些示例用法:

#!/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"

答案 11 :(得分:0)

这是我的版本。特性:

  • 检查确切的程序名称(函数的第一个参数)。搜索&#34; mysql&#34;将无法匹配&#34; mysqld&#34;
  • 搜索程序参数(函数的第二个参数)

脚本:

#!/bin/bash

# $1 - cmd
# $2 - args
# return: 0 - no error, running; 1 - error, not running
function isRunning() {
    for i in $(pidof $1); do
        cat /proc/$i/cmdline | tr '\000' ' ' | grep -F -e "$2" 1>&2> /dev/null
        if [ $? -eq 0 ]; then
            return 0
        fi
    done
    return 1
}

isRunning java "-Djava.util.logging.config.file=logging.properties"
if [ $? -ne 0 ]; then
    echo "not running, starting..."
fi

答案 12 :(得分:0)

没有一个答案对我有用,所以这是我的:

process="$(pidof YOURPROCESSHERE|tr -d '\n')"
if [[ -z "${process// }" ]]; then
  echo "Process is not running."
else
  echo "Process is running."
fi

说明:

|tr -d '\n'

这将删除由终端创建的回车符。其余内容可以通过this帖子进行解释。

答案 13 :(得分:0)

[ $pid ] && [ -d /proc/$pid ] && command 如果您知道 pid

答案 14 :(得分:-1)

以下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]”命令名时阻塞,并且也无法识别名称中包含嵌入空格的进程。

另请注意,最受欢迎且最受欢迎的解决方案需要非可移植的ps选项,并且无偿地使用shell,尽管它很受欢迎,但并不保证在每台Unix / Linux计算机上都存在(bash