What do you advice for shell usage?
- Do you use bash? If not, which one do you use? zsh, fish? Why do you do it?
- Do you write
or
? Do you write fish exclusive scripts?
- Do you have two folders, one for proven commands and one for experimental?
- Do you publish/ share those commands?
- Do you sync the folder between your server and your workstation?
- What should’ve people told you what to do/ use?
- good practice?
- general advice?
- is it bad practice to create a handful of commands like
podup
andpoddown
that replacepodman compose up -d
andpodman compose down
orpodlog
aspodman logs -f --tail 20 $1
orpodenter
forpodman exec -it "$1" /bin/sh
?
Background
I started bookmarking every somewhat useful website. Whenever I search for something for a second time, it’ll popup as the first search result. I often search for the same linux commands as well. When I moved to atomic Fedora, I had to search for rpm-ostree
(POV: it was a horrible command for me, as a new user, to remember) or sudo ostree admin pin 0
. Usually, I bookmark the website and can get back to it. One day, I started putting everything into a .bashrc
file. Sooner rather than later I discovered that I could simply add ~/bin
to my $PATH
variable and put many useful scripts or commands into it.
For the most part I simply used bash. I knew that you could somehow extend it but I never did. Recently, I switched to fish because it has tab completion. It is awesome and I should’ve had completion years ago. This is a game changer for me.
I hated that bash would write the whole path and I was annoyed by it. I added PS1="$ "
to my ~/.bashrc
file. When I need to know the path, I simply type pwd
. Recently, I found starship which has themes and adds another line just for the path. It colorizes the output and highlights whenever I’m in a toolbox/distrobox. It is awesome.
I use fish shell only now. Used to only write bash, but I’ve started writing some fish scripts. I wouldn’t try to plan too much WRT shell scripting up front. Just fix your pain points as you go.
Use
set -x
For debugging
That’s the way I do it:
#!/usr/bin/env nix #! nix shell nixpkgs#nushell <optionally more dependencies> --command nu <script content>
But those scripts are only used by me
This is the way
Do you use bash? Yes because it is everywhere and available by default.
Yes, using bash on all boxen.
Scripts start with #!/bin/sh ,because, that gives quicker execution times.
Any simple aliases, I put in .bash_aliases
Tried tcsh and zsh around 30yrs ago, all bash since then.
Do you have to chmod all your scripts when you include the shebang? Or do you have it configured to save with the right permissions?
I chmod 755 each manually. I’ve never tried the automatic way, sounds easier.
- Fish. Much, much saner defaults.
- I am writing
for dead simple scripts, so they will be a tiny bit more portable and run a tiny bit faster. The lack of arrays causes too much pain in longer scripts. I would love to use Fish, but it lacks a strict mode.
- No, why would I?
- I used to share all my dotfiles, scripts included, but I was too afraid that I would publish some secrets someday, so I stopped doing that. For synchronizing commands, aliases and other stuff between computers I use Chezmoi.
- To use Fish instead of fighting with start up time of Zsh with hundreds of plugins
- Always use the so-called “strict mode” in Bash, that is, the
set -euo pipefail
line. It will make Bash error on non-zero exit code, undefined variables and non-zero exit codes in commands in pipe. Also, always use shellcheck. It’s extremely easy to make a mistake in Bash. If you want to check the single command exit code manually, just wrap it inset +e
andset -e
. - Consider writing your scripts in Python. Like Bash, it also has some warts, but is multiplatform and easy to read. I have a snippet which contains some boilerplate like a
main
function definition withArgumentParser
instantiated. Then at the end of the script themain
function is called wrapped intry … except KeyboardInterrupt: exit(130)
which should be a default behavior. - Absolutely not a bad practice. If you need to use them on a remote server and can’t remember what they stand for, you can always execute
type some_command
. Oh, and read about abbreviations in Fish. It always expands the abbreviation, so you see what you execute.
I use
sh
to attempt to keep it compatible with POSIX systems.I use pain bash. Never really tried zsh and fish, since most of my Linux work is on servers and I don’t really care for extra features.
I try and write idempotent scripts when possible.
I wouldn’t create those aliases on a fleet because writing them to the configuration file of your shell in an idempotent fashion is hacky and my VMs are like cattle.
#!/usr/bin/env bash
A folder
dotfiles
as git repository and adotfiles/install
that soft links all configurations into their places.Two files,
~/.zshrc
(without secrets, could be shared) and another for secrets (sourced by.zshrc
if exist secrets).dotfiles
Thanks! I’ll check them out. I knew the cooncept existed but so far I didn’t dig deep into managing them. This is my start I guess https://wiki.archlinux.org/title/Dotfiles
Am I missing something - doesn’t bash have tab completion or of the box?
hardly
I use bash as my interactive shell. When ~20 years ago or so I encountered “smart” tab completion for the first time, I immediately disabled that and went back to dumb completion, because it caused multi-second freezes when it needed to load stuff from disk. I also saw it refuse to complete filenames because they had the wrong suffix. Maybe I should try to enable that again, see if it works any better now. It probably does go faster now with the SSDs.
I tried OpenBSD at some point, and it came with some version of ksh. Seems about equivalent to bash, but I had to modify some of my .bashrc so it would work on ksh. I would just stick to the default shell, whatever it is, it’s fine.
I try to stick to POSIX shell for scripts. I find that I don’t need bashisms very often, and I’ve used systems without bash on them. Most bash-only syntax has an equivalent that will work on POSIX sh. I do use bash if I really need some bash feature (I recently wanted to
set -o pipefail
, which dash cannot do apparently, and the workaround is really annoying).Do not use
if you’re not writing bash-only scripts. This will break on Debian, Ubuntu, BSD, busybox etc. because /bin/sh is not bash on those systems.
Do not use #!/bin/sh if you’re not writing bash-only scripts
Actually
is for bourne shell compatible scripts. Bash is a superset of the bourne shell, so anything that works in bourne should work in bash as well as in other bourne compatible shells, but not vice versa. Bash specific syntax is often referred to as a “bashism”, because it’s not compatible with other shells. So you should not use bashisms in scripts that start with
.
The trouble is that it is very common for distros to links
/bin/sh
to/bin/bash
, and it used to be that bash being called as/bin/sh
would change its behavior so that bashisms would not work, but this doesn’t appear to be the case anymore. The result is that people often write what they think are bourne shell scripts but they unintentionally sneak in bashisms… and then when those supposed “bourne shell” scripts get run on a non-bash bourne compatible shell, they fail.Oh I wanted to say, “Do not use
if you’re
notwriting bash-only scripts”. I think I reformulated that sentence and forgot to remove the not. Sorry about the confusion. You’re exactly right of course. I have run into scripts that don’t work on Debian, because the author used bashisms but still specified /bin/sh as the interpreter.Oh I wanted to say, “Do not use #!/bin/sh if you’re not writing bash-only scripts”
Hah, I was wondering if that was wat you actually meant. The double negation made my head spin a bit.
I have run into scripts that don’t work on Debian, because the author used bashisms but still specified /bin/sh as the interpreter.
The weird thing is that
man bash
still says:When invoked as sh, bash enters posix mode after the startup files are read. ... --posix Change the behavior of bash where the default operation differs from the POSIX standard to match the standard (posix mode). See SEE ALSO below for a reference to a document that details how posix mode affects bash's behavior.
But if you create a file with a few well known bashisms, and a
shebang, it runs the bashisms just fine.
- Do you use bash? If not, which one do you use? zsh, fish? Why do you do it?
- Do you write #!/bin/bash or #!/bin/sh? Do you write fish exclusive scripts?
I use bash, and I use
for my scripts. Some are POSIX compliant, some have bashisms. But I really don’t care about bashisms, since I explicitly set the bash as interpreter. So no, no fish exclusive scripts, but some “bash exclusive” scripts. Since fish is aimed towards being used as interactive shell I don’t see a real reason to use it as interpreter for scripts anyways.
- Do you have two folders, one for proven commands and one for experimental?
- Do you publish/ share those commands?
- Do you sync the folder between your server and your workstation?
I have my scripts in
$HOME/.scripts
and softlink them from a directory in$PATH
. Some of the scripts are versioned using Git, but the repository is private and I do not plan sharing them because the repoand the scripts scripts contain some not-tho-share information and mostly are simply not useful outside my carefully crafted and specific environment. If I want to share a script, I do it individually or make a proper public Git repository for it.Since my server(s) and my workstations have different use cases I do not share any configuration between them. I share some configuration between different workstations, though. My dotfiles repository is mainly there for me to keep track of changes in my dotfiles.
is it bad practice to create a handful of commands
It becomes bad practice if it is against your personal or corporate guidelines regarding best practices. While it is not particularly bad or insecure, etc. to create bash scripts containing a single command, maybe use an alias instead. The
$1
is automatically the first parameter after typing the alias in the shell.alias podup="podman compose up -d" alias poddown="podman compose down" alias podlog="podman logs -f --tail 20"
Not quite sure about the podman syntax, if
podman exec /bin/sh -it "$1"
also works, you can usealias podenter="podman exec /bin/sh -it
, Otherwise a simple function would do the trick.Btw, if you ever wondered why Debian uses dash as /bin/sh (the switch was a bit annoying at the time), I think the reasoning was something like this:
- dash is a bit faster, which might have saved a second or two on boot times (this was before systemd). Same applies to compilation times, configure scripts run faster with dash.
- A bunch of
scripts in Debian did not actually work if you replaced /bin/sh with another shell, which I guess some people wanted to do. Making dash the default /bin/sh forced everyone to fix their scripts.
Also some history on the abomination that is m4sh, famously used by GNU autoconf configure.ac scripts. Apparently when autoconf was released in 1991, there were still some Unix systems that shipped some 70s shells as the default /bin/sh. These shells do not support shell functions, which makes creating any sort of shell programming library pretty much impossible (I guess you could make a folder full of scripts instead of functions). They decided to use m4 preprocessor macros instead, as a sort of poor man’s replacement for functions.
In hindsight, it wish they had told commercial Unix sysadmins to install a proper /bin/sh or gtfo. But the GNU people thought it was important to make it as easy as possible to install free software even on commercial Unices.
Bash script for simple things (although Fish is my regular shell) and Node or Python scripts for complex things. Using
works just like it would for Bash so you know.
Several things
- write bash and nothing else (except posix sh)
- find a good way to take notes. It shouldn’t be in your bashrc
- only write fish for fish config
- use $!/usr/bin/env bash
Good idea I added a “iwish” command a while ago. Whenever I am pissed about gnome not being able to do something, or anything else that didn’t work as it should, I wrote “iwish gnome had only one extension app” and it would add a new line to my wishlist.md Maybe it would be good for notes too.
inote bla
I love thay idea im gonna implement it tonight