【问题标题】:Bash script to check running process [duplicate]用于检查运行进程的 Bash 脚本 [重复]
【发布时间】:2011-02-23 14:31:53
【问题描述】:

我编写了一个 bash 脚本来检查进程是否正在运行。它不起作用,因为 ps 命令总是返回退出代码 1。当我从命令行运行 ps 命令时,$?设置正确,但在脚本中始终为 1。有什么想法吗?

#!/bin/bash
SERVICE=$1

ps -a | grep -v grep | grep $1 > /dev/null
result=$?
echo "exit code: ${result}"
if [ "${result}" -eq "0" ] ; then
    echo "`date`: $SERVICE service running, everything is fine"
else
    echo "`date`: $SERVICE is not running"
fi

Bash 版本:GNU bash,版本 3.2.25(1)-release (x86_64-redhat-linux-gnu)

【问题讨论】:

  • 您能否检查一下是否从 grep 命令获得非空输出而不是依赖返回值?
  • 我试过这个并且有类似的问题。不考虑输出。这里的代码: #!/bin/bash SERVICE=$1 OUTPUT=$(ps -a | grep -v grep | grep $1) echo $OUTPUT if [ "${#OUTPUT}" -gt 0 ] ;然后 echo "date: $SERVICE 服务正在运行,一切都很好" else echo "date: $SERVICE 没有运行" fi
  • 检查进程是否存在的最佳方法:stackoverflow.com/questions/3043978/…

标签: bash


【解决方案1】:

我在 BASH 版本 3.2.29 上尝试了您的版本,效果很好。但是,您可以执行上述建议的操作,此处为示例:

#!/bin/sh

SERVICE="$1"
RESULT=`ps -ef | grep $1 | grep -v 'grep' | grep -v $0`
result=$(echo $ps_out | grep "$1")

if [[ "$result" != "" ]];then
    echo "Running"
else
    echo "Not Running"
fi

【讨论】:

  • 我试过了,也不行。我的环境(共享主机提供商)一定有问题。
  • 试过用#!/bin/sh -x 运行看看执行过程?
  • 没什么特别的:输出是 + SERVICE=rails + ps -a + grep -v grep + grep rails + result=1 + echo 'exit code: 1' exit code: 1 + '[' 1 -eq 0 ']' ++ date + echo 'Tue May 25 06:52:25 EDT 2010: rails is not running'
  • 请注意:ps -a 仅列出用户在当前终端中的进程。但是,ps -A 检查所有进程。
  • @karlphillip 你每天都能学到新东西,干杯伙伴。
【解决方案2】:

serviceawk 的解决方案采用逗号分隔的服务名称列表。

首先,您可能需要 root 权限才能做您想做的事。如果您不需要检查,则可以删除该部分。

#!/usr/bin/env bash

# First parameter is a comma-delimited string of service names i.e. service1,service2,service3
SERVICES=$1

ALL_SERVICES_STARTED=true

if [ $EUID -ne 0 ]; then
  if [ "$(id -u)" != "0" ]; then
    echo "root privileges are required" 1>&2
    exit 1
  fi
  exit 1
fi

