Re: Single-user actions on reboot

From: Jamie Landeg-Jones <jamie_at_catflap.org>
Date: Fri, 29 Sep 2023 14:34:10 UTC
Guido Falsi <mad@madpilot.net> wrote:

> This is effective but requires the disk mounted r/w which maybe is not 
> enough for you.
>
> Problem is, without any writable media mounted, how can any script 
> register it has already ran?

To get around that (and I know it's not the same thing, but it does the job
for me), I have a script that checks for a marker file in /etc and if it
exists, only runs if the file timestamp is newer than the current time.

I then have various helper scripts to set the date on that file to (e.g.)
15 minutes in the future.

This shuld really be made more generic (having the commands to be run
within the so called flag file), but as it stands, I just use this as
an added file to /etc/rc.d/

This particular example is based on /etc/rc.d/fsck but is added (don't
replace it!), and just forces a full fsck on all filesystems on boot.

It's not clean, and really should be merged into /etc/rc.d/fsck , to
avoid the double-fsck for one thing, but it was a quick and dirty hack
that does the job.

I have a script "force-fsck" that simply does this:

#!/bin/sh
/usr/bin/touch -t "$(/bin/date -v +15M '+%Y%m%d%H%M.%S')" /etc/.force-fsck-expire

which i run prior to doing the reboot. The drop-in script,
/etc/rc.d/fsck_force_full is here if anyone is interested:

https://www.dyslexicfish.com/jamie/freebsd/etc_rc.d_fsck__force__full

Though the meat of it is this:

|         flagfile="/etc/.force-fsck-expire"
|
|         # We have to make sure we only use commands here that exist on the root partition,
|         # as "/usr" and other partitions won't be mounted at this point. Also, we can't use
|         # a marker file that gets removed as the mount at this stage is read-only!
|
|         if [ -f "$flagfile" ] &&                                 # If the flagfile exists,
|             expire_time_1="$(/bin/ls -lD '%s' "$flagfile")" &&   # read it's "mtime", in seconds since epoch
|             [ "$expire_time_1" ] &&                              # If we get a result,
|             expire_time_2="${expire_time_1% $flagfile}" &&       # strip the filename off the end of the string.
|             [ "x$expire_time_2" != "x$expire_time_1" ] &&        # If this operation is successful,
|             expire_time_1="${expire_time_2##* }" &&              # strip the rest of the cruft from beginning of the string.
|             [ "x$expire_time_2" != "x$expire_time_1" ] &&        # If this operation is successful,
|             [ "${expire_time_1%%*[!0-9]*}" ] &&                  # and if the result is a valid integer,
|             [ "$expire_time_1" -gt "$(/bin/date +%s)" ]          # and if the result is older than the current date, then.....
|           then
|                ........
|         fi

Jason, the script could easily be modified by replacing the fsck command with whatever you want to run..

Cheers, Jamie