if [ -x "$(command -v gtimeout)" ]; then
Interesting way to check if a command is installed. How is it better than the simpler and more common "if command...; then"?Techniques I use to create a great user experience for shell scripts
91–100 of 281 posts
Re: Techniques I use to create a great user experience for shell scripts
#92if [ -x "$(command -v gtimeout)" ]; then Interesting way to check if a command is installed. How is it better than the simpler and more common "if command...; then"?
Re: Techniques I use to create a great user experience for shell scripts
#93Earlier quoted context omitted.
If you're trying to write a full fledged program in it, it's going to be a pain as there are only strings (and arrays, I think). Bash is for scripting. If you have complex logic to be done, use another programming language like perl, ruby, python, $YOUR_PREFERRED_ONE,...
You’re arguing that the power of PowerShell is pointless because you’ve resorted to alternatives to bash… because it’s not good enough for common scenarios. This is Stockholm Syndrome. You’ve internalised your limitations and have grown to like them.
Re: Techniques I use to create a great user experience for shell scripts
#94Earlier quoted context omitted.
> "So no, I don’t want my shell to also have to talk..." What's the point of the shell, if not to manage your databases, your REST APIs, files, and mail? Is it something you use for playing games on, or just for fun? > designed to do one thing well. Eeexcept that this is not actually true in practice, because the abstraction was set at a level that's too low . Shoving everything into a character (or byte) stream turn…
> What's the point of the shell, if not to manage your databases, your REST APIs, files, and mail? Is it something you use for playing games on, or just for fun? It's for communicating with the operating system, launching commands and viewing their output. And some scripting for repetitive workflows. If I'd want a full programming environment, I'd take a Lisp machine or Smalltalk (a programmable programming environme…
Sure, on Linux, where your only common options bash or "software".
On Windows, with PowerShell, I can don't have to write a software program. I can write a script that reads like a hypothetical C# Shell would, but oriented towards interactive shells.
(Note that there is a CS-Script, but it's a different thing intended for different use-cases.)
Re: Techniques I use to create a great user experience for shell scripts
#95https://dave.autonoma.ca/blog/2019/05/22/typesetting-markdow...
In effect, create a list of dependencies and arguments:
#!/usr/bin/env bash
source $HOME/bin/build-template
DEPENDENCIES=(
"gradle,https://gradle.org"
"warp-packer,https://github.com/Reisz/warp/releases"
"linux-x64.warp-packer,https://github.com/dgiagio/warp/releases"
"osslsigncode,https://www.winehq.org"
)
ARGUMENTS+=(
"a,arch,Target operating system architecture (amd64)"
"o,os,Target operating system (linux, windows, macos)"
"u,update,Java update version number (${ARG_JAVA_UPDATE})"
"v,version,Full Java version (${ARG_JAVA_VERSION})"
)
The build-template can then be reused to enhance other shell scripts. Note how by defining the command-line arguments as data you can provide a general solution to printing usage information:https://gitlab.com/DaveJarvis/KeenWrite/-/blob/main/scripts/...
Further, the same command-line arguments list can be used to parse the options:
https://gitlab.com/DaveJarvis/KeenWrite/-/blob/main/scripts/...
If you want further generalization, it's possible to have the template parse the command-line arguments automatically for any particular script. Tweak the arguments list slightly by prefixing the name of the variable to assign to the option value provided on the CLI:
ARGUMENTS+=(
"ARG_JAVA_ARCH,a,arch,Target operating system architecture (amd64)"
"ARG_JAVA_OS,o,os,Target operating system (linux, windows, macos)"
"ARG_JAVA_UPDATE,u,update,Java update version number (${ARG_JAVA_UPDATE})"
"ARG_JAVA_VERSION,v,version,Full Java version (${ARG_JAVA_VERSION})"
)
If the command-line options require running different code, it is possible to accommodate that as well, in a reusable solution.Re: Techniques I use to create a great user experience for shell scripts
#96Nowhere in this list did I see “use shellcheck.” On the scale of care, “the script can blow up in surprising ways” severely outweighs “error messages are in red.” Also, as someone else pointed out, what if I’m redirecting to a file?
Always fun trying to read errors in a CI build and they are full of [[
Re: Techniques I use to create a great user experience for shell scripts
#97Earlier quoted context omitted.
> "So no, I don’t want my shell to also have to talk..." What's the point of the shell, if not to manage your databases, your REST APIs, files, and mail? Is it something you use for playing games on, or just for fun? > designed to do one thing well. Eeexcept that this is not actually true in practice, because the abstraction was set at a level that's too low . Shoving everything into a character (or byte) stream turn…
For fun, I took a crack at your example and came up with this craziness (with the caveat it's late and I didn't spend much time on it), which is made a bit more awkward because grep doesn't do capturing groups: netstat -aln \ | grep ESTABLISHED \ | awk '{print $4}' \ | grep -Po '\:\d+$' \ | grep -Po '\d+' \ | sort \ | uniq -c \ | sort -r \ | head -n 10 Changing the awk field to 5 instead of 4 should get you remote po…
1. Your script outputs an error when run, because 'bash' itself doesn't have netstat as a built-in. That's an external command. In my WSL2, I had to install it. You can't declaratively require this up-front, you script has to have an explicit check... or it'll just fail half-way through. Or do nothing. Or who knows!?
PowerShell has up-front required prerequisites that you can declare: https://learn.microsoft.com/en-us/powershell/module/microsof...
Not that that's needed, because Get-NetTcpConnection is a built-in command.
3. Your script is very bravely trying to parse output that includes many different protocols, including: tcp, tcp6, udp, udp6, and unix domain sockets. I'm seeing random junk like 'ACC' turn up after the first awk step.
4. Speaking of which, the task was to get tcp connections, not udp, but I'll let this one slide because it's an easy fix.
5. Now imagine putting your script side-by-side with the PowerShell script, and giving it to people to read.
What are the chances that some random person could figure out what each one does?
Would they be able to modify the functionality successfully?
Note that you had to use 'awk', which is a parser, and then three uses of 'grep' -- a regular expression language, which is also a kind of parsing.
The PowerShell version has no parsing at all. That's why it's just 4 pipeline expressions instead of 9 in your bash example.
Literally in every discussion about PowerShell there's some Linux person who's only ever used bash complaining that PS syntax is "weird" or "hard to read". What are they talking about!? It's half the complexity for the same functionality, reads like English, and doesn't need write-only hieroglyphics for parameters.
Re: Techniques I use to create a great user experience for shell scripts
#98Here's a script that left an impression on me the first time I saw it: https://github.com/containerd/nerdctl/blob/main/extras/rootl... I have since copied this pattern for many scripts: logging functions, grouping all global vars and constants at the top and creating subcommands using shift.
Re: Techniques I use to create a great user experience for shell scripts
#99I'd add, in each my Bash scripts I add this line to get the script's current directory: SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) This is based on this SA's answer: https://stackoverflow.com/questions/59895/how-do-i-get-the-d... I never got why Bash doesn't have a reliable "this file's path" feature and why people always take the current working directory for granted!
readonly SCRIPT_SRC="$(dirname "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}")"
readonly SCRIPT_DIR="$(cd "${SCRIPT_SRC}" >/dev/null 2>&1 && pwd)"
readonly SCRIPT_NAME=$(basename "$0")Re: Techniques I use to create a great user experience for shell scripts
#100Nowhere in this list did I see “use shellcheck.” On the scale of care, “the script can blow up in surprising ways” severely outweighs “error messages are in red.” Also, as someone else pointed out, what if I’m redirecting to a file?
Always fun trying to read errors in a CI build and they are full of [[