Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
languagebash
#!/bin/bash

# Script version global variable. Edit this whenever changes are made.
__ADVANCED_BASH_VERSION__="step_02"

# =======================================================================
#  Helper functions
# =======================================================================

# Echo's its arguments to std error
echo_se() { echo "$@" 1>&2; }

# Sets up auto-logging to a log file in the current directory
# using the specified logFileTag (arg 1) in the log file name.
auto_log() {
  local logFileTag="$1"
  if [[ "$logFileTag" != "" ]]; then
    local logFilePath="./autoLog_${logFileTag}.log"
    echo_se ".. logging to $logFilePath"
    exec 1> >(tee "$logFilePath") 2>&1
  else
    echo_se "** ERROR in autoLog: no logFile argument provided"
    exit 255
  fi
}

# =======================================================================
#  Command processing functions
# =======================================================================

# function that says "Hello World!" and displays user-specified text.
function helloWorld() {
  local txt1=$1
  local txt2=$2
  shift; shift
  local rest=$@
  echo "Hello World!"
  echo "  text 1: '$txt1'"
  echo "  text 2: '$txt2'"
  echo "  rest:   '$rest'"
}

# function that displays its 1st argument on standard output and
# its 2nd argument on standard error
function stdStreams() {
  local outTxt=${1:-"text for standard output"}
  local errTxt=${2:-"text for standard error"}
  echo    "to standard output: '$outTxt'"
  echo_se "to standard error:  '$errTxt'"
}

# function that illustrates auto-logging and capturing function output
#  arg 1 - (required) tag to identify the logfile
#  arg 2 - (optional) text for standard output
#  arg 3 - (optional) text for standard error
function testAutolog() {
  local logFileTag="$1"
  local outTxt=${2:-"text for standard output"}
  local errTxt=${3:-"text for standard error"}

  auto_log "$logFileTag"

  echo -e "\n1) Call stdStreams with output and error text:"
  stdStreams "$outTxt" "$outErr$errTxt"

  echo -e "\n2) Capture stdStreamsecho output in a variable and display it:"
  local output=`stdStreams`echo "$outTxt" "$outErr"`$outTxt`
   echo -e "\tstdStreams   echo output was:\n$output"

  echo -e "\n3) Call echo_se with someerror text:"
  echo_se "Some random text$errTxt"

  echo -e "\n4)Capture echo_se function output in a variable and display it:"
  output=`echo_se "Some random text$errTxt"`
  echo -e "echo_se output was: '$output'"
}

# =======================================================================
#  Main script command-line processing
# =======================================================================

function usage() {
  echo "
advanced_bash.sh, version $__ADVANCED_BASH_VERSION__

Usage: advanced_bash.sh <command> [arg1 arg2...]

Commands:
  helloWorld [text to display]
  stdStreams [text for stdout] [text for stderr]
  testAutolog <logFileTag> [text for stdout] [text for stderr]
"
  exit 255
}

CMD=$1    # initially $1 will be the command
shift     # after "shift", $1 will be the 2nd command-line argument; $2 the 3rd, etc.
case "$CMD" in
  helloWorld) helloWorld "$@"
    ;;
  stdStreams) stdStreams "$1" "$2"
    ;;
  testAutolog) testAutolog "$1" "$2" "$3"
    ;;
  *) usage
    ;;
esac

...

Code Block
languagebash
# function that illustrates auto-logging and capturing function output
#  arg 1 - (required) tag to identify the logfile
#  arg 2 - (optional) text for standard output
#  arg 3 - (optional) text for standard error
function testAutolog() {
  local logFileTag="$1"
  local outTxt=${2:-"text for standard output"}
  local errTxt=${3:-"text for standard error"}

  auto_log "$logFileTag"

  echo -e "\n1) Call stdStreams with output and error text:"
  stdStreams "$outTxt" "$outErr$errTxt"

  echo -e "\n2) Capture stdStreamsecho output in a variable and display it:"
  local output=`stdStreams "$outTxt" "$outErr"``echo $outTxt`
  echo -e "\tstdStreams   echo output was:\n$output"

  echo -e "\n3) Call echo_se with someerror text:"
  echo_se "Some random text$errTxt"

  echo -e "\n4)Capture echo_se function output in a variable and display it:"
  output=`echo_se "Some random text$errTxt"`
  echo -e "echo_se output was: '$output'"
}

...

Expand
titleSolution

Executing:

Code Block
languagebash
~/workshop/step_02.sh testAutoLog

produces this output:

Code Block
auto-logging to ''
** ** ERROR in autoLog: no logFile argument provided

No further code is executed after the auto_log helper function detects that no tag string has been provicedprovided, because it calls exit.

exercise 4

...

Expand
titleSolution

Executing:

Code Block
languagebash
~/workshop/step_02.sh testAutoLog test1

produces this output:

Code Block
.. logging to ./autoLog_test1.log

1) Call stdStreams with output and error text:
to standard output: 'text for standard output'
to standard error:  'text for standard error'

2) Capture stdStreamsecho output in a variable and display it:
to standard error:  'text for standard error'
        stdStreams echo output was:
to standard output:
'text for standard output'

3) Call echo_se with someerror text:
Sometext for randomstandard texterror

4)Capture echo_se function output in a variable and display it:
Sometext for randomstandard texterror
echo_se output was: ''

Why are both standard error and standard output text strings displayed in segment 1) when stdStreams is called?

Expand
titleSolution

Because stdStreams echo's to both standard error and standard output in the current execution environment, where both are directed to the terminal by auto-logging.

Why is only standard output displayed in segment does the $output variable contain the outTxt in 2) when stdStreams echo is called with output being captured?

Expand
titleSolution

Because backtick evaluation creates a new execution environment, and only standard output is returned replaces the command in backticks ( `...` ) with the command's standard output.

Why is the $output variable empty in segment 4) when echo_se "Some random text"se  is called with output being captured?

Expand
titleSolution

Because backtick evaluation creates a new execution environment, and only Because only a command's standard output is returned by backtick evaluation, not standard error.

What log file is produced, what are its contents, and why?

Expand
titleSolution

The log file produced is autoLog_test1.log, written to the current directory in force when step_02.sh was called.

Its contents (below) are nearly the same as when ~/workshop/step_02.sh testAutoLog test1 is called, except that the ".. logging to ./autoLog_test1.log" line is not reported, since that was written before automatic logging was started.

Code Block
1) Call stdStreams with output and error text:
to standard output: 'text for standard output'
to standard error:  'text for standard error'

2) Capture stdStreamsecho output in a variable and display it:
to standard error:  'text for standard error'
        stdStreams echo output was:
to standard output: 'text for standard output'

3) Call echo_se with someerror text:
Sometext for randomstandard texterror

4)Capture echo_se function output in a variable and display it:
Sometext for randomstandard texterror
echo_se output was: ''

exercise 5

What is displayed in the terminal when you call the testAutoLog command but redirect standard output to /dev/null? What is in the log file, and why?

Expand
titleSolution

Executing:

Code Block
languagebash
~/workshop/step_02.sh testAutoLog test1 1> /dev/null

produces only this output:

Code Block
.. logging to ./autoLog_test1.log

because after automatic logging is turned on, both standard output and standard error for the script are redirected to standard output by the "exec 1> >(tee "$logFilePath") 2>&1" line. The ".. logging to ./autoLog_test1.log" message was written before auto logging was enabled.

However the autoLog_test1.log log file contents are the same as before, because your command-line redirection only affected your command-line environment, not the script's execution environment.