Bash 从标准中读取行时完成时没有失败

Bash While readline from standard in with no failure upon completion

在 bash 中,如果我编写一个执行以下操作的脚本,

while read -r line </dev/stdin; do 
...
done | parallel do_something_else

效果很好。没有错误。

但是,当我将脚本放入 make 配方时,make 认为脚本因错误而失败...大概是因为 while 循环在 stdin 结束时失败了。

如何在到达输入末尾时逐行读取 stdin 中的所有行而不返回失败条件?

make 将 运行 每个命令放在单独的 shell 中。考虑:

$ cat Makefile
separate:
    echo $$$$
    echo $$$$

together:
    echo $$$$; \
    echo $$$$

$ make separate
echo $$
87214
echo $$
87215

$ make together
echo $$; \
    echo $$
87223
87223

请记住,在类似伯恩的 shell(我的默认设置是 bash)中,$$ 扩展为 shell 的 PID。但是由于 $Makefile 中也是特殊的,我们必须用它的转义版本 $$ 替换每个 $。因此 $$ 变成了 $$$$,两个美元符号都被替换了。

together 目标中,我添加了尾随 \ 来防止这种行为。连接这些行后,我还必须在 echo 之间添加一个 ;

如果 make 中的任何一个步骤(即单独的命令)失败,make 将在该点失败。因此,如果作业要成功,每个命令都必须 return 0。但是请注意,在大多数错误情况下,您可能 想要 make 失败。我通常会使用 if 条件来处理 bash 脚本中的这些情况,然后使用 -e 执行脚本,以便显示脚本中的任何错误。

鉴于这些要求和这种行为,我得出结论,到目前为止,编写和调试将由 make 执行的 shell 命令的最简单方法是将其放在一个单独的可执行文件:

$ cat t.sh
#!/bin/bash -e
echo $$
echo $$

$ ls -l ./t.sh
-rwxr-xr-x  1 danfarrell  staff  31 Dec 26 16:35 ./t.sh

$ cat Makefile
script:
    ./t.sh

$ make script
./t.sh
88593
88593

然后您可以选择使用您在 shell 脚本完成时选择的退出代码退出。当您希望 make 认为执行成功时退出 0