Monday, April 4, 2022

Do I Need to Restart This Process

Co-worker on another project wanted to know "how do I write a script to restart a process only if it was last started before the system was most-recently patched. So, I Slacked him a quick "one-liner" of:

if [[ $(
         date -d "$(
            ps -p $(
               pgrep <SERVICE_PROCESS_NAME>
            ) -o lstart=
         )" "+%s"
      )
      -lt
      $(
         rpm -qa --qf '%{installtime}\n' | sort -n | tail -1
      ) ]]
then
   <CODE_TO_EXECUTE>
   …
else
   echo "Nothing to do (service restarted since last RPM was installed)"
fi

The above is a simple equality test where two (epoch) times are being compared. Epoch-time is used for comparison as it is the easiest format from which to determine, "is Time-1 more or less recent than Time-2".

Left-hand comparator:

The left expression uses a nested subshell to convert the target-processes start time from its normal format to epoch time. From the inside of the nest outward:

    1. Use `pgrep` to get the process-ID (PID) of the target service. The <SERVICE_PROCESS_NAME> value needs to be a string that appears only once in the process table
    2. Use the `ps` utility's `-p` flag to constrain output to that of the PID returned from the `pgrep` subshell and display only the targeted-process's  `lstart` attribute. The `lstart` attribute is one of several start-related attributes for a process (see man page for details).  Use of `lstart` attribute is because it provides a full time-specification. The other start-related attributes provide shorter, less-complete time-specifications that are not suitable for conversion to epoch time.
    3. Use the `date` utility's `-d` flag to specify the format of the time-string returned by the `ps` subshell – converting that subshell's time-string to epoch-format with the `%s` format-specifier.

Right-hand comparator:

The right expression is getting the install time of the most recently installed RPM. When using the `rpm` utility's query-format (`--qf`) to dump out an RPM's `installtime` attribute, the attribute-string is already in epoch-format and requires no further output-massaging. When using the `rpm` utility's "query all" capability, output is not time-sorted. Since the `installtime` attribute is just a numerical string, the output can be effectively time-sorted by using `sort -n`. Since we're only interested in the youngest RPM, using `tail -1` gets us the final element of the number-sorted output.

I did note to my co-worker that, if they're following a "patch and reboot" standard that his service-process should never be older than the most-recently installed RPM. So, not sure what the ultimate aim of the test will be.

No comments:

Post a Comment