Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

How to Check Shell Output Without Compromising Stdout/Stderr

DZone's Guide to

How to Check Shell Output Without Compromising Stdout/Stderr

Denny Zhang explains how to effectively check the output of shell functions and scripts using the Linux tee command.

· DevOps Zone
Free Resource

Download “The DevOps Journey - From Waterfall to Continuous Delivery” to learn learn about the importance of integrating automated testing into the DevOps workflow, brought to you in partnership with Sauce Labs.

Ever need to check the output of shell functions or scripts? If no fatal error messages are found, resume normal procedure. Otherwise, go to error handling.

Usually people solve this by redirecting stdout/stderr to grep command. But what about functions or scripts that take several minutes? During this waiting period, end users are blinded with nothing printed. It could be confusing and scary to them.

linux_tee.pngImage from http://dennyzhang.com/shell_tee

Problem Explained

Let's examine the code snippet below.

  • L10, called a user defined function, might be time-consuming and error-prone.
  • L11-L17 runs logic conditionally, according to my_fun output.

People may be stuck at L10 for quite a while with nowhere to check what's going on. This is definitely not good.

#!/bin/bash -e
function my_fun() {
    set -e
    echo "Run function"
    # Simulate time-consuming steps
    # And they might fail as well
    sleep 3
    echo "Action done: my_fun"
}
output=$(my_fun)
if echo "$output" | grep "Action done" \
               1>/dev/null 2>&1; then
   echo "Do something..."
else
   echo "Error. msg: $output"
   exit 1
fi

echo "Action Done"

Use the Linux tee Command

tee is a command using standard streams that reads the standard input and writes it to both the standard output and one or more files, effectively duplicating its input.

Unlike usual pipe redirection, tee can do two redirections. Using tee, users can see detailed progress.

Don't Be Fooled by Exit Code 

What could $? stand for in the command below? $? is zero! Surprising, isn't it? 

ls /DIR_WONTEXST | tee -a test.log
echo $?

This is a tricky part of shell scripting. By running a list of commands in one line, we get the exit code of the last command. If you want to fail this line whenever any command fails, run set -o pipefail. See more discussion in StackOverflow.

Put It All Together

  1. Redirect output to both terminal and log file by tee command.
  2. Use set -o pipefail to detect possible failures.

Updated version:

#!/bin/bash -e
function my_fun() {
    set -e
    echo "Run function"
    # Simulate time-consuming steps
    # And they might fail as well
    sleep 3
    echo "Action done: my_fun"
}

set -o pipefail
tmp_log_file=/tmp/my_fun.log

my_fun 2>&1 | tee -a "$tmp_log_file"
if grep "Action done" "$tmp_log_file" \
               1>/dev/null 2>&1; then
   echo "Do something..."
else
   echo "Error. msg: $output"
   exit 1
fi

echo "Action Done"

More Reading: Challenge Your Shell Scripts By ShellCheck

Like our blog posts? Discuss with us on LinkedIn, Wechat, or Newsletter.

Discover how to optimize your DevOps workflows with our cloud-based automated testing infrastructure, brought to you in partnership with Sauce Labs

Topics:
devops ,linux

Published at DZone with permission of Denny Zhang, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}