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 blueprint that can take a company of any maturity level all the way up to enterprise-scale continuous delivery using a combination of Automic Release Automation, Automic’s 20+ years of business automation experience, and the proven tools and practices the company is already leveraging.

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.

Download the ‘Practical Blueprint to Continuous Delivery’ to learn how Automic Release Automation can help you begin or continue your company’s digital transformation.

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 }}