Zsh环境下如何获取子shell中首个非后台运行命令的PID
Zsh环境下获取嵌套子shell中sleep进程PID的解决方案
问题原因说明
你执行的带括号包裹的命令会启动一个独立的子shell在后台运行,$!和jobs -p返回/列出的都是这个顶层子shell的PID,不会包含子shell内部启动的sleep进程,因此无法直接拿到目标sleep的PID。
可行解决方法
方法1:通过顶层子shell PID追溯(执行命令后立即操作首选)
执行完原命令后第一时间拿到顶层子shell的PID:
subshell_pid=$!
再通过父PID过滤出该子shell启动的sleep进程:
sleep_pid=$(pgrep -P $subshell_pid sleep)
确认PID无误后即可终止:
kill $sleep_pid
方法2:进程特征过滤(错过拿$!的时机时使用)
如果已经过了获取$!的时机,可以通过sleep的执行参数匹配,你的场景下sleep时长为100秒,可以直接过滤:
sleep_pid=$(ps -eo pid,command | awk '$2=="sleep" && $3=="100" {print $1}')
如果存在多个sleep 100的进程,可以结合进程树进一步过滤:
pstree -p $$ | grep 'sleep(100)'
从输出中提取对应PID即可。
方法3:提前预埋PID记录(后续避免同类问题的方案)
后续执行同类嵌套后台命令时,可以直接把sleep的PID写入临时文件,随时可以读取:
# 修改后的启动命令 ( sleep 100 & echo $! > /tmp/my_sleep.pid ; wait ; program1 & another program & another ) & # 需要终止时直接读取PID kill $(cat /tmp/my_sleep.pid)
注意事项
- 如果pgrep返回多个结果,建议先执行
ps -p $sleep_pid -f确认进程匹配度,避免误杀其他进程 - 不要随意使用
kill -9终止sleep进程,常规TERM信号(默认kill的信号)即可正常终止sleep,避免产生僵尸进程
内容的提问来源于stack exchange,提问作者Stack
相关产品推荐
相关产品推荐

