There are differences though between different types of shell and I want to show this behaviour and its consequences , in particular how common expectations might be met or not, and also suggest solutions.
Here is my example. It is a simple script: a command pipeline consisting of a printf (printing two lines) followed by a while, wrapped by a starting and closing echo
echo Before pipeline printf "text1\ntext2\n" | while read line ; do # Do something useful with 'line' echo $line done echo After pipelineand the output - with whichever shell - is
Before pipeline text1 text2 After pipeline
Now let's modify this script and add an exit into the while loop so that it looks like this
echo Before pipeline printf "text1\ntext2\n" | while read line ; do # Do something useful with 'line' echo $line exit 1 done echo After pipelineAs artificial as this example might look you can simply assume that there are more complex things happening in the while loop and under certain conditions one might want to exit the loop.
Here are the results for bash and Korn shell ksh
bash #!/bin/bash | ksh #!/bin/ksh |
---|---|
Before pipeline text1 After pipeline | Before pipeline text1 |
Exit code: 0 | Exit code: 1 |
Common behaviour: both shells leave the loop and neither prints the second line 'text2' | |
bash continues with the commands after the while loop (and exits with the result of the last 'echo' command) | ksh exits the whole script |
While the behaviour of ksh seems more natural (exit means exit everything) the bash behaviour can be explained when considering that the while loop is a sub shell with its own scope as if it would be a separate shell script. Exiting the loop means to return to the parent. This also means that the parent script can capture this exit code and thus the solution is a check after the loop.
echo Before pipeline printf "text1\ntext2\n" | while read line ; do # Do something useful with 'line' echo $line exit 1 done [ $? -ne 0 ] && echo ERROR && exit 2 echo After pipelineThe result for bash: exit code 2 and the output
Before pipeline text1 ERRORThe exit code check line is meaningless for ksh since it will never be reached.
I've seen plenty of bash scripts with similar constructs where the author coded a quick 'exit' line into the while loop but forgetting to check the result, probably assuming the ksh behaviour.
No comments:
Post a Comment