当我启动 shell 时,在我的例子中是 bash 和/或 zsh,我需要向 .zshrc 和/或 .bashrc 添加哪些行来检查程序是否已经在运行,以及程序是否尚未运行,启动它?
示例:我正在启动一个新的 zsh shell。如果 top 尚未运行,我想启动 top 并让它接管 shell。如果 top 已经在另一个窗口中运行,我希望 .zshrc 继续加载并给我一个打开的终端。
6-16更新:
if ! pgrep -U $USER top >/dev/null; then
exec top
fi
上面的脚本满足了我的要求。 -q 标志对我不起作用,因为 -q 不是我的系统上的选项。所以我必须将 PID 通过管道传输到 /dev/null。谢谢 mveroone、Kusalananda 和 Thomas Dickey。
我有一些功能蔓延超出了原始问题的范围。假设我在单用户系统上,无需输入密码即可成为 root 用户。如果需要的话,我如何以root身份自动运行top?
6-18 好的,以 root 身份传递命令的功能蔓延问题已解决。我用它来启动几个
感谢您所有深思熟虑的回复。
答案1
pgrep
像这样使用:
if ! pgrep -u $USER top >/dev/null 2>&1; then
exec top
fi
解释:
pgrep
如果发现该命令正在运行,则实用程序将以零退出代码退出。因此,否定该测试。- 还可以使用 来将其限制为当前用户
-u $USER
,这样它就不会因为某种原因而获取其他人的进程。$USER
是一个标准的 shell 变量。如果由于某种原因未定义,请尝试使用$LOGNAME
,如果失败,请使用$( id -n -u )
(但此时您必须问自己发生了什么事,因为$LOGNAME
是还标准 shell 变量)。 - 我们不需要 的输出
pgrep
,因此将标准输出和错误流重定向到/dev/null
。
如果top
(或其他)未发现正在运行,则exec
根据OP的问题,它会替换外壳。
这应该适用于所有sh
兼容的 shell。
编辑:pgrep
BSD 系统(OS X,OpenBSD,...)上的实现有一个-q
选项可以让它丢弃任何输出,但pgrep
Linux 上显然没有这个标志。在 BSD 系统上,使用这个而不是稍微难看的重定向到/dev/null
.
答案2
如果程序始终从 shell 启动并且您可以完全控制它(即它没有在第 3 方程序中硬编码),那么您可以使用某种锁定机制,例如lockfile
或flock
。例如通过添加
flock -n /tmp/top -c top
到.bashrc
/.zshrc
您将确保只有 shell 的第一个实例将运行该top
命令(除非您杀死它,然后将启动另一个实例)。
您可能想要创建一个函数,以便能够手动启动命令(不仅仅是在 shell 初始化时):
mytop () { flock -n /tmp/$0 -c top; }
mytop
只要你想跑就跑。
答案3
同意这pgrep
是要走的路,但也存在一些陷阱。您不需要使用该-q
选项,因为您可以重定向输出pgrep
来消除该问题:
pgrep -U $USER top >/dev/null || exec top
陷阱在于它不是标准实用程序,因此您必须记住它可能不可移植。以下是一些帮助页面链接:
环境USER
变量更加完善,但似乎不在 POSIX 的 shell 列表中(请参阅2.5.3 Shell 变量)。相反,它指出这USER
是已知正在使用的许多变量之一(参见注释8.1 环境变量定义)。
这运行top
为你自己, 当然。如果您选择让它运行为根,然后您可以将 更改$USER
为然后使用(首选)或root
运行。 POSIX 中都不存在(top
sudo
su
查看列表)。后者 ( su
) 在类 Unix 系统上随处可用,但sudo
通常是首选。所以你会有
pgrep -U root top >/dev/null || exec sudo top
除非您已配置sudo
为不需要密码,否则 shell 启动时将提示您输入密码top
。
答案4
我会在我的 .zshrc (或其他)中附加这样的片段:
if pgrep -u $USER 程序名 然后 执行程序名 菲
警告 :我还没有测试过这段代码。请不要在 root 或服务器上唯一的用户上使用它。确保失败时可以恢复。