为什么bash循环中向变量追加字符串的操作无法生效?
问题原因
你遇到的是Shell管道触发的子Shell变量作用域问题。
在Bash等绝大多数Shell实现中,管道符|连接的每一段命令都会运行在独立的子进程(子Shell)中,子Shell会继承父Shell的变量副本,但子Shell中对变量做的所有修改都仅在子进程内部生效,子进程执行结束后就会销毁,不会同步到父Shell的环境中。
你写的代码里while循环是管道的最后一段,运行在子Shell里,循环内给ALL_PIDS追加值的操作修改的是子Shell的局部变量,父Shell中声明的ALL_PIDS从头到尾都没有被赋值,所以echo输出为空。
解决方案
- 方案1:用进程替换替代管道,让
while循环运行在当前Shell中
# 先初始化变量 ALL_PIDS="" while read -r PID; do ALL_PIDS+="$PID " done < <(lsof +d /var/log/ | tail -n +2 | awk '{print $2}' | uniq) # 此时变量已正常赋值 echo "$ALL_PIDS"
- 方案2:直接捕获命令输出到变量,无需额外循环
ALL_PIDS=$(lsof +d /var/log/ | tail -n +2 | awk '{print $2}' | uniq | tr '\n' ' ')
- 方案3:如果你的最终目的是批量杀死这些进程,完全不需要先存变量,直接管道传递给
xargs即可,更简洁高效
# 先确认要杀的PID是否正确,可选执行 lsof +d /var/log/ | tail -n +2 | awk '{print $2}' | uniq # 批量杀进程,先使用默认TERM信号,杀不掉再换9信号 lsof +d /var/log/ | tail -n +2 | awk '{print $2}' | uniq | xargs kill
内容的提问来源于stack exchange,提问作者andrew
相关产品推荐
相关产品推荐

