我想编写一小部分脚本来保存错误状态,执行一些其他代码,并将错误状态设置为原始错误状态。在 Bash 中它看起来像这样:
<< some command >>; _EXIT=$?;( <<other code here>> ;exit $_EXIT)
但我需要的代码无论是在 bash、zsh、csh 还是 tcsh 下运行都可以运行。我事先不知道会使用哪个shell,因为这是由用户决定的。用户还决定<<某个命令>>。
可以安全地假设 << other code >> 将在所有 shell 中工作,但假设您可以写入文件则不安全(因此将其放入文件中将不起作用)。
背景
GNU Parallel 在用户决定的 shell 中执行用户给出的命令。命令完成后,GNU Parallel 需要进行一些清理工作。同时GNU Parallel需要记住用户给出的命令的退出值。上面代码片段之前运行的代码是用户给出的命令。 <<其他代码>>是清理代码。
答案1
这个答案适用于类似 bash 的 shell 和类似 csh 的 shell,并且不需要 perl:
sh -c '<< other code >>; [ "$0" != "" ] && exit "$0"; exit "$1"' "$?" "$status"
或者您可以添加虚拟/焊盘参数:
sh -c '<< other code >>; [ "$1" != "" ] && exit "$1"; exit "$2"' foo "$?" "$status"
则测试可改为[ ! -z "$0" ]
(或"$1"
)。我不知道它是否适用于 zsh 或 Fish。我熟悉的每个 shell 都会 在解析命令时进行评估,并将它们作为参数传递给$?
命令。 shell将它们分配给最后两个位置参数。当“其他代码”完成时,shell 将检查从中获取其值的位置参数,看看它是否为空或非空,并以适当的位置参数值退出。$status
sh -c
sh
$?
如果环境 shell 使用$?
或以外的其他内容$status
来保存退出状态,则此操作将会失败。如果 shell 允许$?
设置(非空),如果它不是退出状态,或者是$?
一个无效的字符序列,导致整个命令作为语法错误被拒绝,它也会失败。
答案2
使用perl:
perl -e '$a=shift; `<< other code >>`; exit $a' $? # Fails in csh
编辑这也适用于 csh(以及 zsh、tcsh、sh、pdksh、ksh93 - 尽管不是 Fish):
perl -e '$a=shift; `<< other code >>`; $a=~s/h// and exit $a; exit shift' "$?h" "$status"