如何以POSIX方式实现'set -o pipefail'-差不多完成了,需要专家的帮助 [英] How to implement 'set -o pipefail' in a POSIX way - almost done, expert help needed

查看:160
本文介绍了如何以POSIX方式实现'set -o pipefail'-差不多完成了,需要专家的帮助的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须以POSIX方式实现BASH set -o pipefail选项,以便它可以在各种LINUX/UNIX风格上运行.稍微说明一下,该选项使用户可以验证所有管道命令的成功执行.启用此选项后,如果cat失败,此命令cat app.log | grep 'ERROR'将失败,否则将抑制cat错误.

I have to implement the BASH set -o pipefail option in a POSIX way so that it works on various LINUX/UNIX flavors. To explain a bit, this option enables the user to verify the successful execution of all piped commands. With this option enabled this command cat app.log | grep 'ERROR' fails if cat fails, otherwise the cat error is suppressed.

因此,我在这里找到了一个非常不错的解决方案: http://cfaj.ca /shell/cus-faq-2.html

So, I found a really nice solution here: http://cfaj.ca/shell/cus-faq-2.html

      run() {
         j=1
         while eval "\${pipestatus_$j+:} false"; do
           unset pipestatus_$j
           j=$(($j+1))
         done
         j=1 com= k=1 l=
         for a; do
           if [ "x$a" = 'x|' ]; then
             com="$com { $l "'3>&-
                         echo "pipestatus_'$j'=$?" >&3
                       } 4>&- |'
             j=$(($j+1)) l=
           else
             l="$l \"\$$k\""
           fi
           k=$(($k+1))
         done
         com="$com $l"' 3>&- >&4 4>&-
                    echo "pipestatus_'$j'=$?"'
         exec 4>&1
         eval "$(exec 3>&1; eval "$com")"
         exec 4>&-
         j=1
         while eval "\${pipestatus_$j+:} false"; do
           eval "[ \$pipestatus_$j -eq 0 ]" || return 1
           j=$(($j+1))
         done
         return 0
       }

上述run()函数使用户可以通过以下方式调用管道命令:

The above-mentioned run() function enables the user to invoke the piped commands in such a way:

run cmd1 \| cmd2 \| cmd3

如果其中一个命令失败,则在$?

If one of the commands fails you get it in $?

但是,存在一个问题,它不支持管道之间的命令分组.我希望能够调用这样的内容:

There is a problem however, it does not support the grouping of commands between pipes. I want to be able to invoke something like this:

run echo "test" ; grep "test" \| awk '{print}'

当我这样做时,调用失败.我无法进行正确的修改来支持命令分组-对于我的bash技能而言,脚本有点太复杂了...

When I do it, the invocation fails. I cannot get the right modification to support the grouping of commands -- the script is a bit too complex for my bash skills...

有人可以帮忙吗?

谢谢!

推荐答案

键入时:

run echo "test" ; grep "test" \| awk '{print}'

使用参数echo"test"调用run;然后使用参数"test"|awk{print}调用grep.通常,grep不会找到任何名为|awk{print}的文件.

you invoke run with the arguments echo and "test"; then you invoke grep with arguments "test", |, awk and {print}. Typically, grep is not going to find any of the files called |, awk or {print}.

要根据需要调用run,您必须像使用|一样转义分号(并且您需要对&&||以及可能包含命令行的其他组件;对$(...)或反引号`...`的处理需要仔细考虑).

To invoke run as you wanted, you'd have to escape the semi-colon like you did the | (and you'd need to do things similarly for && or || or & and possibly other components of a command line; the handling of $(...) or backticks `...` needs to be thought about carefully).

如果您写:

run echo "test" \; grep "test" \| awk '{print}'

您至少会得到要用于run的所有参数.是否奏效尚有待商;.我还不了解您显示的run代码应该如何工作.

you will at least get all the arguments you intended to run. Whether it then works is debatable; I don't yet understand how the run code you showed is supposed to work.

[...稍后...]

它执行一些令人恐惧的I/O重定向,但是将由管道符号分隔的命令的每个段包装到一个单独的小象形文字包中.它假设用双引号引起来的参数正确中和了它,但这并不总是正确的(尽管很多时候它是正确的).

It does some fearsome I/O redirections, but wraps each segment of a command separated by a pipe symbol into a separate little packet of hieroglyphs. It assumes that wrapping double quotes around an argument neutralizes it correctly, which is not always true (though it is true a lot of the time).

这篇关于如何以POSIX方式实现'set -o pipefail'-差不多完成了,需要专家的帮助的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