【问题标题】:Bash return code error handling when using heredoc input使用heredoc输入时的Bash返回码错误处理
【发布时间】:2020-02-12 02:07:47
【问题描述】:

动机

我的情况是,我必须通过一次 bash 调用运行多个 bash 命令,而无法编写完整的脚本文件(用例:Passing multiple commands to a container in Kubernetes)。 common solution 是将命令与;&& 组合在一起,例如:

bash -c " \
echo \"Hello World\" ; \
ls -la ; \
run_some_command "

在实践中,编写这样的 bash 脚本很容易出错,因为我经常忘记分号会导致细微的错误。

this question 的启发,我尝试使用heredoc 以更标准的风格编写脚本:

bash <<EOF
echo "Hello World"
ls -la
run_some_command
EOF

不幸的是,我注意到使用 heredoc 时退出代码错误处理存在差异。例如:

bash -c " \
run_non_existing_command ; \
echo $? "

输出(注意$? 正确捕获了退出代码):

bash: run_non_existing_command: command not found
127

bash <<EOF
run_non_existing_command
echo $?
EOF

输出(请注意,与标准脚本执行相比,$? 无法捕获退出代码):

bash: line 1: run_non_existing_command: command not found
0

为什么heredoc 版本的行为不同?是否可以以heredoc 样式编写脚本并保持正常的退出代码处理?

【问题讨论】:

  • for instance: - 您的实例不组合命令(至少不是以我定义“组合”的方式),它运行 bash -c echo "Hello World" 然后运行 ​​ls -larun_some_command,所有在父壳中。我认为您缺少 \ 斜杠
  • @KamilCuk 正确修复,谢谢!复制粘贴错误,部署到 Kubernetes 时 `` 是通过 YAML 多行字符串处理的......观察结果应该仍然有效。
  • 不,这不是一回事。可能同样的事情是bash -c "echo \"Hello World\" ; ls -la ; run_some_command ;"

标签: linux bash shell heredoc


【解决方案1】:

为什么heredoc版本的行为不同?

因为$?在运行命令之前已经展开。

下面会输出1,即false命令的退出状态:

false
bash <<EOF
run_non_existing_command
echo $?
EOF

原理和下面一样,会打印5:

variable=5
bash <<EOF
variable="This is ignored"
echo $variable
EOF

是否可以用heredoc风格编写脚本并保持正常的退出代码处理?

如果您想让$? 在子shell 内展开,那么:

bash <<EOF
run_non_existing_command
echo \$?
EOF

bash <<'EOF'
run_non_existing_command
echo $?
EOF

还要注意:

bash -c \
run_non_existing_command ;
echo $? ;

正好等于:

bash -c run_non_existing_command
echo $?

echo $? 不在bash -c 内部执行。

【讨论】:

  • 有趣,有没有一个简单的解释为什么引用EOF 摆脱了逃避$? 的必要性?
  • 是的,它就是这样设计的。见posix shell 2.7.4 Here-DocumentIf any character in word is quoted, .... the here-document lines shall not be expanded.
猜你喜欢
  • 2011-04-17
  • 2012-01-12
  • 2015-03-14
  • 2016-10-28
  • 2018-07-29
  • 2020-07-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多