$!在命令行上不起作用

$!在命令行上不起作用

我正在运行下面的直接在 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

我无法用bash4.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 永远不会认为这!会启动历史引用。

相关内容