Here is another one. Often you only want to trace a particular command in your script. Then why not write a function that does just that?
> call() { set -x; "$@"; { set +x; } 2>/dev/null; }
> call uname -a
+ uname -a
CYGWIN_NT-6.1-WOW W530 3.1.7(0.340/5/3) 2020-08-22 19:03 i686 Cygwin
> call make -j8 *.mak
+ make -j8 some_name.mak
We can improve this further by returning (and tracing) the exit code of the called command:
> call() { local rc; set -x; "$@"; rc=$?; { set +x; } 2>/dev/null; return $rc; }
> call true && echo yes
+ true
+ rc=0
yes
> call false && echo yes
+ false
+ rc=1
Here is a real life example that calls the Rhapsody CLI program to generate source code from a .rcl-file with command-line options:
die() {
local c=${1:--1} m=${2:-'Died'}
echo "$m at ${BASH_SOURCE[1]}:${FUNCNAME[1]} line ${BASH_LINENO[0]} (exit $c)" >&2
exit $c
}
call() { local rc; set -x; "$@"; rc=$?; { set +x; } 2>/dev/null; return $rc; }
call "$opt_rhapsodycl" -f $rclfile || die $? 'Rhapsody license server not reachable'
For example, in case of failure prints something like:
+ path/to/RhapsodyCL.exe -f configuration.rcl
+ rc=127
Rhapsody license server not reachable at ./Build:main line 167 (exit 127)
Or in case of success the script continues. With these two functions (call
and die
) we can write very compact and readable one-liners that also produce nice tracing output.