szaydel
12/20/2019 - 9:13 PM

bash stack backtrace for shell script usage

#!/bin/bash

set -eu

trap _exit_trap EXIT
trap _err_trap ERR
_showed_traceback=f

function _exit_trap
{
  local _ec="$?"
  if [[ $_ec != 0 && "${_showed_traceback}" != t ]]; then
    traceback 1
  fi
}

function _err_trap
{
  local _ec="$?"
  local _cmd="${BASH_COMMAND:-unknown}"
  traceback 1
  _showed_traceback=t
  echo "The command ${_cmd} exited with exit code ${_ec}." 1>&2
}

function traceback
{
  local -i start=$(( ${1:-0} + 1 )) # hide this function from backtrace
  local -i end=${#BASH_SOURCE[@]}
  local -i i=0
  local -i j=0

  echo "Traceback (most recent call last):" 1>&2
  for ((i=start; i < end; i++)); do
    j=$(( i - 1 ))
    local fname="${FUNCNAME[$i]}"
    local file="${BASH_SOURCE[$i]}"
    local line="${BASH_LINENO[$j]}"
    if [ $i -eq $start ] ; then printf "  ⦿-"; fi 1>&2
    printf "file: ${file}, line: ${line}, in ${fname}\n" 1>&2
    printf "%-${j}s" "" 1>&2 ;
    if [ $i -lt $(( end-1 )) ]; then 
      printf "  %s" "\\_"
    else
      printf "\n" ; fi
  done
}

function alpha
{
  beta
}
function beta
{
  gamma
}
function gamma
{
  delta
}
function delta
{
  epsilon
}

function epsilon
{
  no_such_function
}

alpha