![如果反引号运算符失败,如何打印并退出 bash](https://linux22.com/image/94310/%E5%A6%82%E6%9E%9C%E5%8F%8D%E5%BC%95%E5%8F%B7%E8%BF%90%E7%AE%97%E7%AC%A6%E5%A4%B1%E8%B4%A5%EF%BC%8C%E5%A6%82%E4%BD%95%E6%89%93%E5%8D%B0%E5%B9%B6%E9%80%80%E5%87%BA%20bash.png)
我有getinfo.sh
它要么打印信息,要么以代码 1 存在。
我想将此脚本的结果存储在 bash 变量中,否则打印错误消息并退出。
如果我运行这个
#!/bin/bash
X=`getinfo.sh` || echo "failed" && exit 1
那么即使成功,脚本也会退出getinfo.sh
(在这种情况下,它什么也不打印。
另一方面
X=`getinfo.sh` || (echo "failed" && exit 1)
对于我来说,这是有道理的,因为我来自类似 C 语言的语言,但是不是退出脚本,因为括号创建了一个新的内壳,并且退出的是内壳,外壳继续运行。
如果失败,如何存储getinfo.sh
打印并退出的输出?
答案1
(...)
不是(主要)团体命令,而是启动一个子 shell。所以exit
in(echo failed && exit 1)
只退出子 shell。
要对命令进行分组而不在子 shell 中运行它们,您可以使用{ ...; }
:
X=`getinfo.sh` || {
echo >&2 "failed"
exit 1
}
虽然在这里,我宁愿使用:
if ! x=$(getinfo.sh); then
echo >&2 failed
exit 1
fi
另请注意,echo failed && exit 1
如果本身失败,则可能无法退出echo
,例如,当 stdout 是完整文件系统上的文件时,或者忽略 SIGPIPE 的损坏管道,或者 stdout 已关闭,或者已达到 SIGXFSZ 的文件大小限制时,可能会发生这种情况忽略...
答案2
您可以使用大括号将命令组合在一起,而无需创建子 shell。
X=$(getinfo.sh) || { echo "failed" && exit 1; }
{ list; }
将命令列表放在大括号之间会导致该列表在当前 shell 上下文中执行。没有创建子shell。后面的分号(或换行符)列表是必须的。
注意:对于命令替换,反引号实际上已被弃用,因此我使用了更现代的$()
语法。
答案3
既然您正在设置变量的值,为什么不检查变量的值并在不合适时退出呢?
X=`getinfo.sh`
[ -z "$X" ] && echo "failed" && exit 1
这假设getinfo.sh
失败时返回空(如果长度为零,则退出),但您可以根据失败时返回的X
内容修改检查。getinfo
或者更恰当地说,检查以确保X
包含您正在查找的数据类型。
答案4
最简单的方法是将 -e 添加到你的 shebang 中:
#!/bin/bash -e
这意味着脚本将在出现第一个错误时停止。由于您使用反引号,因此如果有任何错误消息,您可能会在标准输出中看到它。
如果您确实想使用 echo-and-exit 方法,我会编写一个单独的函数来调用,它总是打印一些错误消息并立即退出。了解如何编写 bash 函数(它们非常简单)。