- 论坛徽章:
- 60
|
本帖最后由 reyleon 于 2013-11-28 20:19 编辑
http://www.unix.com/showthread.php?p=302265010- ======================================================================
- 13. How do I get the exit code of cmd1 in cmd1|cmd2
- First, note that cmd1 exit code could be non-zero and still don't
- mean an error. This happens for instance in
- cmd | head -1
- you might observe a 141 (or 269 with ksh93) exit status of cmd1,
- but it's because cmd was interrupted by a SIGPIPE signal when
- "head -1" terminated after having read one line.
- To know the exit status of the elements of a pipeline
- cmd1 | cmd2 | cmd3
- a. with zsh:
- The exit codes are provided in the pipestatus special array.
- cmd1 exit code is in $pipestatus[1], cmd3 exit code in
- $pipestatus[3], so that $? is always the same as
- $pipestatus[-1].
- b. with bash:
- The exit codes are provided in the PIPESTATUS special array.
- cmd1 exit code is in ${PIPESTATUS[0]}, cmd3 exit code in
- ${PIPESTATUS[2]}, so that $? is always the same as
- ${PIPESTATUS: -1}.
- c. with any other Bourne like shells
- 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
- `
- d. with a POSIX shell
- You can use this function to make it easier:
- 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
- }
-
- use it as:
-
- run cmd1 \| cmd2 \| cmd3
- exit codes are in $pipestatus_1, $pipestatus_2, $pipestatus_3
- ======================================================================
复制代码 |
|