Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the correct value of `$?` in a pipeline?

Tags:

bash

shell

sh

ksh

zsh

I was a bit disturbed to find the following behavior:

bash$ false
bash$ true | echo $?
0
bash$ ksh
ksh$ false
ksh$ true | echo $?
0
ksh$ zsh
zsh$ false
zsh$ true | echo $?
1

Intuitively, it looks like zsh gets it right while bash and ksh are wrong. $? is 'the exit status of the most recently executed pipeline', which in each case should be 1. Note that false | echo $? also prints 0 in both ksh and bash. Is the standard flexible on this point (ie, the behavior is unspecified), or are bash and ksh non-compliant here? I'm also curious to know what bash and ksh are doing to get this wrong.

$ bash --version
GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin11)
Copyright (C) 2007 Free Software Foundation, Inc.
$ zsh --version
zsh 4.3.11 (i386-apple-darwin11.0)
$ ksh --version
  version         sh (AT&T Research) 1993-12-28 s+
like image 836
William Pursell Avatar asked Apr 18 '15 12:04

William Pursell


1 Answers

POSIX says:

$? Expands to the decimal exit status of the most recent [command or] pipeline ...

Please note the comment from @lurker. Bash in it's current version 4.3.11 behaves the same as zsh.

What happens in bash and zsh is that $? will be set by the command before the pipe and get not changed inside the pipe. That's why the expected the result is the return value from false -> 1. And this is what POSIX specifies.

I couldn't find any documentation that describes the ksh behaviour. I can only assume that ksh resets $? before executing the pipe, since the following code works:

#!/bin/ksh
false
ret=$?
true | echo "$ret"

Probably this should get filed as a bug in ksh. However, I'm not sure if this behaviour is specified exactly enough by POSIX.

like image 74
hek2mgl Avatar answered Nov 15 '22 13:11

hek2mgl