bashutils.sh 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. # These are common functions and settings I use when writing things in bash
  2. # Usage: source $HOME/lib/bash/bashutils.sh
  3. #
  4. # Imports (optional)
  5. # Set these to control behavior
  6. #
  7. # # print debug messages
  8. # export DEBUG=1
  9. #
  10. # # set explicit program name
  11. # export PROGNAME=foo
  12. #
  13. # # choose descriptor to use for error messages
  14. # export ERROR_FD=1 # stdout
  15. # export ERROR_FD=2 # stderr
  16. #
  17. # # choose not to use -u and -e
  18. # export NO_ERRORS=1
  19. #
  20. # Exports:
  21. # These are defined and exported
  22. #
  23. # ARGV=("$@")
  24. # ARGC=("$#")
  25. # FALSE=1
  26. # TRUE=0
  27. # Set -u and -e unless in interative shell or NO_ERRORS set.
  28. if [[ $- == *i* ]]; then
  29. IS_INTERACTIVE=1
  30. fi
  31. if [ "$SHLVL" -eq 1 ]; then
  32. IS_LOGIN=1
  33. fi
  34. if [ -n "${IS_INTERACTIVE+xxx}" ] || [ -n "${IS_LOGIN+xxx}" ]; then
  35. # These does not work well in interactive shells.
  36. :
  37. elif [ -z "${NO_ERRORS+xxx}" ]; then
  38. # This is bash. Be safe.
  39. set -u -e
  40. fi
  41. # exports
  42. ARGV=("$@")
  43. ARGC=("$#")
  44. FALSE=1
  45. TRUE=0
  46. # Helper functions
  47. # Deep bash magic from before the dwan of time...
  48. # https://gitlab.com/kyb/autorsync/-/blob/master/utils.bash#L84
  49. function echodbg { >/dev/stderr echo $'\e[0;36m'"DBG $@"$'\e[0m'; }
  50. function stacktrace2 {
  51. local i=${1:-1} size=${#BASH_SOURCE[@]}
  52. ((i<size)) && echodbg "STACKTRACE"
  53. for ((; i < size-1; i++)) ;do ## -1 to exclude main()
  54. ((frame=${#BASH_SOURCE[@]}-i-2 ))
  55. echodbg "[$frame] ${BASH_SOURCE[$i]:-}:${BASH_LINENO[$i]} ${FUNCNAME[$i+1]}()"
  56. done
  57. }
  58. function stackfuncs {
  59. # echo stack function list, colon separated, top to bottom in call order
  60. tracefuncs="" # stacktrace functions, lowest (in call stack) to hightest
  61. local i=${1:-1} size=${#BASH_SOURCE[@]}
  62. #((i<size)) && echodbg "STACKTRACE"
  63. for ((; i < size-1; i++)) ;do ## -1 to exclude main()
  64. ((frame=${#BASH_SOURCE[@]}-i-2 ))
  65. #echodbg "[$frame] ${BASH_SOURCE[$i]:-}:${BASH_LINENO[$i]} ${FUNCNAME[$i+1]}()"
  66. tracefuncs="${FUNCNAME[$i+1]}:${tracefuncs}"
  67. topfunc="${FUNCNAME[$i+1]}"
  68. done
  69. tracefuncs=`echo $tracefuncs | sed 's#:$##'`
  70. default_name="${PROGNAME:-default}"
  71. echo "${tracefuncs:-$default_name}"
  72. }
  73. function info() { echo `date +%c` `stackfuncs`\: info: "$@" >&${ERROR_FD:-2}; }
  74. function warn() { echo `date +%c` `stackfuncs`\: warning: "$@" >&${ERROR_FD:-2}; }
  75. function error() { echo `date +%c` `stackfuncs`\: error: "$@" >&${ERROR_FD:-2}; }
  76. # Temporary debug messages
  77. # DEBUG=1 debug foo
  78. #
  79. # GLobal debug messages
  80. # export DEBUG=1
  81. # ...
  82. # debug foo
  83. #
  84. # TODO
  85. # have it check debug levels and or strings
  86. function debug() { [[ -v DEBUG ]] && echo `date +%c` `stackfuncs`\: debug: "$@" >&${ERROR_FD:-2} || true ; }
  87. function die() {
  88. exit_code=1
  89. if [[ -v 2 ]]; then
  90. exit_code="${1}"
  91. shift;
  92. fi
  93. echo `date +%c` `stackfuncs`\: fatal: "$@" >&${ERROR_FD:-2} && exit "${exit_code}";
  94. }