Thursday, 5 February 2026

pipe status


[root@oel01db ~]# echo hello

hello

[root@oel01db ~]#

[root@oel01db ~]# echo $?

0

[root@oel01db ~]#


[root@oel01db ~]# echo hello | grep hi

[root@oel01db ~]#

[root@oel01db ~]# echo $?

1

[root@oel01db ~]#


$? always stores the exit status of the very last command executed in the foreground.

Here echo hello is succeeded , where as grep hi failed, hence the exit code 1

## The Exit Code Logic

In Linux, every command returns an exit status (stored in the $? variable) to tell the system how it went. For grep:

  • 0 (Success): A match was found.

  • 1 (Failure to match): The command ran perfectly, but the pattern ("hi") was not found in the input ("hello").

  • 2 (Error): There was a syntax error or the file doesn't exist.

Check man page for the exit code for a command.

Example 2

[root@oel01db ~]# cat non-existing-file
cat: non-existing-file: No such file or directory
[root@oel01db ~]#
[root@oel01db ~]# echo $?
1
[root@oel01db ~]#
[root@oel01db ~]# cat non-existing-file | tr , :
cat: non-existing-file: No such file or directory
[root@oel01db ~]#
[root@oel01db ~]# echo $?
0
[root@oel01db ~]#

Why we got exit code 0 ?

## The Breakdown

  1. cat non-existing-file: This command failed because the file doesn't exist. Its internal exit code was 1.

  2. | (The Pipe): This passed the (empty) output of cat over to the next command.

  3. tr , :: This command received nothing from the pipe, performed "nothing" successfully, and finished. Because it didn't encounter a system error, it exited with 0.

Since tr was the last command in the pipeline, the shell updated $? to 0.

## How to see the "Real" failure

If you want to catch errors that happen earlier in the pipe, you have two main options:

Option 1: Use ${PIPESTATUS} (Bash/Zsh)

PIPESTATUS is a built-in array variable in Bash that stores the exit status (return codes) of every single command in the most recently executed foreground pipeline.

[root@oel01db ~]# cat non-existing-file | tr , :

cat: non-existing-file: No such file or directory
[root@oel01db ~]# echo "${PIPESTATUS[@]}"
1 0
  • 1 is the failure from cat.

  • 0 is the success from tr.


[root@oel01db ~]# cat non-existing-file | tr , :
cat: non-existing-file: No such file or directory
[root@oel01db ~]#
[root@oel01db ~]# echo "${PIPESTATUS[1]}"
0
[root@oel01db ~]#

${PIPESTATUS[0]} = Exit code of command1

${PIPESTATUS[1]} = Exit code of command2

${PIPESTATUS[2]} = Exit code of command3

Option 2: Use set -o pipefail

This is a safer way to write scripts. If you enable this, the entire pipeline will return a non-zero exit code if any command in the chain fails.


[root@oel01db ~]# set -o pipefail
[root@oel01db ~]# cat non-existing-file | tr , :
cat: non-existing-file: No such file or directory
[root@oel01db ~]# echo $?
1
[root@oel01db ~]#

No comments:

Post a Comment

Deploy PostgreSQL Database Code to Dev and Test Environments Sequentially Using GitHub Actions

Deploy PostgreSQL Database Code to Dev and Test Environments Sequentially Using GitHub Actions Modern database deployments should be repeata...