Reputation: 31
The following switch statement has strange behavior:
3)
if [ $state -ne $last_state ]
then
echo "state: $state"
fi
stty -F $SERIAL $BAUD -echo igncr
echo "befor cat"
{
cat -v $SERIAL >> $USBDRIVE/gpsData_$filecounter.txt && echo "after cat"
} || {
echo "catch"
state=0
last_state=3
((filecounter++))
}
;;
I thought, that when the cat command fails while is beeing excecuted, "after cat" will be written and than the part after || will be excecuted. But when I look at the output, it seems that after echoing "after cat" a break happen so that the actual state does not change and will be entered one more time. Then stty fails, too (becaus the serial adapter is missing). After that, the cat command againt fails at the beginning but now enters the "catch" block....
Here is the relevant output:
pi@rpi ~/serial_logger $ ./serial_logger.sh
serial adapter found: ttyUSB0
state: 1
USB-Storage found: usb0
state: 3
before cat
after cat #here should be entered state 0
state: 3
stty: /dev/ttyUSB0: No such file or directory
before cat
cat: /dev/ttyUSB0: No such file or directory
catch
state: 0
USB-Storage found: usb0
state: 2
What am I doing wrong?
Upvotes: 3
Views: 545
Reputation: 4681
In your example, the cat
succeeds which is why "after cat" is printed and the "catch group" is not entered.
I thought, that when the cat command fails while is beeing excecuted, "after cat" will be written
This assumption is wrong, "after cat" will be written only if cat
succeeds because you used the &&
operator.
and than the part after || will be excecuted.
Note that there is no such thing as a "groupfail" which would allow you to actually emulate try/catch behaviour in Bash using command groups ({ [...] }
). Consider this example with multiple lines inside your group:
{
cmd1
cmd2
} || { # catch block
As long as cmd2
succeeds, your program will not enter the catch block, even if cmd1
fails.
You could however use the &&
operator to emulate try/catch behavior:
cmd1 && cmd2 && cmd3 || { # catch block
This could also be written as
{ cmd1 && cmd2 && cmd3 ; } || { # catch block
You see that however you do it, the syntax is a little clumsy.
Maybe this related stackoverflow question can help you too.
Last, but not least, two common Bash error handling mechanisms should be mentioned:
Registering a signal handler for the ERR
signal causes Bash to call a function whenever a command returns a non-zero exit status:
trap error_handler ERR
function error_handler() {
echo error
}
Setting the errexit
shell option causes your program to terminate as soon as a command returns a non-zero exit status (signal handlers are still executed):
set -e
Upvotes: 2