Hello,
Within the context of, say, an s6 run script that needs to do a little bit of
prep work before execing into a server, it is often helpful to abort early if
any of said prep work stumbles upon an unexpected problem.
Maybe the filesystem is R/O.  Or full.
Maybe an operator has fat-fingered something we need.
Who knows!  Production is full of surprises.
sh provides set -e, which is often satisfactory for simple prep scripts
(if one is aware of its footguns).
Is there a succinct, idiomatic set -e equivalent in the execline suite?
I have included an example s6 run script below, which demonstrates the closest I
have come so far.  fgsigwait is my alternative take on foreground[1].  fgsigwait
behaviour differs in the following respects:
* fgsigwait exits[2] if prog1 exits with non-zero status.
  foreground, by comparison, sets the ? environment variable and continues.
  (fgsigwait -! reverts to foreground-ish behaviour.)
* fgsigwait forwards some trappable signals to its child.  HUP, INT, etc.
  This is where its name comes from.
  (PID 1 is broken on some of our systems, which provided the initial motivation
  for this hack.  fgsigwait always waits on prog1 after forwarding a signal.
  This, plus execline's execution model, gave me fine control over when stuff
  is forked -- and helped us avoid some Z process leaks.  Anyhoo.)
fgsigwait otherwise aims to be a syntactic execlineb drop-in for foreground in
cases where these features are desired.  Chaining stuff with fgsigwait emulates
sh set -e without needing to repeatedly and explicitly test the ? env var.
--- 8< ---
#!/usr/bin/env -S execlineb -WP
fdmove -c 2 1
# slow-deathroll is a simple wrapper around
# github.com/leahneukirchen/snooze
# extends the s6 one-second restart penalty if we crash too soon
fgsigwait { slow-deathroll }
# Here is a simple example of some prep work.
# We want to bail here if any of these things exit non-zero.
fgsigwait {
  execline-cd data
  if -t { test ! -e live } fgsigwait { mkdir -p empty } ln -s empty live
}
# maybe a smidge more prep here...
# all prep done.  exec into our server.
nsd -d -c nsd.conf
--- >8 ---
This does work OK, but, every time I reach for my little program, I can't shake
the feeling that I am probably reinventing some wheel.
fgsigwait was implemented in Go, as is personal tradition when something need be
hacked up in a hurry on the clock.  Spooling up the Go runtime eats a few extra
milliseconds of time, and a few megabytes of memory.  While not practically
significant to us -- we don't deploy to tiny machines -- a small part of me was
sad to add bloat.  It would be nice if I could get rid of it.
Is there a better way to abort?
I suppose I could just fork sh, but inlining is pleasant when the prep is short.
Thanks!
[1]: 
https://skarnet.org/software/execline/foreground.html
[2]: 
https://skarnet.org/software/execline/exitcodes.html
Received on Mon Sep 05 2022 - 20:54:48 CEST