如何确定一个进程是否正在运行,并使用它来制作条件shell脚本?


108

如何确定某个进程是否正在运行,然后让bash脚本根据该条件执行某些操作?

例如:

  • 如果进程abc正在运行,请执行此操作

  • 如果它没有运行,请执行此操作。


1
很重要的一点是,请注意以下解决方案均未考虑过程状态。对我的一个问题的评论将带到了这里,但是对它的回答使我进入了程序的不同状态,例如“ zombie进程”(不是我所描述的“正在运行”的进程)。STAT在的输出中ps,列值所表示的内容的完整列表在适用于那些倾向于编写适应该问题的答案或自己编辑的人。
user66001 2013年


Answers:


166

一个执行类似操作的bash脚本如下所示:

#!/bin/bash

# Check if gedit is running
# -x flag only match processes whose name (or command line if -f is
# specified) exactly match the pattern. 

if pgrep -x "gedit" > /dev/null
then
    echo "Running"
else
    echo "Stopped"
fi

该脚本只是在检查程序“ gedit”是否正在运行。

或者,您只能检查程序是否没有像这样运行:

if ! pgrep -x "gedit" > /dev/null
then
    echo "Stopped"
fi

@DreadPirateShawn您能告诉我为什么使用/ dev / null而不是简单的0吗?使用数字使代码更易读,至少对于菜鸟(例如我)而言。没有重定向,没有任何内容
Silviu 2015年

2
@Silviu嗯?谷歌搜索/dev/null:“ / dev / null将命令标准输出重定向到null设备,这是一种特殊设备,该设备会丢弃写入其中的信息” ...使用0会将命令输出重定向到名为的文件0。在这种情况下,我建议您逐渐适应> /dev/null-您会在任何地方看到它,因为这是丢弃输出的标准/正确方法。
DreadPirateShawn 2015年

谢谢,我用它来编写一个漂亮的小脚本,该脚本在程序执行之前检查程序是否正在运行。(尽管我必须将其扩展一点,因为google chrome的可执行文件的名称与run命令的名称不同,但exec名称只是chrome。)
Cestarian

3
请向中添加-x参数,pgrep以便它查找确切的应用程序,否则,如果在另一个应用程序名称内找到相同的字符串,它将得到错误的正确提示。我只是花了1个小时才找到答案。
Thanos Apostolou,

1
要检查程序是否未运行,请使用! pgrep
Mohammed Noureldin

36

任何使用类似ps aux | grep abcpgrep abc有缺陷的解决方案。

为什么?

由于您没有在检查特定进程是否正在运行,因此您正在检查是否有任何运行的进程恰好匹配abc。任何用户都可以轻松地创建和运行名为abc(或abc名称或自变量中包含某处)的可执行文件,从而对测试造成误判。有可应用于各种选项psgreppgrep以缩小搜索范围,但你仍然不会得到一个可靠的测试。

那么,如何可靠地测试某个正在运行的进程?

这取决于您需要测试的内容。

我想确保服务abc正在运行,如果没有,请启动它

这就是初始化和新贵的目的。他们将启动服务,并确保其pid被存储在pidfile中。尝试再次启动该服务(通过init或upstart),它将检查pidfile,如果不存在则启动它,如果已经运行则中止。这仍然不是100%可靠的,但与您所获得的接近。

有关其他解决方案,请参阅如何检查我的游戏服务器是否仍在运行

abc是我的脚本。我需要确保脚本的仅一个实例正在运行。

在这种情况下,请使用锁定文件或lockdir。例如

#!/usr/bin/env bash

if ! mkdir /tmp/abc.lock; then
    printf "Failed to acquire lock.\n" >&2
    exit 1
fi
trap 'rm -rf /tmp/abc.lock' EXIT  # remove the lockdir on exit

# rest of script ...

有关其他锁定方法,请参见Bash FAQ 45


3
尽管从技术上讲这是正确的,但我个人在现实生活中曾遇到过这样的问题。大多数程序不会以破坏脚本的方式更改其名称。因此,对于简单的脚本,类似pgrepps完全可以满足要求,而您的方法似乎有些过分。但是,如果您要编写公开发行的股票,则应以最安全的方式编写。
Scott Severance 2012年

2
@ScottSeverance程序更改名称不是问题;无论如何,都需要干预。是其他用户在运行同一程序或其他名称相似的程序突然导致脚本误报,从而做错了事。我只喜欢“作品”,而不是“大部分作品”。
盖尔哈2012年

2
我误会了。但是我们许多人都运行单用户系统。而且在多用户情况下,也可以使用grep来输入用户名。
Scott Severance,2012年

1
如果您的脚本在运行时失败并在解锁文件之前死亡怎么办?
jp093121 2014年

2
@ jp093121退出脚本时会触发EXIT陷阱。无论是由于到达脚本末尾而退出,退出命令还是接收到信号(可以处理),rm命令都会运行。因此,只要在设置陷阱后结束,锁就应该消失了。
盖尔哈

18

这是我用的:

#!/bin/bash

#check if abc is running
if pgrep abc >/dev/null 2>&1
  then
     # abc is running
  else
     # abc is not running
fi

简而言之如果'pgrep'返回0,则进程正在运行,否则,进程未运行。


相关阅读:

