I have been following through some of the similar questions (such as How to set a variable to the output from a command in Bash?), however the accepted answers seem to be non-working for me. I wasn't sure whether I ought to derail someone else's question or post my own duplicate, so apologies if I chose wrong here.
I wish to get the output and exit status of a number of commands in a script I am putting together. Here is an example of what I have been using:
cmd_output=$(rm $file)
exit_status=$?
if [ "${exit_status}" -eq 0 ]
then
log "Successfully removed the original" ${TAB_LEVEL}
else
fail "Failed to remove the original, the output was: \n ${cmd_output}"
fi
The log and fail functions are:
# Usage: fail "Failure message"
function fail {
echo "FATAL ERROR: $1" >> "${LOG_DIR}/${LOG_FILE}"
exit 1
}
# Usage: log "Log message" 3 Where the tab-level is 3.
function log {
if (("${2}" > 0))
then
eval "printf ' %.0s' {1..$2}" >> "${LOG_DIR}/${LOG_FILE}"
fi
echo "$1" >> "${LOG_DIR}/${LOG_FILE}"
return 0
}
In the example above I use the $(cmd) format, but I have also tried using backticks.
In my log file, all I see when there is a failure is:
FATAL ERROR: Failed to remove the original, the output was: \n
Also, the output of the failed commands ends up on screen as per usual. Is there a common reason that my cmd_output variables would be remaining empty?
To store the output of a command in a variable, you can use the shell command substitution feature in the forms below: variable_name=$(command) variable_name=$(command [option ...] arg1 arg2 ...) OR variable_name='command' variable_name='command [option ...]
The echo command writes text to standard output (stdout). The syntax of using the echo command is pretty straightforward: echo [OPTIONS] STRING... Some common usages of the echo command are piping shell variable to other commands, writing text to stdout in a shell script, and redirecting text to a file.
The echo command is useful to display the variable's output especially when you know the content of a variable will not cause any issue.
You have to include the output of the special standard error output stream:
cmd_output=$(rm "$file" 2>&1)
There are three default streams on every program (that are numbered file descriptors):
0. Standard input (where the program normally reads from)
1. Standard output (where the program normally writes to)
2. Standard error (where the program normally writes error messages)
So to capture the error messages, we must redirect standard error output (stderr) into normal standard output (stdout) which will then be captured by the $(...)
expression.
The syntax for redirection is through the >
"operator". Immediately before it you tell which file descriptor to redirect (the default is 1, which is stdout). And you can specify it to redirect to a file. If you write an ampersand (&
) after it, you force it to redirect into another file descriptor. Therefore, in this example, we redirect file descriptor 2 (stderr) into file descriptor 1 (stdout).
Also, you can also redirect input with <
"operator", but in this case the default file descriptor is 0 (stdin).
Another observation is that it is probably good practice to place your $file
variable between double quotes, in case it has white space characters.
Hope this helps a little =)
*nix command generally have two forms of output: standard output (stdout
) and standard error (stderr
).
FOO=$(...)
only captures stdout
, and leaves stderr
unhindered.
If you want the contents of stderr
with this syntax, you need to postfix your command with 2>&1
so that stderr
is merged into stdout
. (e.g. like so: rm $file 2>&1
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With