我尝试将 bash 脚本的 shebang 从 迁移#!/bin/bash
到#!/usr/bin/env bash
,其中一些脚本被破坏,因为它们依赖于此代码来检查自身正在运行的现有实例,并且仅适用于#!/bin/bash
:
$ pidof -x myscript -o %PPID
我想知道的是如何可靠地检查调用的脚本是否env
正在运行,因为我尝试过的大多数解决方案都会涉及一些肮脏的正则表达式,并且最终仍然不可靠:
$ pgrep -f '(^|/)myscript(\s|$)'
考虑到我的脚本的路径是/home/user/myscript
,上面的代码可能会返回以下不需要的命令的 PID:
editor /home/user/myscript
bash /tmp/myscript
bash /home/user/myscript with spaces
答案1
在 Linux 上,您可以用来pgrep
获取可能嫌疑人的 PID,并检查这些 PID 的第一个参数(在 参考资料中提供/proc/$PID/cmdline
)。/proc/$PID/cmdline
包含进程的所有参数(包括参数 0),以 ASCII NUL ( \0
) 分隔。
就像是:
pgrep bash | xargs -I {} sed -nz '2{p; q}' /proc/{}/cmdline | grep -Fqzx "$0"
这假设您sed
和grep
支持以空分隔行。打印sed
相应文件的第二行cmdline
(参数 1),这将是脚本名称。grep
然后查找与您的脚本名称完全匹配的内容。你可以在 中完成整场比赛sed
,但我不想玩弄引号。
如果您通过不同的路径调用脚本,这将失败:
/home/user/myscript
cd /home; usr/myscript
myscript
但是,脚本名称中的空格应该是安全的。