Exit Codes in Practical DevSecOps Labs: Success, Failure, Security Tools, and Pipes
Exit codes tell you whether a command or script succeeded or failed. Understanding them is critical for CI/CD pipelines, security tooling, and automation across every Practical DevSecOps course.
Table of Contents
Exit Code Basics
Every command returns an exit code when it finishes:
| Exit Code | Meaning |
|---|---|
0 |
Success |
| Non-zero | Failure |
Check the last command's exit code with echo $?.
Examples
Successful ls:
ls
echo $?
0
Listing a non-existent directory:
ls non-existent-dir
ls: cannot access 'non-existent-dir': No such file or directory
echo $?
2
Exit code 2 indicates failure.
Removing a file:
touch newfile # create
rm newfile # delete
echo $? # 0 (success)
rm newfile # try again
echo $? # 1 (failure — file gone)
Command not found:
gibberish
echo $?
bash: gibberish: command not found
127
Exit code 127 is a standard code for "command not found."
Security Tool Exit Codes
In security tooling, exit codes have a special meaning:
| Exit Code | Meaning in Security Context |
|---|---|
0 |
No vulnerabilities found (success) |
| Non-zero | Vulnerabilities found (failure) |
Different tools use different non-zero codes. One tool may return 1, another 13, yet another 255. All indicate vulnerabilities were found.
Note: Some poorly designed tools always return
0regardless of findings. In CI/CD, these tools won't cause pipeline failures automatically — you'll need to write custom scripts to parse their output.
Example: Mock security tool
cat > myfaketool << EOL
#!/bin/bash
vulncount=$((0 + $RANDOM % 3))
if [ $vulncount -eq 0 ]; then
echo "No Vulnerabilities"
exit 0
else
echo "Vulnerabilities found: $vulncount"
exit 99
fi
EOL
chmod +x myfaketool
./myfaketool
echo $?
When vulnerabilities are found, the tool exits with 99 (non-zero). When none are found, it exits with 0.
Exit Codes in Piped Commands
When commands are connected with a pipe (|), echo $? returns the exit code of the last command in the pipeline, not the first.
Example
cat > hello_world.sh <<"EOF"
echo "Hello World"
exit $1
EOF
sh hello_world.sh 5 | grep "Hello World"
echo $?
Hello World
0
Even though hello_world.sh exited with code 5, the pipeline's exit code is 0 — the exit code of grep, which found a match.
If grep doesn't find a match:
sh hello_world.sh 5 | grep "Hello World" | grep "Hello Universe"
echo $?
1
Now the exit code is 1 because the last grep found no match.
Common Questions
| Question | Answer |
|---|---|
| How do I check a command's exit code? | Run echo $? immediately after the command. |
Does 0 always mean success? |
By convention, yes. Non-zero always means something went wrong. |
| Why does my pipeline show exit code 0 even when the first command failed? | echo $? returns the exit code of the last command in the pipe. Use set -o pipefail to change this behavior. |
| What exit code means "command not found"? | 127 is the standard code for a command that cannot be found. |
| Can I force a command to succeed in a pipeline? | Append ` |
Read more about exit code conventions at Advanced Bash-Scripting Guide: Exit Codes.
Wrap-Up
Exit codes are the backbone of automation and CI/CD pipelines. Remember: 0 means success, non-zero means failure. In security scanning, non-zero typically means vulnerabilities were found. In piped commands, always check which command's exit code you're actually reading.