我正在运行下面的直接在 bash 命令行提示符下:
$ PIDS= ;while read name; do (cd $name; npm install) & echo started install; PIDS+=($!); done < <(\ls); for pid in ${PIDS[@]}; do wait $pid; done;
我明白了:
-bash: !: event not found
我假设该!
符号用于执行命令历史替换,而不是看到“$!”首先作为变量。
如果直接在 bash 命令行上运行,如何获取最后一个后台进程的 pid?
答案1
我无法用bash
4.3 和 4.4 重现您的问题,所以这里是一个通用答案。
您的问题是由!
in触发的PIDS+=($!)
,!
它是历史替换的开始(默认情况下通过交互式 shell 启用)。
要么用 禁用历史记录替换set +H
,要么引用!
(由于前面的内容,此处不合需要$
),或者在 后面添加一个空格!
。 Bash 手册如下:
!
启动历史替换,除非后面跟有空格、换行符、回车符,=
或者(
(当使用内置 shopt 启用 extglob shell 选项时)
然后你的命令行将变成:
PIDS=()
while read name; do
(cd "$name"; npm install) &
echo started install
PIDS+=( $! )
done < <(\ls)
wait "${PIDS[@]}"
笔记:
- 你不限于这里的一行代码
- 我在变量周围添加了正确的引号
- 您可以同时等待多个 PID;我修好了
答案2
来自bash 变更日志:
本文档详细介绍了此版本 bash-4.2-alpha 与之前版本 bash-4.1-release 之间的更改。 (……)
3. Bash 中的新功能 (...)
u。历史扩展不再扩展
$!
变量扩展。
为了应对旧版本的 bash,请更改PIDS+=($!)
为PIDS+=($! )
.额外的空间确保 bash 永远不会认为这!
会启动历史引用。