我在 bash 脚本中处理错误时遇到问题。到目前为止,我在 bash 中看到的错误处理解决方案似乎都不适用于此示例脚本:
#!/usr/bin/env bash
set -euo pipefail
eval $(do_stuff)
touch file
输出是:
./script.sh: line 4: do_stuff: command not found
但即便如此,它仍然愉快地继续并创建文件,这正是我想要禁止的。我想我可以将 stderr 通过管道传输到另一个程序,并在它获取一些输出时终止整个程序:
unbuffer ./script.sh 2>&1|{ while read stdin; do echo $stdin;killall -9 bash;done; }
然而,它大约只有 5% 的时间有效。在大多数情况下,它无法尽早终止脚本。
答案1
我想出了如何优雅地处理我发布的案例:
eval() {
if [[ -z "${@}" ]];then
exit 1
fi
builtin eval "$@"
}
它会覆盖默认的 eval() 实现,如果没有收到输入,则会退出。但我不会接受这个答案,因为它仍然没有回答这个问题的标题。
答案2
只需先将其更改为赋值,然后再评估即可。
示例1(输入命令无效则停止):
[xiaobai@localhost ~]$ cat h2.sh
#!/bin/bash
trap err_handler ERR
err_handler() { echo trapped ; exit; }
e2=$(echoasasas)
eval "$e2"
echo "next"
[xiaobai@localhost ~]$ sh h2.sh
h2.sh: line 5: echoasasas: command not found
trapped
[xiaobai@localhost ~]$
示例 2(如果输出不是有效命令则停止):
[xiaobai@localhost ~]$ cat h2.sh
#!/bin/bash
trap err_handler ERR
err_handler() { echo trapped ; exit; }
e2=$(echo xxxxx)
eval "$e2"
echo "next"
[xiaobai@localhost ~]$ sh h2.sh
h2.sh: line 6: xxxxx: command not found
trapped
[xiaobai@localhost ~]$
示例 3(继续运行下一个命令):
[xiaobai@localhost ~]$ cat h2.sh
#!/bin/bash
trap err_handler ERR
err_handler() { echo trapped ; exit; }
e2=$(echo ls)
eval "$e2"
echo "next"
[xiaobai@localhost ~]$ sh h2.sh
Android CRITICAL Documents
next
[xiaobai@localhost ~]$
示例 4(如果 STDERR 在另一个 shell 中触发,则一半):
[xiaobai@localhost ~]$ cat /tmp/so.sh
ls yyyyyy 2>/tmp/kas
[xiaobai@localhost ~]$ cat /tmp/kas
[xiaobai@localhost ~]$ cat h2.sh
#!/bin/bash
trap err_handler ERR
err_handler() { echo trapped ; exit; }
echo "before"
e2=$(/bin/bash /tmp/so.sh)
eval "$e2"
echo "next"
[xiaobai@localhost ~]$ sh h2.sh
before
trapped
[xiaobai@localhost ~]$ cat /tmp/kas
ls: cannot access 'yyyyyy': No such file or directory
[xiaobai@localhost ~]$