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
51–60 of 78 posts
Re: Bash Debugging
#52I always put set -euxo pipefail at the top of my bash scripts. It makes some conditional testing more difficult but it has paid for itself many times over just because of pipefail
This is a lifesaver. Although I save the -x until I really need to see all the garbage debug output.
Re: Bash Debugging
#53I always put set -euxo pipefail at the top of my bash scripts. It makes some conditional testing more difficult but it has paid for itself many times over just because of pipefail
Re: Bash Debugging
#54Earlier quoted context omitted.
Just adding `set -e` also exits the script when a subshell exits with non-zero error code. I'm not sure why I would leave `set -e` out in any shell script.
grep has a bad interaction with set -e, since it (infuriatingly) exits with 1 if no lines are matched.
Re: Bash Debugging
#55Earlier quoted context omitted.
Perhaps, but in any case I would never write code like this. 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 herestri…
Do enlighten me on why it is a bad idea to use loops over read; it's perhaps one of my favourite patterns in bash, and combined with pipes, appears to me one of the cleanest ways to correctly and concisely utilise parallelism in software.
https://unix.stackexchange.com/questions/169716/why-is-using...
https://unix.stackexchange.com/questions/209123/understandin...
Both of these posts must be read carefully if you really wish to write robust scripts.
Re: Bash Debugging
#56Earlier quoted context omitted.
Perhaps, but in any case I would never write code like this. 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 herestri…
> looping over `read` is essentially never the right thing to do Why? I do it quite often, though admittedly usually in one-time scripts.
Re: Bash Debugging
#57Earlier 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…
Android and Apple are in similar situations.
Re: Bash Debugging
#58Good 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...
That's a nice list; I guess every experienced user has their helper functions. However, I have a small criticism for the philosophy of that `die`: `die` functions should pass by default the exit code of the failed command, and not silence its error output. If I want to give my own meaning to the command failure in a large script for instance, I will use a different, more specialized `die`. My own die is roughly as fo…
Re: Bash Debugging
#59Earlier quoted context omitted.
Just adding `set -e` also exits the script when a subshell exits with non-zero error code. I'm not sure why I would leave `set -e` out in any shell script.
grep has a bad interaction with set -e, since it (infuriatingly) exits with 1 if no lines are matched.
Re: Bash Debugging
#60Earlier quoted context omitted.
Do enlighten me on why it is a bad idea to use loops over read; it's perhaps one of my favourite patterns in bash, and combined with pipes, appears to me one of the cleanest ways to correctly and concisely utilise parallelism in software.
Stéphane Chazelas has already explained this extensively, so I will link to two of his most information-dense posts: https://unix.stackexchange.com/questions/169716/why-is-using... https://unix.stackexchange.com/questions/209123/understandin... Both of these posts must be read carefully if you really wish to write robust scripts.
Reasons of 1) performance, 2) readability, and 3) security are provided as points against the pattern, and the post itself acknowledges that the pattern is a great way to call external programs.
I'd think that the fact that one is using shell to begin with would almost certainly mean that one is using the subshell loop pattern for calling external programs, which is the use case that your post approves of. In this case, subshells taking the piped input as stdin allows the easy passing of data streamed over a file-descriptor, probably one of the most trivially performant ways of data movement, and the pattern is composable, certainly easier to remember, modify, and to extend than the provided xargs alternative, without potential problems such as exceeding max argument length. Having independent subshells also allows for non-interference between separate loops when run in parallel, offering something resembling a proper closure. In these respects, subshell loops provide benefits rather than pitfalls in performance and readability. Certainly read has some quirks that one needs to be aware of, but aren't much of an issue when operating on inputs of a known shape, which is likely the case if one is about to provide them as arguments to another command.
Regarding "security", the need to quote applies to anything in shell, and has nothing specifically to do with the pattern.