Unix Shell,使用管道子进程获取退出代码

7

假设我在Unix Shell中执行以下操作:

$ some-script.sh | grep mytext

$ echo $?

这将给我grep的退出代码。

但是我如何获取some-script.sh的退出代码?

编辑

假设管道操作是不可变的。也就是说,我无法将其分开并分别运行两个命令。

5个回答

5

有多种解决方案,具体取决于您想要做什么。

最简单和易于理解的方法是将输出发送到一个文件,然后保存退出代码后进行grep:

tmpfile=$(mktemp)
./some-script.sh > $tmpfile
retval=$?
grep mytext $tmpfile
rm tmpfile

3
我明白了。也许这是一个解决方案:tmpfile=$(mktemp); (./some-script.sh; echo $? > $tmpfile) | grep mytext; retval=$(cat $tmpfile)。虽然有点不太规范,但或许可以有所帮助。 - watain
然هگژgrepèژ·هڈ–echo $? > tmpfileçڑ„输ه‡؛ - Mike
不行,因为 echo $? > $tmpfile 没有输出。echo 的标准输出被发送到 $tmpfile - watain
正确的做法是,确保没有任何内容被传递给grep命令,这样它就不会将第一个命令的输出附加在后面。 - Mike
我不确定我是否正确理解了。第一个命令(./some-script.sh)的输出仍然会传递给grep。你试过了吗?也许你可以添加实际的脚本和为什么管道操作是不可变的问题。 - watain

4

来自comp.unix.shell FAQ(#13)的一个技巧解释了如何在Bourne shell中使用管道帮助实现您想要的功能:

   You need to use a trick to pass the exit codes to the main
   shell.  You can do it using a pipe(2). Instead of running
   "cmd1", you run "cmd1; echo $?" and make sure $? makes it way
   to the shell.

   exec 3>&1
   eval `
     # now, inside the `...`, fd4 goes to the pipe
     # whose other end is read and passed to eval;
     # fd1 is the normal standard output preserved
     # the line before with exec 3>&1
     exec 4>&1 >&3 3>&- 
     {
       cmd1 4>&-; echo "ec1=$?;" >&4
     } | {
       cmd2 4>&-; echo "ec2=$?;" >&4
     } | cmd3
     echo "ec3=$?;" >&4

2

如果你正在使用bash:

PIPESTATUS
    An array variable (see Arrays) containing a list of exit status values from the processes in the most-recently-executed foreground pipeline (which may contain only a single command). 

我正在使用 sh。我的客户不喜欢 bash。 - Mike

2

有一个实用程序叫做mispipe,它是moreutils软件包的一部分。

它的作用就是:mispipe some-script.sh 'grep mytext'


0

第一种方法是将退出状态暂时保存在某个文件中。这会导致您必须使用大括号创建子shell:

(your_script.sh.pl.others; echo $? >/tmp/myerr)|\ #subshell with exitcode saving
grep sh #next piped commands
exitcode=$(cat /tmp/myerr) #restore saved exitcode
echo $exitcode  #and print them

另一种由Randy提出的方法,代码实现更简单:

some-script.sh | grep mytext
echo ${PIPESTATUS[0]} #print exitcode for first commands. tables are indexted from 0

就这些。两种方法都在bash下工作(我知道,这是一个bash主义者)。祝好运 :) 这两种方法都没有将临时管道保存到物理文件中,只有退出代码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接