Bash脚本:: 字符串比较

Ubuntu手册pgrep


谢谢!我也尝试过这个,它也可以完美工作:)
Nirmik 2012年

pgrep具有前面提到的相同的15个字符限制“功能”,因此例如pgrep gnome-power-manager也会失败
Thorsen 2012年

1
确保使用pgrep的-x选项:“仅匹配名称(或命令行,如果指定-f)与模式完全匹配的进程”。
Alastair Irvine


2

嘲笑@ rommel-cid的想法,您可以使用pidof|| (||)如果进程不存在则运行命令,&&如果进程不存在则运行命令,从而创建快速的if / then / else条件。例如,这里有一个正在运行的进程(我的chrome浏览器,其进程名称为“ chrome”),以及一个针对不存在的进程的测试。我使用1> / dev / null抑制了标准输出,因此它不会打印:

$ (pidof chrome 1>/dev/null && echo "its running? ok, so am i then" ) || echo "it's not running? ok i'll run instea\
d"
its running? ok, so am i then
$ (pidof nosuchprocess 1>/dev/null && echo "its running? ok, so am i then" ) || echo "it's not running? ok i'll run\
 instead"
it's not running? ok i'll run instead
$

1

没有一个“简单”的解决方案对我有用,因为我需要检查的二进制文件未在系统范围内安装,因此我必须使用路径进行检查,而路径又需要使用以下ps -ef | grep方法:

app="$_sdir/Logic 1.2.18 (64-bit)/Logic"

app_pid=`ps -ef | grep "$app" | awk '{print $2}'`

if `ps -p $app_pid > /dev/null`; then
    echo "An instance of logic analyzer is appear to be running."
    echo "Not starting another instance."
    exit 5
else
    nohup "$app" &> /dev/null &
fi

0

对于您的问题,我想到的第一件事是:
ps aux | grep -i abc如果流程正在运行,它将显示该流程的详细信息。您可以匹配其运行的行数或时间,并与零或任何其他操作进行比较。当您运行上面的命令时,它将至少显示一行输出,即有关thi grep命令创建的过程的详细信息。因此,请注意这一点。
那应该是一个简单的技巧。将其放在bash脚本中,看看是否有帮助。


0

使用start-stop-daemon

/sbin/start-stop-daemon --background --make-pidfile --pidfile /tmp/foo.pid -S --startas /usr/bin/program -- arg1 arg2

它可以作为普通用户使用。


0

我发现@John Vrbanac发布的已接受答案对我不起作用,@ geirha发布的答案未回答原始问题。

John Vrbanac的解决方案无法为我检查PHP进程是否正在运行,我正在运行CentOS 7。

@geirha的答案只能确保启动另一个实例之前该实例尚未运行。这不是原始问题,原始问题是检查进程是否正在运行。

这对我有用:

假设我的流程名称中包含字符串“ Jane”。这将发现它是否正在运行。这适用于BASH和PHP脚本。

ps -aux | grep "[J]ane" > /dev/null 2>&1
if [[ "$?" == "0" ]]; then
    echo "It's running"
else
    echo "It's not running"
fi

1
嗯,这是一个Ubuntu问题解答站点,因此这里的某些答案在CentOS 7上不起作用也就不足为奇了,因为Linux在这里是不合时宜的。unix.stackexchange.com
Elder Geek

尽管答案的作者使用CentOS,但此答案对ubuntu仍然有效。
菲利普-Zyan K Lee- Stockmann

0
## bash

## function to check if a process is alive and running:

_isRunning() {
    ps -o comm= -C "$1" 2>/dev/null | grep -x "$1" >/dev/null 2>&1
}

## example 1: checking if "gedit" is running

if _isRunning gedit; then
    echo "gedit is running"
else
    echo "gedit is not running"
fi

## example 2: start lxpanel if it is not there

if ! _isRunning lxpanel; then
    lxpanel &
fi

## or

_isRunning lxpanel || (lxpanel &)

注意pgrep -x lxpanel或即使已消失(僵尸)pidof lxpanel仍报告lxpanel正在运行;因此要获得活着和运行过程中,我们需要使用psgrep


-1

从2016年9月23日开始,pgrep似乎需要一个选项“ -x”才能使muru的脚本起作用。

#!/bin/bash

if pgrep -x "conky" > /dev/null 2>&1
then
  echo "conky running already"
else
  echo "now starting conky"
  conky
fi
exit 0

我在Ubuntu 16.04.1计算机上尝试并测试了上述脚本。请享用!


-1
#!/bin/bash
while [ true ]; do     # Endless loop.
  pid=`pgrep -x ${1}`  # Get a pid.
  if [ -z $pid ]; then # If there is none,
    ${1} &             # Start Param to background.
  else
    sleep 60           # Else wait.
  fi
done

1
欢迎来到Ask Ubuntu!我建议编辑此答案以使用有关此操作的特定详细信息将其扩展。(另请参阅“我如何编写一个好的答案?”,以获取有关在AskUbuntu上认为最有价值的答案的一般建议。)
David Foerster

-3

isProcessRunning(){如果[[$(pidof $ 1)> / dev / null]; 然后retval ='true'; 否则retval ='false'; fi; 回声$ retval; }

isProcessRunning geany

真正

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.