pgrep匹配非预期进程问题:为何bash脚本被识别为tmux进程?
问题:pgrep误将含tmux参数的bash进程识别为tmux进程的原因
以下是一个用于判断是否运行tmux的脚本雏形(已为调试目的修改,测试时从未运行tmux实例):
#!/bin/bash -x if [[ -n "$TMUX" ]]; then echo "We are inside tmux" exit 1 fi if [[ $(pgrep -c tmux) -ne 0 ]]; then echo "joining tmux session" tmux a exit 0 fi bash
操作步骤与现象
- 在终端1中运行脚本:
alacritty -e ~/tmux.sh - 终端2中的输出:
+ [[ -n '' ]] ++ pgrep -c tmux + [[ 1 -ne 0 ]] + echo 'joining tmux session' joining tmux session + tmux a no sessions + bash [user@hostname ~]$ pgrep -a tmux 27220 /bin/bash -x /home/user/tmux.sh
预期与疑问
我预期条件应为[[ 0 -ne 0 ]](即条件不成立),pgrep不应将/bin/bash -x /home/user/tmux.sh识别为tmux进程——我要查找的是tmux进程,而非参数中包含tmux字符串的进程。
此外,若在一个终端运行vim ~/tmux.sh,在另一个终端执行pgrep -c tmux会返回0(此时无tmux实例运行),可见该行为并不一致。
为何会出现这种差异?
系统与环境更新
- 更新1:系统信息
- alacritty 0.13.2 (bb8ea18e)
- bash 5.2.26(1)-release
- pgrep来自procps-ng 4.0.4
- archlinux
- 更新2:直接用sh/bash运行脚本时,pgrep表现符合预期;仅当通过
alacritty -e ~/tmux.sh启动时才会出现该异常行为。 - 更新3:使用foot或xterm终端执行
foot ~/tmux.sh时也会出现此问题。
原因分析与解决方案
核心原因
pgrep默认会匹配进程的命令名(argv[0])以及整个命令行参数,但这里的差异来自于进程的argv[0]不同:
- 直接用bash运行脚本时,bash的
argv[0]是bash,脚本路径作为参数传入,pgrep搜索tmux时不会匹配到。 - 通过终端
-e参数启动脚本时,终端会将脚本路径设置为bash的argv[0](即进程命令名显示为/home/user/tmux.sh),此时pgrep tmux会匹配到命令名中的tmux字符串,导致计数为1。
而用vim ~/tmux.sh时,vim的argv[0]是vim,参数里的tmux.sh不会被pgrep默认匹配——procps-ng的pgrep在默认搜索短名称时,只会匹配argv[0]最后一个斜杠之后的部分以及进程可执行文件路径,因此不会误判。
解决方案
要让pgrep只匹配tmux的可执行进程,可采用两种方式:
- 精确匹配命令名:添加
-x参数,强制匹配argv[0]完全等于tmux的进程
if [[ $(pgrep -cx tmux) -ne 0 ]]; then echo "joining tmux session" tmux a exit 0 fi
- 匹配可执行文件路径:用
-f结合正则限定tmux的可执行路径,避免误匹配
if [[ $(pgrep -c -f '^/usr/bin/tmux') -ne 0 ]]; then echo "joining tmux session" tmux a exit 0 fi
验证
修改脚本后,用alacritty -e ~/tmux.sh启动,pgrep -cx tmux会返回0,符合预期,不会再触发错误的tmux a操作。
内容的提问来源于stack exchange,提问作者simbioz
相关产品推荐
相关产品推荐

