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