for service in ${SERVICES//,/ }
do
    STATUS=$(service ${service} status | awk '{print $2}')

    if [ "${STATUS}" != "started" ]; then
        echo "${service} not started"
        ALL_SERVICES_STARTED=false
    fi
done

if ${ALL_SERVICES_STARTED} ; then
    echo "All services started"
    exit 0
else
    echo "Check Failed"
    exit 1
fi

【讨论】:

    【解决方案3】:

    我需要不时执行此操作并最终破解命令行,直到它工作为止。

    例如,这里我想看看我有没有SSH连接,(“ps”返回的第8列是正在运行的“path-to-procname”并被“awk”过滤:

    ps | awk -e '{ print $8 }' | grep ssh | sed -e 's/.*\///g'
    

    然后我把它放在一个 shell 脚本中,(“eval”-ing 反引号内的命令行),像这样:

    #!/bin/bash
    
    VNC_STRING=`ps | awk -e '{ print $8 }' | grep vnc | sed -e 's/.*\///g'`
    
    if [ ! -z "$VNC_STRING" ]; then
        echo "The VNC STRING is not empty, therefore your process is running."
    fi
    

    “sed”部分修剪到确切令牌的路径,可能不是您的需要。

    这是我用来获得您答案的示例。我编写它是为了自动创建 2 个 SSH 隧道并为每个隧道启动一个 VNC 客户端。

    我从我的 Cygwin shell 运行它以从我的 Windows 工作站对我的后端进行管理,所以我可以用一个命令跳转到 UNIX/LINUX-land,(这也假设客户端 rsa 密钥已经是“ssh-copy -id"-ed 并且为远程主机所知)。

    这是幂等的,因为每个 proc/command 仅在其 $VAR eval 为空字符串时触发。

    它附加“| wc -l”来存储匹配的运行过程的数量(即找到的行数),而不是每个 $VAR 的 proc-name 以满足我的需要。我保留“echo”语句,以便重新运行并诊断两个连接的状态。

    #!/bin/bash
    
    SSH_COUNT=`eval ps | awk -e '{ print $8 }' | grep ssh | sed -e 's/.*\///g' | wc -l`
    VNC_COUNT=`eval ps | awk -e '{ print $8 }' | grep vnc | sed -e 's/.*\///g' | wc -l`
    
    if  [ $SSH_COUNT = "2" ]; then
        echo "There are already 2 SSH tunnels."
    elif  [ $SSH_COUNT = "1" ]; then
        echo "There is only 1 SSH tunnel."
    elif [ $SSH_COUNT = "0" ]; then
        echo "connecting 2 SSH tunnels."
        ssh -L 5901:localhost:5901 -f -l USER1 HOST1 sleep 10;
        ssh -L 5904:localhost:5904 -f -l USER2 HOST2 sleep 10;
    fi
    
    if  [ $VNC_COUNT = "2" ]; then
        echo "There are already 2 VNC sessions."
    elif  [ $VNC_COUNT = "1" ]; then
        echo "There is only 1 VNC session."
    elif [ $VNC_COUNT = "0" ]; then
        echo "launching 2 vnc sessions."
        vncviewer.exe localhost:1 &
        vncviewer.exe localhost:4 &
    fi
    

    这对我来说非常类似于 perl,并且可能比真正的 shell 脚本更多的是 unix utils。我知道有很多“魔法”数字和俗气的硬编码值,但它有效,(我认为我也对使用这么多大写字母的品味很差)。可以通过一些 cmd-line 参数添加灵活性以使其更加通用,但我想分享对我有用的东西。请改进和分享。干杯。

    【讨论】:

      【解决方案4】:

      最简单的进程名检查:

       bash -c 'checkproc ssh.exe ; while  [ $? -eq 0  ] ; do  echo "proc running";sleep 10; checkproc ssh.exe; done'
      

      【讨论】:

      • 这看起来像是一个 Windows 解决方案,但不是一个很好的解决方案。您可以链接到checkproc 的文档吗?
      【解决方案5】:

      尽管在 bash 中使用 /dev/null 方法取得了一些成功。当我将解决方案推送到 cron 时,它失败了。不过,检查返回命令的大小效果很好。 & 号允许 bash 退出。

      #!/bin/bash
      SERVICE=/path/to/my/service
      result=$(ps ax|grep -v grep|grep $SERVICE)
      echo ${#result}
      if  ${#result}> 0 
      then
              echo " Working!"
      else
              echo "Not Working.....Restarting"
              /usr/bin/xvfb-run -a /opt/python27/bin/python2.7 SERVICE &
      fi
      

      【讨论】:

        【解决方案6】:

        有几个非常简单的方法:

        pgrep procname && echo Running 
        pgrep procname || echo Not running 
        killall -q -0 procname && echo Running 
        pidof procname && echo Running
        

        【讨论】:

        • 我怎样才能做同样的事情,但不将 PID 从 pgrep 输出到控制台?
        • 使用 thispgrep procname > /dev/null && echo Running 避免 pgrep 输出 PID
        • "killall -q" 一句话也不说
        • 即使进程只包含您要查找的进程名称,您的方法也会返回结果。这不是检查确切名称的解决方案。
        • @FAjir 解决办法是做pgrep -x procname,测试整个进程名。
        【解决方案7】:

        这个技巧对我有用。希望这可以帮助你。让我们将以下内容保存为 checkRunningProcess.sh

        #!/bin/bash
        ps_out=`ps -ef | grep $1 | grep -v 'grep' | grep -v $0`
        result=$(echo $ps_out | grep "$1")
        if [[ "$result" != "" ]];then
            echo "Running"
        else
            echo "Not Running"
        fi
        

        使 checkRunningProcess.sh 可执行。然后使用它。
        使用示例。

        20:10 $ checkRunningProcess.sh proxy.py
        Running
        20:12 $ checkRunningProcess.sh abcdef
        Not Running
        

        【讨论】:

        • 这是我需要检查的进程是否也通过它的命令行参数运行。 ps auxps -ef 有什么区别
        【解决方案8】:

        我想知道对进程进行渐进式尝试是否是一个好主意,因此您将这个 func 传递给进程名称 func_terminate_process "firefox",它首先会更好地处理事情,然后继续杀死。

        # -- NICE: try to use killall to stop process(s)
        killall ${1} > /dev/null 2>&1 ;sleep 10
        
        # -- if we do not see the process, just end the function
        pgrep ${1} > /dev/null 2>&1 || return
        
        # -- UGLY: Step trough every pid and use kill -9 on them individually
        for PID in $(pidof ${1}) ;do
        
            echo "Terminating Process: [${1}], PID [${PID}]" 
            kill -9 ${PID} ;sleep 10
        
            # -- NASTY: If kill -9 fails, try SIGTERM on PID
            if ps -p ${PID} > /dev/null ;then
                echo "${PID} is still running, forcefully terminating with SIGTERM"
                kill -SIGTERM ${PID}  ;sleep 10
            fi
        
        done
        
        # -- If after all that, we still see the process, report that to the screen.
        pgrep ${1} > /dev/null 2>&1 && echo "Error, unable to terminate all or any of [${1}]" || echo "Terminate process [${1}] : SUCCESSFUL"
        

        【讨论】:

          【解决方案9】:

          Andor 上述建议之一的简单脚本版本:

          !/bin/bash
          
          pgrep $1 && echo Running
          

          如果上面的脚本被称为 test.sh,那么为了测试,输入: test.sh NameOfProcessToCheck

          例如 test.sh php

          【讨论】:

            【解决方案10】:

            我用这个每 10 秒检查一次进程是否正在运行,如果没有则启动并允许多个参数:

            #!/bin/sh
            
            PROCESS="$1"
            PROCANDARGS=$*
            
            while :
            do
                RESULT=`pgrep ${PROCESS}`
            
                if [ "${RESULT:-null}" = null ]; then
                        echo "${PROCESS} not running, starting "$PROCANDARGS
                        $PROCANDARGS &
                else
                        echo "running"
                fi
                sleep 10
            done    
            

            【讨论】:

              【解决方案11】:

              这些都是有用的提示。我只需要在启动脚本时知道服务是否正在运行,这样我就可以在离开时让服务保持相同的状态。我最终使用了这个:

                 HTTPDSERVICE=$(ps -A | grep httpd | head -1)
              
                 [ -z "$HTTPDSERVICE" ] &&  echo "No apache service running." 
              

              【讨论】:

                【解决方案12】:

                检查您的脚本名称是否不包含 $SERVICE。如果是这样,它将显示在 ps 结果中,导致脚本始终认为该服务正在运行。您可以像这样针对当前文件名对其进行 grep:

                #!/bin/sh
                SERVICE=$1
                if ps ax | grep -v grep | grep -v $0 | grep $SERVICE > /dev/null
                then
                    echo "$SERVICE service running, everything is fine"
                else
                    echo "$SERVICE is not running"
                fi
                

                【讨论】:

                • 对于那些想要将其用作脚本的一部分而不是函数的人,请将 $0 更改为 grep ps ax | grep -v grep | grep -v grep | grep $SERVICE > /dev/null
                【解决方案13】:

                工作一个。

                !/bin/bash 支票=$0 服务=$1 日期=`日期` 输出=$(ps aux | grep -v grep | grep -v $CHECK |grep $1) 回显 $OUTPUT 如果 [ "${#OUTPUT}" -gt 0 ] ; 然后 echo "$DATE: $SERVICE 服务正在运行,一切都很好" else echo "$DATE: $SERVICE 没有运行" 菲

                【讨论】:

                • pgrep 是一个更好的解决方案,您仍然存在不检查进程名称而是检查 ps aux 的整个输出的问题。
                【解决方案14】:
                #!/bin/bash ps axho 通讯| grep $1 > /dev/null 结果=$? echo "退出代码:${result}" if [ "${result}" -eq "0" ] ;然后 echo "`date`: $SERVICE 服务正在运行,一切正常" 别的 echo "`date`: $SERVICE 没有运行" /etc/init.d/$1 重启 菲

                类似的东西

                【讨论】:

                  【解决方案15】:

                  我发现了问题。 ps -ae 代替 ps -a 有效。

                  我想这与我在共享主机环境中的权利有关。从命令行执行“ps -a”和从 bash 脚本中执行它显然是有区别的。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2018-01-16
                    • 2019-06-24
                    • 2017-07-07
                    • 2014-08-21
                    • 2012-10-30
                    相关资源
                    最近更新 更多