【问题标题】:Ignoring specific exit code in Bash忽略bash中的特定退出代码
【发布时间】:2022-05-08 02:53:01
【问题描述】:

注意:问题不重复Ignoring specific errors in a shell script


假设需要捕获文件编码表示的前导字符。

在 shell 中(在 Bash 中测试),很容易使用以下形式:

encoded="$(< file base64 | head -c16)"

需要的语句功能,除非对环境进行某些更改。

考虑以下几点:

set -o errexit -o pipefail
shopt -s inherit_errexit
encoded="$(< file base64 | head -c16)"

最后一行将导致脚本终止,因为base64 给出的非零返回状态 (141),对关闭的管道不满意。返回状态传播到管道,然后传播到调用外壳。

不良影响需要解决方法,如下所示:

set -o errexit -o pipefail
shopt -s inherit_errexit
encoded="$((< file base64 || :) | head -c16)"

: 与关键字 true 具有相同的效果,以评估为非错误。

但是,这种方法会导致进一步的不良影响。

以下显示了具有不同错误的变体:

set -o errexit -o pipefail
shopt -s inherit_errexit
encoded="$((< /not/a/real/file base64 || :) | head -c16)"
echo $?

打印的代码为零。现在,一个真正的错误已被掩盖。

最明显的解决方案如下,相当冗长

set -o errexit -o pipefail
shopt -s inherit_errexit
encoded="$((< /not/a/real/file base64 || [ $? == 141 ]) | head -c16)"
echo $?

有更紧凑的表格吗?是否有任何可用的环境更改,使得语句只掩盖特定的状态代码,而没有显式的内联表达式?

【问题讨论】:

  • 我怀疑还有什么更好的。区分不同的退出代码比较少见,因此没有捷径可走。
  • 您的解决方案似乎不错;如果你经常使用不守规矩的命令,那么你可以定义一个函数mybase64() { base64 "$@" || [[ $? == 141 ]]; }
  • 我认为你不需要圆括号,这会导致进程分叉。花括号应该足够了。
  • @ceving:您能否为这个想法推荐一个可行的例子?我还没有发现。
  • 您需要重定向作为输入吗?对于@ceing 的含义,我猜是:encoded="$( { base64 $1 ; } | head -c16)"$1 作为文件。

标签: linux bash unix scripting


【解决方案1】:

首先,显然,要真正引发 141 错误,文件需要相当大,例如

head -c 1000000 /dev/urandom > file

现在,正如您所说,此脚本 sh.sh 将在显示 encoded: ... 之前终止:

#!/bin/bash
set -o errexit -o pipefail
shopt -s inherit_errexit

encoded="$(< file base64 | head -c16)"

echo "encoded: $encoded"

您可以通过调用 ^cat > /dev/nullafterhead 让 base64 继续将其其余数据通过管道传输到 /dev/null,而不是检查错误代码:

#!/bin/bash
set -o errexit -o pipefail
shopt -s inherit_errexit

encoded="$(< file base64 | ( head -c16 ; cat > /dev/null ) )"

echo "encoded: $encoded"

现在你会得到encoded: NvyX2Zx4nTDjtQO8 或其他任何东西。

这不会掩盖其他错误,例如文件不存在:

$ ./sh.sh
./sh.sh: line 5: file: No such file or directory

但是,由于会读取整个文件,因此效率会降低。

【讨论】:

    【解决方案2】:

    对于您的特定示例程序,您也可以更改您的方法。 16 个 base 64 字符代表 16 * 6 = 96 位,因此需要文件中 96/8 = 12 个字节的数据:

    encoded="$(head -c12 file | base64)"
    

    这不会导致 SIGPIPE。

    【讨论】:

    • 是的,这可能是真的,但问题是关于 shell 的一般工作原理,而不是任何特定的命令。
    猜你喜欢
    • 2023-01-26
    • 2021-11-12
    • 1970-01-01
    • 2017-12-23
    • 1970-01-01
    • 2017-03-29
    • 2010-10-20
    • 1970-01-01
    • 2013-04-27
    相关资源
    最近更新 更多