Is there any practical difference in debugging using bash -x scriptname.sh or using set -x inside the script and then calling it?
In my personal experience I always use bash -x because that way I don't have to change the script so it's less invasive.
Is there a scenario where bash -x would not fit and just set -x would work?
I came up with these questions because I always see people suggesting set -x when trying to help others to debug and I was wondering why not bash -x scriptname.sh. Is there a technical limitation?
PS: I'm not asking about what the commands do, but I'm asking "how" they do and if one is better than the other.
About what they do:
33 Answers
I would also suggest set -x and not bash -x to a user debugging a script.
- The user fully expects to modify the script to fix the bug, so adding a line is a non-issue.
- You don't have to know how the user runs their script (it could be via some build script or IDE, and not just
./fooin a terminal) - You don't have to confirm the shebang, since
#!/bin/bash -euiwould require you to instead runbash -euix fileand#!/bin/shwould requiresh -x file.
But for myself? Yeah, I'd just run bash -x.
The main reason to avoid things in the shebang is that strictly a POSIX kernel doesn't have to support more than one argument. So #!/usr/bin/env bash -x may not work (#!/bin/bash -x may, but then you may be using the ancient bash on macOS, for example). (That said, many UNIX-like systems do, in fact, support shebangs with multiple arguments.)
If you're dealing with security or secrets options at the first part of your script, but you want to be able to debug later on, you may want to set +x for the security related section. But, you can always do set -x so that is not a particularly robust reason to avoid bash -x.
They are different interface to the same functionality, check out the docs:
All of the single-character options used with the set builtin (see The Set Builtin) can be used as options when the shell is invoked.
The different is. Do I set it before the first line of the script gets evaluated (bash -x ./script.sh), or do I set it within the script (set -x anywhere in the script). They can both enable and disable the simple trace funvtionality, last set "wins" as in affects the lines that follow. There is no functional difference in the effect the two have otherwise.