检查Shell脚本是否正在运行的Linux命令

43

如何使用Linux命令查找进程(比如aa.sh)是否正在运行。ps命令似乎无法生效,并没有显示脚本名称。

请给予建议。


ps -ae 显示了脚本名称给我。 - nims
4
ps aux|grep scriptname 或者 pgrep scriptname 的意思是在当前系统中查找名为 "scriptname" 的进程。ps aux 命令用于显示所有正在运行的进程,而 grep 命令则用于根据关键字过滤出匹配的结果。另外,pgrep 命令也可以直接查找与给定名称匹配的进程,并返回进程 ID。 - Basile Starynkevitch
或者使用 pidof 命令来获取进程的 PID。 - tripleee
9个回答

51

查看这个

ps aux | grep "aa.sh"

5
这可能会带来一些意外惊喜,让我同时举两个例子。第一个是:它也会找到“aaa.sh”,这可能会引起错误。第二个是:grep会找到自己,你需要处理它。pgrep是优雅的解决方案。 - user897079
3
我们可以使用一个小技巧来防止grep命令显示自身:ps aux | grep "[a]a.sh" - Vassilis
抱歉,但是pgrep是正确的方法,这个解决方案需要@Vassilis的技巧才能正常工作。 - Gilles Quénot

43

13
如果有人想知道这是什么作用,请查看解释 - tutuDajuju
3
@tutuDajuju:感谢你的帮助。稍微离题一下,值得特别注意的是,你提供的链接服务:http://explainshell.com,可以解析任意Unix命令行并根据Ubuntu手册解释具体的选项使用方法。以下是解释此答案的明确URL:http://www.explainshell.com/explain?cmd=pgrep+-fl+aa.sh - mklement0
1
如果你正在编写脚本,那么你可以接着使用 if [ $? = 0 ] 来判断进程是否被找到(pgrep 返回 0)或未被找到(pgrep 返回 1)。 - otocan

13

补充以上答案:

要在脚本中使用,请使用以下内容:

result=`ps aux | grep -i "myscript.sh" | grep -v "grep" | wc -l`
if [ $result -ge 1 ]
   then
        echo "script is running"
   else
        echo "script is not running"
fi

如果我单独运行 ps aux | grep -i "myscript.sh" | grep -v "grep" | wc -l,输出为0。但如果我在我的脚本中运行它,结果为2并且脚本退出。有什么建议吗? - Ahue
1
有关编程的内容翻译如下:一个是用于脚本,另一个是用于grep本身。如果您在终端中尝试ps aux | grep hello,您将看到grep作为一个进程。为了防止grep显示自己,我使用了一个技巧:ps aux | grep [h]ello - Vassilis

6
上述解决方案非常适用于交互式使用,您可以通过目测结果来排除错误的情况。
如果可执行文件本身恰好匹配,或者任何不是脚本名称的参数匹配,则可能会发生误报 - 对于没有文件名扩展名的脚本,这种可能性更大。
以下是一种更为稳健的脚本解决方案,使用 shell 函数:
getscript() {
  pgrep -lf ".[ /]$1( |\$)"
}

示例用法:

# List instance(s) of script "aa.sh" that are running.
getscript "aa.sh"  # -> (e.g.): 96112 bash /Users/jdoe/aa.sh

# Use in a test:
if getscript "aa.sh" >/dev/null; then
  echo RUNNING
fi
  • 匹配区分大小写(在 macOS 上,可以在 pgrep 调用中添加 -i 以使其不区分大小写;在 Linux 上,这不是一个选项)。
  • getscript 函数也适用于包含文件名组件的完整或部分路径;部分路径不能以 / 开头,每个指定的组件必须完整。 指定的路径越“完整”,误报的风险就越低。注意:只有当脚本使用路径“调用”时,路径匹配才会起作用 - 对于在 $PATH 中直接调用的脚本通常如此。
  • 即使使用此函数,也无法排除所有误报,因为路径可能包含嵌入的空格,但是 pspgrep 都没有反映对命令行应用的原始引号。该函数保证的是任何匹配都不是第一个标记(即解释器),并且它作为一个独立的单词出现,可选地在路径之前。
  • 另一种减少误报风险的方法是同时匹配 可执行文件 名称(即解释器,例如 bash)- 假设已知;例如:
# List instance(s) of a running *bash* script.
getbashscript() {
  pgrep -lf "(^|/)bash( | .*/)$1( |\$)"
}

如果您愿意做更多的假设,比如脚本解释器路径永远不会包含嵌入式空格,那么正则表达式可以变得更加严格,从而进一步降低误报的风险。

5

请检查这个

ps -ef | grep shellscripname.sh

你也可以在下面找到正在运行的进程:

ps -ef

2

我被mklement0的最后一个回答所启发 - 我有一些脚本/小程序,我通过/etc/crontab在每次重启时运行。我基于他的答案构建了一个登录脚本,可以显示我的程序是否仍在运行。

我通过.profile文件在每次登录时执行这个scripts.sh,以便获得即时通知。

cat scripts.sh 
#!/bin/bash

getscript() {
  pgrep -lf ".[ /]$1( |\$)"
}

script1=keepalive.sh
script2=logger_v3.py

# test if script 1 is running
if getscript "$script1" >/dev/null; then
  echo "$script1" is RUNNING
  else
    echo "$script1" is NOT running
fi

# test if script 2 is running:
if getscript "$script2" >/dev/null; then
  echo "$script2" is RUNNING
  else
    echo "$script2" is NOT running
fi

2
pgrep -f aa.sh 

要使用id执行某些操作,您需要使用管道符。这里我将结束其所有子任务。

pgrep aa.sh | xargs pgrep -P ${} | xargs kill

如果您想在进程正在运行时执行命令,请按照以下步骤进行操作。
pgrep aa.sh && echo Running

1

这是一个快速脚本,用于测试shell脚本是否在运行。

#!/bin/sh

scripToTest="your_script_here.sh"
scriptExist=$(pgrep -f "$scripToTest")
[ -z "$scriptExist" ] && echo "$scripToTest : not running" || echo "$scripToTest : runnning"

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接