pgrep
这是我的行为自由BSD脚本:
luis@Balanceador:~/Temporal$ cat test.sh
#!/usr/bin/env bash
pgrep -fl "test.sh"
luis@Balanceador:~/Temporal$ ./test.sh
luis@Balanceador:~/Temporal$
无输出。这是:脚本本身是没有检测到作为跑步。就像 的命令行行为一样pgrep
。这对我来说很好。
这就是Linux(Ubuntu)案例:
luis@Terminus:~/Temporal$ cat test.sh
#!/usr/bin/env bash
pgrep -fl "test.sh"
luis@Terminus:~/Temporal$ ./test.sh
4514 bash
luis@Terminus:~/Temporal$
可以看出,test.sh
脚本本身似乎是检测到作为一个正在运行的进程。
我正在开发一个 shell (Bash)脚本那必须能够停止并等待如果另一个例子它的(同名)被检测到,并且必须在 Linux 和 FreeBSD 上工作,所以我想为此同质化 pgrep 命令。
有什么办法可以让两个人都表现得好相同?
grep
任何类似或接受的衍生品的答案ps
。
已测试:
-x
(确切的)开关来自手册页,但不适用于参数在脚本上(或者我不明白如何使其工作)。在这种情况下,参数对于检测并不重要(它们可以是任何参数);我只需要检测主“.sh”脚本。
进一步说明:
- 请不要回答“使用文件锁定”之类的问题。其实我想了解一下这个
pgrep
工具。
答案1
FreeBSDpgrep
排除了进程的祖先pgrep
,包括运行它的脚本实例。 Linuxpgrep
没有相应的功能。
您可以手动排除脚本实例。要排除的进程 ID 位于$$
.您确实需要小心一点,避免使用任何子 shell:最简单的方法pgrep … | grep -v "^$$ "
可能会列出管道的右侧(如果在调用pgrep
之前恰好在进程列表中到达它)grep
。
instances=$(pgrep -fl "test.sh")
if [[ "$instances" =~ (.*)$'\n'"$$ "[^$'\n']*$'\n'(.*) ]]; then
instances=${BASH_REMATCH[1]}$'\n'${BASH_REMATCH[2]}
elif [[ "$instances" =~ (^|.*$'\n')"$$ "[^$'\n']*($|$'\n'.*) ]]; then
instances=${BASH_REMATCH[1]}${BASH_REMATCH[2]}
fi
答案2
只需添加x
到标志中:
#!/usr/bin/env bash
pgrep -flx "pgrep.sh"
在 Ubuntu 中测试,它不会在输出中打印任何内容(如果这是你想要的!)。