going-flying.com gemini git repository
70f567250ffdbffb9047c9b214512f1c549a7603 - Matthew Ernisse - 1675787445
new post
diff --git a/users/mernisse/articles/32.gmi b/users/mernisse/articles/32.gmi new file mode 100644 index 0000000..de85bfa --- /dev/null +++ b/users/mernisse/articles/32.gmi @@ -0,0 +1,125 @@ +--- +Title: Re: Wrapper Script Etiquette +Date: 02/07/2023 11:24 +In-Reply-To: gemini://thrig.me/blog/2023/02/05/wrapper-script-etiquette.gmi + +I stumbled upon some musing[1] about different form simple shell scripts +can take and had some thoughts. Now my first rule of programming is to +follow the style of the team you're working with. If you think something +should be different, you must convince the team instead of doing your own +thing in the corner. It's more important that the team be able to survive +without you than it is to be "right". If you are working alone then as a +team of 1, you just need to convince yourself. Once you have satisfied the +above, the next rule is to keep it as simple and straightforward as possible. +To paraphrase something I heard many years ago, you have to be smarter than +the author to debug a thing so try not to be your cleverest when you are +writing something else you may not be qualified to maintain it. For some +final context before I begin my more specific thoughts I'm used to working +in mixed environments so my goal with shell scripts specifically is maximal +portability. I prefer POSIX shell to the point that I'd rather inline Python +or Perl than resort to bash-isms. My targets are typically MacOS/bash, +Linux/bash, Linux/dash, and BSD/pdksh. + + +These were the examples given in the original article. + +=> gemini://thrig.me/blog/2023/02/05/wrapper-script-etiquette.gmi [1] + +## pa + +``` + ping -f "$@" +``` + +## re + +``` + #!/bin/sh + ping -f "$@" +``` + +## ci + +``` + #!/bin/sh + /sbin/ping -f "$@" +``` + +## vo + +``` + #!/bin/sh + exec /sbin/ping -f "$@" +``` + +Now in these specific examples you would need super-user privileges to +run any of these commands (I tested on MacOS, Debian Linux and OpenBSD) +but I'm going to assume the original author didn't intend to limit the +scope of their comments to scripts requiring elevated privileges to run. + +The first example (pa) is not even a shell script. + +Of the remaining, I'd prefer the second form (re) the most. It is simple, +lets the shell do most of the work and doesn't impose unnecessary portability +problems. The author argues that hard-coding absolute path names provides +some additional security but for maintainability's sake I'd rather choose to +control $PATH in the script if it was critical and still allow the shell to +resolve locations itself. It is certainly easier to read and maintain +than having /full/path/to/file everywhere. More critically I think the +security argument is a bit of a fallacy. Defense is depth is a good strategy +but there's no point in digging a moat inside the vault. If an attacker has +gained control of your system sufficiently to modify the environment of your +running shell (to change your $PATH) and inject an executable binary on the +filesystem then the game was already over. Now there may be some cases +where you absolutely want a specifically installed version of a program +to be run, and then you may find yourself hard-coding a full path to it +(perhaps it is located in a directory not in your shell's $PATH and you +don't want to accidentally execute other binaries later in the script from +that directory) but for system utilities letting the shell do the lookup +for you is not unreasonable. As to the complaint of extra work, Most shells +cache the lookups so the penalty is very low and the portability gains are +very high. You certainly don't want to find yourself doing this. + +``` +case $(uname -s) in + Darwin) + /usr/bin/foo + ;; + + OpenBSD) + /bin/foo + ;; + + *) + /usr/local/bin/foo + ;; +esac +``` + +Towards the final form (vo), and generally as far as using exec goes, the +author elucidates a frustration with an untidy pstree(1) output and frankly +I find that argument unpersuasive. More important than an aesthetic situation +that might be encountered rarely (are you often looking at the process table +in another window while running a script?) is being able to figure out where a +hung program came from. I've had many situations where a remote filesystem +hangs and a bunch of programs back up blocked waiting on IO and if they all +were just exec'd binaries over shell scripts I'd never be able to say track +down the cron(8) job that fired them off. Exec also obviates the ability for +any sort of cleanup or trap handler functions from running leading to the +question, why is this a shell script? If you truly are making a script that +is literally as shown in vo above, you should probably just use an alias or a +function in your .profile instead. You save yourself the performance and +security concerns of executing a new copy of the shell entirely there. + +Hopefully my thoughts make it clear that I value simplicity, portability and +maintainability in most things, and doubly so in shell scripts. I have +scripts that have roots over 20 years ago and they generally get polished down +to be as short, and simple as possible. If you don't want to find yourself +mad at it at some point in the future, leave as few traps for yourself as you +can. + +For further reading one might find an annotated view of my .profile[2] +interesting. + +=> /~mernisse/14.gmi [2] +