cli: survive the --serve transition when nobody is watching
Deploying v0.8.0 broke fmr, and the reason is a flaw I should have seen: self-update is executed by the OLD binary, so the unit repair I put in the new binary's updater cannot fix the very update that installs it. The unit kept its argument-less ExecStart, the new binary answered that with usage and exit 2, and the service went into a restart loop. Fixed on fmr by hand, but that is not a fix for anyone else - and the whole premise of an unattended self-update is that nobody is watching when it happens. So: when started with no verb *and* systemd started us, the server repairs the unit and serves anyway, loudly. systemd sets INVOCATION_ID for every service invocation and nothing else does, so a person at a terminal still gets usage and a non-zero exit. Marked as a one-release shim to remove once no deployment predates --serve. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
3cdbccee18
commit
3a4cb1c327
@@ -73,6 +73,26 @@ func run() error {
|
||||
|
||||
switch {
|
||||
case actions.Help:
|
||||
// Compatibility shim for one release.
|
||||
//
|
||||
// Serving became an explicit verb, but self-update is run by the *old* binary — so the
|
||||
// repair added to the updater cannot fix the very update that installs the new one. A
|
||||
// unit written before this change starts us with no arguments, and without this branch
|
||||
// the service would simply stop working, unattended, on a host nobody is watching.
|
||||
//
|
||||
// Only when systemd started us: INVOCATION_ID is set by systemd for every service
|
||||
// invocation and by nothing else, so a person at a terminal still gets usage. Remove
|
||||
// this once no deployment predates --serve.
|
||||
if os.Getenv("INVOCATION_ID") != "" {
|
||||
slog.Warn("started by systemd with no verb — this unit predates --serve; " +
|
||||
"repairing it and serving anyway")
|
||||
if repaired, err := system.RepairExecStart(); err != nil {
|
||||
slog.Error("could not repair the unit; fix ExecStart by hand", "err", err)
|
||||
} else if repaired {
|
||||
slog.Info("systemd unit updated to pass --serve")
|
||||
}
|
||||
return serve(cfg)
|
||||
}
|
||||
config.Usage(os.Stderr)
|
||||
os.Exit(2)
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user