Is there a reason bash is still the de facto shell scripting language other than sheer momentum of legacy? I'm able to get what I need done in it, but it's clunky and the syntax is horrid. I guess it forces you to move to a proper language once scripts grow to a certain size/complexity, so perhaps it's by design?
Bash Debugging
21–30 of 78 posts
Re: Bash Debugging
#22The `die()` trick is good, but bash has an annoying quirk: if you try to `exit` while you're inside a subshell, then the subshell exits but the rest of the script continues. Example: #!/bin/bash die() { echo "$1" >&2; exit 1; } cat myfile | while read line; do if [[ "$line" =~ "information" ]]; then die "Found match" fi done echo "I don't want this line" ..."I don't want this line" will be printed. You can often avoi…
Re: Bash Debugging
#23Good stuff! I use set-x frequently and have used a similar thing to die (but Julia’s version is nicer). I’ll consider using the debugger thing but stepping through a bash script line by line sounds a bit tedious. Perhaps less so than having to reread a log and rerun the script a bunch.
I often add a fail-unless function: fail-unless() { local result "$@" result=$? if ((result != 0)); then echo >2&1 "Failed ${result} with command '$*'." exit ${result} fi } That way, I know exactly what failed in the script.
Re: Bash Debugging
#24Is there a reason bash is still the de facto shell scripting language other than sheer momentum of legacy? I'm able to get what I need done in it, but it's clunky and the syntax is horrid. I guess it forces you to move to a proper language once scripts grow to a certain size/complexity, so perhaps it's by design?
Are you sure it's bash? Most scripts on FreeBSD's are written for sh, which I feel is much more widely supported due to being part of the POSIX standard. Bash is just popular I think.
Bash/sh is good for when you need to combine some commands and what needs to be done can be accomplished mostly by CLI commands with a little glue to tie them together. Some times it is surprising what can be accomplished. I wrote a program to import pictures from an SD card on Windows using C#, copying pictures to C:\Pictures\YYYY\MM\DD according to the EXIF data or failing that, file time stamp. I tried to port it to Linux but ran into problems trying to connect to the EXIF library. After struggling with that, I rewrote it using sh, some EXIF tool and various file utilities. It took 31 lines, about half of which were actual commands and the rest comments or white space.
A much bigger project is a script to install Debian with root on ZFS. It's mostly a series of CLI commands with some variable substitution and conditionals depending on stuff like encrypted or not.
Re: Bash Debugging
#25Is there a reason bash is still the de facto shell scripting language other than sheer momentum of legacy? I'm able to get what I need done in it, but it's clunky and the syntax is horrid. I guess it forces you to move to a proper language once scripts grow to a certain size/complexity, so perhaps it's by design?
Are you sure it's bash? Most scripts on FreeBSD's are written for sh, which I feel is much more widely supported due to being part of the POSIX standard. Bash is just popular I think.
I feel like when I see a shell script in my work, which is not in operating systems development of course, people are targeting bash. I agree many things are careful to target sh for certain reasons (e.g. a script that runs in a container where the base image doesn’t have bash installed) but i still think GP’s question is interesting because it’s not common to see, say, a zsh shell script, but seeing #!/bin/bash is super common.
Re: Bash Debugging
#26The `die()` trick is good, but bash has an annoying quirk: if you try to `exit` while you're inside a subshell, then the subshell exits but the rest of the script continues. Example: #!/bin/bash die() { echo "$1" >&2; exit 1; } cat myfile | while read line; do if [[ "$line" =~ "information" ]]; then die "Found match" fi done echo "I don't want this line" ..."I don't want this line" will be printed. You can often avoi…
Could killing the PID like that create zombies?
First of all, sending sigkill is literally overkill and perpetuates a bad practice. Send `TERM`. If it doesn't work, figure out why.
Secondly, subshells should be made as clear as possible and not hidden in pipes. Related, looping over `read` is essentially never the right thing to do. If you really need to do that, don't use pipes; use heredocs or herestrings.
Fourth, if you cannot avoid subshells and you want to terminate the full script on some condition, exit with a specific exit code from the subshell, check for it outside and terminate appropriately.
Re: Bash Debugging
#27Earlier quoted context omitted.
I often add a fail-unless function: fail-unless() { local result "$@" result=$? if ((result != 0)); then echo >2&1 "Failed ${result} with command '$*'." exit ${result} fi } That way, I know exactly what failed in the script.
You do e.g. `fail-unless somecommand`. The result (exit/return code) is captured in the function and based on that, the function logs and exits or not.
Re: Bash Debugging
#28Earlier quoted context omitted.
Are you sure it's bash? Most scripts on FreeBSD's are written for sh, which I feel is much more widely supported due to being part of the POSIX standard. Bash is just popular I think.
I suppose it’s an ambiguous designation. I feel like when I see a shell script in my work, which is not in operating systems development of course, people are targeting bash. I agree many things are careful to target sh for certain reasons (e.g. a script that runs in a container where the base image doesn’t have bash installed) but i still think GP’s question is interesting because it’s not common to see, say, a zsh…
Re: Bash Debugging
#29If I ever have to debug anything in bash. I stop using bash hah.
Re: Bash Debugging
#30Good info. You can improve your debugging by using exit codes like this: # die: print error message to stderr, then exit with error code. # example: die 69 "Service unavailable." die() { n="$1" ; shift ; >&2 printf %s\\n "$*" ; exit "$n" } Many more shell script exit codes and helper functions: https://github.com/SixArm/unix-shell-script-kit/blob/main/un...
__errex() {
printf 'Fatal error [%s] on line %s in '"'"'%s'"'"': %s\n' \
"${1:-"?"}" \
"${2:-"?"}" \
"${3:-"unknown script"}" \
"${4:-"unknown error"}" >&2 ;
exit "${1:-1}"
}
alias die='__errex "$?" "${LINENO}" "$0"'