Linux 脚本检查进程是否正在运行并对结果采取行动

问题描述 投票:0回答:8

我有一个进程经常失败并且有时会启动重复的实例..

当我跑步时:

ps x |grep -v grep |grep -c "processname"
我会得到:
2
这是正常的,因为该进程在恢复过程中运行..

如果我得到

0
我想开始这个过程 如果我有:
4
我想停止并重新启动该过程

我需要的是一种获取结果的方法

ps x |grep -v grep |grep -c "processname"

然后设置一个简单的3选项功能

ps x |grep -v grep |grep -c "processname"
if answer = 0 (start process & write NOK & Time to log /var/processlog/check)
if answer = 2 (Do nothing & write OK & time to log /var/processlog/check)
if answer = 4 (stot & restart the process & write NOK & Time to log /var/processlog/check)

该过程停止于

killall -9 process
该过程开始于
process -b -c /usr/local/etc

我的主要问题是找到一种方法来根据

ps x |grep -v grep |grep -c "processname"
的结果采取行动。

理想情况下,我希望将 grep 的结果作为脚本中的变量,如下所示:

process=$(ps x |grep -v grep |grep -c "processname")

如果可以的话。

linux bash process grep
8个回答
80
投票

用于监视系统上的进程是否正在运行的程序。

脚本存储在

crontab
中并每分钟运行一次。

这适用于进程未运行或进程运行多次的情况:

#! /bin/bash

case "$(pidof amadeus.x86 | wc -l)" in

0)  echo "Restarting Amadeus:     $(date)" >> /var/log/amadeus.txt
    /etc/amadeus/amadeus.x86 &
    ;;
1)  # all ok
    ;;
*)  echo "Removed double Amadeus: $(date)" >> /var/log/amadeus.txt
    kill $(pidof amadeus.x86 | awk '{print $1}')
    ;;
esac

0
如果找不到进程,请重新启动它。
1
如果找到进程,就ok了。
*
如果进程运行 2 个或更多,则终止最后一个。


更简单的版本。这只是测试进程是否正在运行,如果没有则重新启动它。

它只是测试来自

$?
程序的退出标志
pidof
。如果进程正在运行,则为
0
;如果未运行,则为
1

#!/bin/bash
pidof  amadeus.x86 >/dev/null
if [[ $? -ne 0 ]] ; then
        echo "Restarting Amadeus:     $(date)" >> /var/log/amadeus.txt
        /etc/amadeus/amadeus.x86 &
fi

最后,一个衬垫

pidof amadeus.x86 >/dev/null ; [[ $? -ne 0 ]] && echo "Restarting Amadeus:     $(date)" >> /var/log/amadeus.txt && /etc/amadeus/amadeus.x86 &

然后可以在 crontab 中使用它每分钟运行一次,如下所示:

* * * * * pidof amadeus.x86 >/dev/null ; [[ $? -ne 0 ]] && echo "Restarting Amadeus:     $(date)" >> /var/log/amadeus.txt && /etc/amadeus/amadeus.x86 &

cccam oscam


8
投票

我采用了@Jotne解决方案并且工作完美!例如我的 NAS 中的 mongodb 服务器

#! /bin/bash

case "$(pidof mongod | wc -w)" in

0)  echo "Restarting mongod:"
    mongod --config mongodb.conf
    ;;
1)  echo "mongod already running"
    ;;
esac

5
投票

我已经根据我的情况采用了你的脚本 Jotne。

#! /bin/bash

logfile="/var/oscamlog/oscam1check.log"

case "$(pidof oscam1 | wc -w)" in

0)  echo "oscam1 not running, restarting oscam1:     $(date)" >> $logfile
    /usr/local/bin/oscam1 -b -c /usr/local/etc/oscam1 -t /usr/local/tmp.oscam1 &
    ;;
2)  echo "oscam1 running, all OK:     $(date)" >> $logfile
    ;;
*)  echo "multiple instances of oscam1 running. Stopping & restarting oscam1:     $(date)" >> $logfile
    kill $(pidof oscam1 | awk '{print $1}')
    ;;
esac

我在测试的时候遇到了一个问题.. 我用这一行启动了 oscam1 的 3 个额外进程:

