Exit Code of command is 0, but binaries exit code is 3 [duplicate] - bash

This question already has answers here:
Pipe output and capture exit status in Bash
(16 answers)
Closed 8 years ago.
I made a simple script:
$ more test.bash
#!/bin/bash
echo test
exit 1
When I run the script , the exit status should be 1
$ /tmp/test.bash
echo $?
1
But when I run this as the following
/tmp/test.bash | tr -d '\r' 1>>$LOG 2>>$LOG
echo $?
0
The exit status is 0, (not as expected 1)
It seems that the exit status comes from tr command.
But I what I want is to get the exit status from the script - test.bash.
What do I need to add/change in my syntax in order to get the right exit status from the script, and not from the command after the pipe line?

Use the PIPESTATUS array:
$ ls foo | cat
ls: foo: No such file or directory
$ echo ${PIPESTATUS[0]} ${PIPESTATUS[1]}
2 0
Note: PIPESTATUS is a bashism (i.e. not POSIX).

Related

bash echo is doing commands and not adding what I need [duplicate]

This question already has an answer here:
echo bash code to .sh file to execute mixed up the variables
(1 answer)
Closed 3 months ago.
I need to create a new file name test.sh.
I need to write those lines with echo or somethings else but cant open new file manually and write it.
That is, I have to write down some things in the bash such a way that the following file is created:
TEST_VALUE=$1
if [[cat data | grep $TEST_VALUE]]; then
exit 1
fi
exit 0
But, when I do that by echo the result is:
TEST_VALUE=
if [[]]; then
exit 1
fi
exit 0
I need the file as I write it with $1 and not the argument and with the grep.
I tried to grep each row but it is doing the command and not copied it as I want.
How do I do it?
Thank You
Ignoring that the content you're trying to copy is buggy, the best way to do this is with a quoted heredoc:
cat >file <<'EOF'
TEST_VALUE=$1
if [[cat data | grep $TEST_VALUE]]; then
exit 1
fi
exit 0
EOF
But that content is buggy! A better version would look like:
cat >file <<'EOF'
#!/bin/sh
test_value=$1
! grep -q -e "$test_value" <data
EOF
echo 'TEST_VALUE=$1
if [[cat data | grep $TEST_VALUE]]; then
exit 1
fi
exit 0' > test.sh
You need to use quotes, in any other case your command will be executed.

How to parse the error given by a bash script? [duplicate]

This question already has an answer here:
Bash how do you capture stderr to a variable? [duplicate]
(1 answer)
Closed 2 years ago.
Given this script:
#!/bin/bash
COMMAND=$(echo test | jq)
if [[ $COMMAND == *"error"* ]]; then
echo failed
else
echo success
fi
Since the output of $(COMMAND) is the following: parse error: Invalid literal at line 2, column 0, I'd expect to have as output of that script failed, but I'm having success.
How can I parse the error that I got on scripts?
jq prints errors to stderr so you'd have to do this:
COMMAND=$(echo test | jq 2>&1)
But checking if command failed can be done using much easier method in
Bash:
#!/usr/bin/env bash
if ! echo test | jq '.'
then
echo failed
else
echo success
fi

Automatically exit when bash command produce return code non zero [duplicate]

This question already has answers here:
Automatic exit from Bash shell script on error [duplicate]
(8 answers)
Error handling in Bash [closed]
(15 answers)
Closed 4 years ago.
In bash how do we make the script to automatically exit if a command line return code is not zero. For example:
#!/bin/bash
cd /something_something
mv file_a /somedir/file_a # this produce an error
echo $? # This produce a non-zero output
echo "We should not continue to this line"
I know we can debug bash script with #!/bin/bash -x but sometime the script is too long, it run so fast, and we missed important error.
And I don't want to keep writing
[[ $? -ne 0 ]] && run next_command
There are lots of problems with using set -e. Just join the commands with &&, and test the result with an if statement.
if cd /something_something && mv file_a /somedir/file_a; then
echo $?
exit
fi
echo "Both cd and mv worked"

What does `echo $?` mean in bash? [duplicate]

This question already has answers here:
Meaning of $? (dollar question mark) in shell scripts
(8 answers)
Closed 9 years ago.
I came upon the following command:
echo $?
what does that command do?
Echoes (prints) the exit value for the previous command.
If it failed it will be different than zero (0).
$ cd ~
$ echo $?
> 0
$ cd //whatever/
> bash: cd: //whatever/: No such file or directory
$ echo $?
> 1
Programs exit with a status code. Every program is unique and has a different set of failure codes, but it's universally acknowledged that 0 is the 'success' code.

Pipe command output, but keep the error code [duplicate]

This question already has answers here:
Pipe output and capture exit status in Bash
(16 answers)
Closed 5 years ago.
How do I get the correct return code from a unix command line application after I've piped it through another command that succeeded?
In detail, here's the situation :
$ tar -cEvhf - -I ${sh_tar_inputlist} | gzip -5 -c > ${sh_tar_file} -- when only the tar command fails $?=0
$ echo $?
0
And, what I'd like to see is:
$ tar -cEvhf - -I ${sh_tar_inputlist} 2>${sh_tar_error_file} | gzip -5 -c > ${sh_tar_file}
$ echo $?
1
Does anyone know how to accomplish this?
Use ${PIPESTATUS[0]} to get the exit status of the first command in the pipe.
For details, see http://tldp.org/LDP/abs/html/internalvariables.html#PIPESTATUSREF
See also http://cfajohnson.com/shell/cus-faq-2.html for other approaches if your shell does not support $PIPESTATUS.
Look at $PIPESTATUS which is an array variable holding exit statuses. So ${PIPESTATUS[0]} holds the exit status of the first command in the pipe, ${PIPESTATUS[1]} the exit status of the second command, and so on.
For example:
$ tar -cEvhf - -I ${sh_tar_inputlist} | gzip -5 -c > ${sh_tar_file}
$ echo ${PIPESTATUS[0]}
To print out all statuses use:
$ echo ${PIPESTATUS[#]}
Here is a general solution using only POSIX shell and no temporary files:
Starting from the pipeline:
foo | bar | baz
exec 4>&1
error_statuses=`((foo || echo "0:$?" >&3) |
(bar || echo "1:$?" >&3) |
(baz || echo "2:$?" >&3)) 3>&1 >&4`
exec 4>&-
$error_statuses contains the status codes of any failed processes, in random order, with indexes to tell which command emitted each status.
# if "bar" failed, output its status:
echo $error_statuses | grep '1:' | cut -d: -f2
# test if all commands succeeded:
test -z "$error_statuses"
# test if the last command succeeded:
echo $error_statuses | grep '2:' >/dev/null
As others have pointed out, some modern shells provide PIPESTATUS to get this info. In classic sh, it's a bit more difficult, and you need to use a fifo:
#!/bin/sh
trap 'rm -rf $TMPDIR' 0
TMPDIR=$( mktemp -d )
mkfifo ${FIFO=$TMPDIR/fifo}
cmd1 > $FIFO &
cmd2 < $FIFO
wait $!
echo The return value of cmd1 is $?
(Well, you don't need to use a fifo. You can have the commands early in the pipe echo a status variable and eval that in the main shell, redirecting file descriptors all over the place and basically bending over backwards to check things, but using a fifo is much, much easier.)

Resources