考虑到它的参数,如何检测bash脚本是不是已经在运行[重复]

Posted

技术标签:

【中文标题】考虑到它的参数,如何检测bash脚本是不是已经在运行[重复]【英文标题】:How to detect if a bash script is already running, considering its arguments [duplicate]考虑到它的参数,如何检测bash脚本是否已经在运行[重复] 【发布时间】:2021-10-29 06:57:11 【问题描述】:

对不起我的英语不好;)

我需要检查一个脚本是否已经在运行。我不想使用锁定文件,因为它可能很棘手(即:如果我的脚本写了一个锁定文件,但崩溃了,我会认为它正在运行)。 我还需要考虑参数。 IE: 测试.sh 123 应该被认为是一个不同的过程 测试.sh 456

我试过了:

#!/bin/bash

echo "inside test.sh, script name with arguments: $0 +$*$"

echo "  simple pgrep on script name with arguments:"
pgrep -f "$0 +$*$"

echo "  counting simple pgrep on script name with arguments with wc -l"
echo $(pgrep -f "$0 +$*$" | wc -l)

echo "  counting pgrep echo result with wc -w"
processes=$(pgrep -f "$0 +$*$")
nbProcesses=$(echo $processes | wc -w)
echo $nbProcesses

sleep 300

当我尝试时,我得到了这个结果:

[frederic.charrier@charrier tmp]$ /tmp/test.sh 123
inside test.sh, script name with arguments: /tmp/test.sh +123$
  simple pgrep on script name with arguments:
123976
  counting simple pgrep on script name with arguments with wc -l
2
  counting pgrep echo result with wc -w
1
^Z
[1]+  Stoppé                 /tmp/test.sh 123
[frederic.charrier@charrier tmp]$ /tmp/test.sh 123
inside test.sh, script name with arguments: /tmp/test.sh +123$
  simple pgrep on script name with arguments:
123976
124029
  counting simple pgrep on script name with arguments with wc -l
3
  counting pgrep echo result with wc -w
2

我的问题是:

当我第一次运行脚本时,它只运行一次。所以 pgrep 只返回一个结果:123976,这很好。但是为什么 123976 上的“wc -l”会返回 2? 当我第二次运行脚本时,我得到了同样奇怪的行为:pgrep 返回正确的结果,pgrep | wc -l 返回错误,“echo pgrep ... | wc -w”返回正确结果。为什么?

【问题讨论】:

除了您要查找的命令之外,pgrep 命令是否有可能找到自己?您可以使用ps 进行检查,也可以使用| grep -v grep 从grep 命令中排除PID 来避免它。 顺便说一句,这似乎是特定于 Linux 的。我无法在 macOS 上重现。问题出在pgrep 还是wc,我不知道。 如果您在两个链接问题的54个答案中都找不到您想要的解决方案,请说明原因,您的问题可以考虑重新开放。 对不起,如果它听起来像重复,但我想避免“羊群”解决方案。无论如何,一切都很好,因为@kamilcuk 的回答帮助我理解了替换后的“两个进程”计数:) 【参考方案1】:

如何检测 bash 脚本是否已经在运行

如果您意识到您的方法的缺点,使用pgrep 看起来不错。请注意,$0$* 都可以在其中包含正则表达式语法的东西,你必须先将它们转义,我想我也会从一开始就使用 pgrep -f "^$0... 来匹配它。

为什么 123976 上的“wc -l”返回 2?

因为命令替换$(..) 会生成一个子shell,所以在执行pgrep 时会运行两个shell。

总的来说,echo $(cmd) 是一种反模式。只需运行它cmd

在某些情况下,例如当命令替换中只有一个命令时,bash 会优化并用命令本身替换 (exec) 子shell,从而有效地消除子shell。这是一个优化。这就是processes=$(pgrep ..) 返回 1 的原因。

为什么?

还有一个进程正在运行。

【讨论】:

但是echo $(pgrep ...)仍然只输出一个进程ID。

以上是关于考虑到它的参数,如何检测bash脚本是不是已经在运行[重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Bash 脚本中检测操作系统?

如何提取文件名并更改 bash 的结尾? [复制]

sh 查找传递给它的最后一个bash脚本参数

检查 Bash shell 脚本中是不是存在输入参数

如何将参数从 bash 传递到 php 脚本?

如何检测 Python 是不是在 Git Bash 终端或 Windows cmd 中运行?