/usr/local/bin/oscam1 -b -c /usr/local/etc/oscam1 -t /usr/local/tmp.oscam1
这给我留下了 oscam1 的 8 个进程。问题是这样的.. 当我运行脚本时,它一次只会杀死 2 个进程,所以我必须运行它 3 次才能将其减少到 2 个进程..

除了

killall -9 oscam1
后面跟着
/usr/local/bin/oscam1 -b -c /usr/local/etc/oscam1 -t /usr/local/tmp.oscam1
之外,在
*)
中除了原来的进程之外还有什么更好的方法来killall吗?那么停机时间将为零?


0
投票

如果您将 awk '{print $1}' 更改为 '{ $1=""; print $0}' 您将得到除第一个进程之外的所有进程。它将以字段分隔符(通常是空格)开头,但我不记得有什么过分关心。所以:

#! /bin/bash

logfile="/var/oscamlog/oscam1check.log"

case "$(pidof oscam1 | wc -w)" in

0)  echo "oscam1 not running, restarting oscam1:     $(date)" >> $logfile
    /usr/local/bin/oscam1 -b -c /usr/local/etc/oscam1 -t /usr/local/tmp.oscam1 &
    ;;
2)  echo "oscam1 running, all OK:     $(date)" >> $logfile
    ;;
*)  echo "multiple instances of oscam1 running. Stopping & restarting oscam1:     $(date)" >> $logfile
    kill $(pidof oscam1 | awk '{ $1=""; print $0}')
    ;;
esac

值得注意的是,pidof 路由似乎适用于没有空格的命令,但如果您正在寻找一个名为 myscript 的 python 脚本,您可能会想要返回到基于 ps 的字符串。在ps下像

root 22415 54.0 0.4 89116 79076 pts/1 S 16:40 0:00 /usr/bin/python /usr/bin/myscript

仅供参考


0
投票

“pidof”命令不会显示 shell/perl/python 脚本的 pid。因此,要查找 Perl 脚本的进程 ID,我必须使用 -x 选项,即“pidof -x perlscriptname”


0
投票

我根本无法让案例发挥作用。 这是我所拥有的:

#! /bin/bash

logfile="/home/name/public_html/cgi-bin/check.log"

case "$(pidof -x script.pl | wc -w)" in

0)  echo "script not running, Restarting script:     $(date)" >> $logfile
#  ./restart-script.sh
;;
1)  echo "script Running:     $(date)" >> $logfile
;;
*)  echo "Removed duplicate instances of script: $(date)" >> $logfile
 #   kill $(pidof -x ./script.pl | awk '{ $1=""; print $0}')
;;
esac

现在删除案例操作命令只是为了测试脚本。上面的 pidof -x 命令返回“1”,case 语句返回“0”的结果。

有人知道我哪里出错了吗?

通过将以下内容添加到我的 BIN/BASH 脚本中解决了这个问题: PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin


0
投票

如果您正在寻找一种更现代的方法来检查服务是否正在运行(这不适用于任何旧进程),那么 systemctl 可能就是您正在寻找的。

这是基本命令:

systemctl show --property=ActiveState your_service_here

这将产生非常简单的输出(根据服务是否正在运行,将出现以下两行之一):

ActiveState=active
ActiveState=inactive

如果您想了解可以获得的所有属性:

systemctl show --all your_service_here

如果您喜欢按字母顺序排列:

systemctl show --all your_service_here | sort

以及对其进行操作的完整代码:

service=$1
result=`systemctl show --property=ActiveState $service`
if [[ "$result" == 'ActiveState=active' ]]; then
    echo "$service is running" # Do something here
else
    echo "$service is not running" # Do something else here
fi 

0
投票

如果您使用的是 CentOS,则无需编写脚本和设置 cron 作业。这是确保 systemd 服务在失败时重新启动的最明智的方法之一。 对 /usr/lib/systemd/system/mariadb.service 进行以下更改

然后在文件的 [Service] 部分下,添加以下 2 行:

Restart=always
RestartSec=3

保存文件后,我们需要重新加载守护进程配置以确保 systemd 知道新文件

systemctl daemon-reload

阅读以下链接了解完整步骤 - https://jonarcher.info/2015/08/ensure-systemd-services-restart-on-failure/

© www.soinside.com 2019 - 2024. All rights reserved.