【问题标题】:Linux/Unix command to determine if process is running?Linux / Unix命令确定进程是否正在运行?
【发布时间】:2012-02-25 09:54:54
【问题描述】:

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

【问题讨论】:

    标签: linux bash shell unix process


    【解决方案1】:

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

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

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

    $ pidof bash remmina
    6148 6147 6144 5603 21598
    

    在其他 Unices 上,pgreppsgrep 的组合将达到同样的效果,正如其他人正确指出的那样。

    【讨论】:

    • +1 pidof httpd 在 Red Hat 5 上运行良好。但在我的 Red Hat 4 上,pidof 不存在 :-(
    • 确实,这个命令没有我想象的那么普遍,我编辑了我的答案以使其更清楚。
    • 确实很干净。 (在支持的系统上)。谢谢。
    【解决方案2】:

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

    【讨论】:

    • 谢谢@Johnsyweb。你也可以检查pidof吗?好的,你做到了。谢谢你。所以我们应该在 OSX 上找到其他工作......你的基本 ps|grep 可能是唯一的解决方案;-)
    【解决方案3】:

    这应该适用于大多数版本的 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
    • 红帽企业 Linux ES 第 4 版
    • 红帽企业 Linux 服务器第 5 版

    【讨论】:

    • +1 是的,只需ps。为了避免第二个grep,我建议:ps aux | grep [h]ttpd
    • 我没有在这里使用方括号技巧,以便更容易将变量放入主 grep
    • 好吧 ;) 我刚刚在 Red Hat AS 4 和 Red Hat AP 5 上进行了测试。我当然可以!因此,您可以在列表中添加:Red Hat Enterprise Linux ES 版本 4Red Hat Enterprise Linux Server 版本 5。干杯
    • @Downvoter:为什么?我错过了什么?据我所知,接受的答案是做同样的查找!
    【解决方案4】:

    虽然pidofpgrep 是确定正在运行的内容的绝佳工具,但遗憾的是,它们在某些操作系统上均不可用。一个明确的故障保险是使用以下内容:ps cax | grep command

    Gentoo Linux 上的输出:

    14484 ? S 0:00 阿帕奇2 14667 ? S 0:00 阿帕奇2 19620 ? SL 0:00 阿帕奇2 21132 ? SS 0:04 阿帕奇2

    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 列表,您也可以轻松地使用 grep 搜索:

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

    谁的输出在 Linux 和 OS X 上是一样的:

    3519 3521 3523 3524

    以下的输出是一个空字符串,使得这种方法对于未运行的进程是安全的:

    回声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”)并使用参数执行它来测试它:./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

    【讨论】:

    • 进程可以运行,但停止。因此,如果目标是测试 mysqld 或 httpd 是否“启动并运行”(响应),您还应该检查它是否已停止。
    • 抱歉,虽然从语义的角度来看答案肯定是正确的,但我完全反对通过对进程 arg 向量进行模式匹配来尝试找到进程。任何这样的方法迟早都注定要失败(实际上您自己承认这一点,并说需要进行更多检查)。我在单独的答案中添加了我自己的建议。
    • grep 也会发现自己正在运行(例如,ps cax | grep randomname 将始终返回 0,因为 grep 会找到 grep randomname(希望这很清楚......)。一种解决方法是添加方括号围绕进程名称的第一个字母,例如ps cax | grep [r]andomname
    • ps cax | rev | cut -f1 -d' ' | rev 将只显示名称列,以便于解析。
    • ps cax 可能无法完整输出命令名称。例如,它打印“chromium-browse”而不是“chromium-browser”。
    【解决方案5】:

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

    ps acux | grep cron
    

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

    在原生 ps 命令的遗传学指向 SysV 的系统上,您会使用

    ps -e |grep cron
    

    ps -el |grep cron 
    

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

    【讨论】:

    • 这个答案如何移植? (你说在不同的平台上应该使用不同形式的ps命令)
    • ps 不幸的是,它是那些工具之一,根据他们的祖先,相同的结果具有不同的选项集。因此,除非您围绕此编写自己的(再次与其他任何内容不兼容)包装器,否则要走的路是了解遗产的主要路线并相应地进行调整。当您编写脚本时会有所不同 - 您将使用这些差异来确定您所在的分支并调整脚本的行为。底线:你需要知道两者。著名的例子:Larry Wall 的“配置”脚本。名言:恭喜,你没有运行 Eunice。
    【解决方案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
    

    【讨论】:

    • 其实使用ps cax就不需要使用grep -v了。例如,您可以使用:ps cax | grep java > /dev/null || echo "Java not running".
    • 第 3 行有错误。请把“running”改成“$running”。
    【解决方案7】:

    你应该知道 PID !

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

    只有进程 id (pid) 是真正唯一的。

    当您在后台启动某些内容时,请始终存储 pid。在 Bash 中,这可以通过 $! Bash 变量来完成。这样做可以省去很多麻烦。

    如何判断进程是否正在运行(通过 pid)

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

    简单地做:

    ps -o pid= -p

    这是 POSIX,因此是可移植的。如果进程正在运行,它将返回 pid 本身,如果进程未运行,它将不返回任何内容。严格来说,该命令将返回单个列,pid,但由于我们给出了一个空标题标题(紧接在等号之前的内容)并且这是唯一请求的列,因此 ps 命令将不会使用标题一点也不。这是我们想要的,因为它使解析更容易。

    这适用于 Linux、BSD、Solaris 等。

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

    【讨论】:

    • 除了这个不回答问题,就是判断一个服务是否在运行。在这种情况下,PID 是未知的,因此只有当您确实知道 PID 时,此答案才有效。
    • 错了。我的评论的全部要点是退一步说,如果您首先发现自己处于必须执行某种形式的grep <sometext> 才能找到给定流程的情况,那么您在开始流程时做错了, 恕我直言。我从 OP 的问题中得知,他确实可以控制流程的启动方式。
    • OP 问题更正确的“术语”应该是“跨平台命令以确定服务是否正在运行”,它不是运行检查的同一系统,而是外部系统,所以PID 根本不为人所知。
    • 这不是万无一失的。您感兴趣的进程可能在系统运行足够长的时间以使 PID 回绕后死亡,然后可能已为另一个进程分配了您正在检查的相同 PID。 stackoverflow.com/questions/11323410/linux-pid-recycling
    • @claymation。有道理。然而,PID 方法仍然比进程参数上的模式匹配更好,因为 PID 冲突比意外启动同一服务的两个实例的可能性要小得多。只是我的两分钱。 :-)
    【解决方案8】:

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

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

    小解释是怎么回事:

    1. -m1 - 在第一次匹配时停止进程
    2. "mysqld$|httpd$" - grep 将匹配以 mysqld 或 httpd 结尾的行
    3. /proc/[0-9]* - bash 将匹配以任意数字开头的行
    4. cut - 只需按分隔符“/”分割输出并提取字段 3

    【讨论】:

      【解决方案9】:

      以下 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)

      【讨论】:

      • $ isPidRunning 0] 打印例如“0] 正在运行 3 [ksoftirqd/0] 8 [rcuop/0] 17 [rcuos/0] 26 [rcuob/0] 34 [migration/0] 35 [watchdog/0]”在这里。
      • 你需要那个 PATH 的东西做什么?
      • 我进一步开发了解决方案here
      • @jarno PATH 设置是脚本可移植的要求。否则,它至少会在 Solaris 10 和更早版本以及可能的其他 Unix 实现上失败。
      • @jarno 我可能会这样做,但也需要为 awk 重复此 PATH 设置。请注意,我恢复到旧的反引号语法,以便与 pre-POSIX 语法 bourne shell 一起移植。
      【解决方案10】:

      将各种建议放在一起,我能想到的最简洁的版本(没有触发部分单词的不可靠 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"
      

      【讨论】:

        【解决方案11】:

        这将打印基本名称为“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"
        

        【讨论】:

          【解决方案12】:

          你应该知道你的进程的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
          

          基于peterhanswer。知道给定 PID 是否正在运行的诀窍在于 ps -o pid= -p $PID 指令。

          【讨论】:

            【解决方案13】:

            这是我的版本。特点:

            • 检查确切的程序名称(函数的第一个参数)。搜索“mysql”将不匹配运行“mysqld”
            • 搜索程序参数(函数的第二个参数)

            脚本:

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

            【讨论】:

              【解决方案14】:

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

              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发帖解释。

              【讨论】:

                【解决方案15】:

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

                【讨论】:

                  猜你喜欢
                  • 2015-04-05
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-07-09
                  • 1970-01-01
                  • 2012-01-10
                  • 1970-01-01
                  • 1970-01-01
                  • 2010-10-23
                  相关资源
                  最近更新 更多