Handy scripts you'd like to share

Quick-and-dirty "need reboot" script.

There are much more advanced options already existing, but I wanted it the most KISS as possible.
It's also tolerably fast.
Only standard tools used: bash, date, uname, file, grep, sed, awk, paste, column, and /proc files.
No attempt at restarting services, not even mapping processes to service names.
Not well tested, likely to miss something and crap out in some cases, standard disclaimer applies.
Intended to run with sudo else only user processes are listed.
Can be called from command line or sourced for the functions.
Reports running and installed kernel versions, last update to /boot, running updated binaries.

reboot_test.sh
#!/bin/bash

last_chboot()                 { date -r /boot +%s; }
last_chboot_hr()              { date -r /boot +'%F %T'; }
last_reboot()                 { date -r /proc +%s; }
last_reboot_hr()              { date -r /proc +'%F %T'; }
upgraded_boot()               (( $(last_chboot) > $(last_reboot) ))
upgraded_boot_hr()            { upgraded_boot && echo yes || echo no; }
currently_booted_image()      { grep -Po 'BOOT_IMAGE=/@\K\S+' /proc/cmdline; }
currently_running_kernel()    { uname -r; }
currently_installed_kernel()  { file $(currently_booted_image) |grep -Po 'version \K\S+'; }
currently_installed_kernels() { file /boot/vmlinuz* |grep -Po 'version \K\S+' |paste -sd' '; }
upgraded_running_kernel()     { [ $(currently_running_kernel) != $(currently_installed_kernel) ]; }
upgraded_running_kernel_hr()  { upgraded_running_kernel && echo yes || echo no; }

# NOTE: $1=pid $6=pathname $7="(deleted)"
awk_uniq_del_paths_simple() { # unused, no command / user name, only pathname and list of pids
  awk '$6 && $7 {pathpids[$6]=(pathpids[$6] " " $1)} END { for (pp in pathpids) print pp " " pathpids[pp] }';
}
awk_uniq_del_paths() {
  awk ' $6 && $7 {pathpids[$6][$1]=""}
        END {
          for (path in pathpids) for (pid in pathpids[path]) {
            getline uid < ("/proc/" pid "/loginuid")
            ("id -nu " uid) | getline user
            getline comm < ("/proc/" pid "/comm")
            print pid " " comm " " uid " " user " " path
          }
        }
      '
}
upgraded_mapped_executables() {
  trap "$(shopt -p nullglob)" RETURN; shopt -s nullglob
  local p
  for p in /proc/{1..9}*; do
    sed -En '/^\S+ +..x. .*[^]]$/ {s/^\S+/'"${p:6}"'/;p}' "$p/maps" 2>&-
  done |awk_uniq_del_paths
}
upgraded_mapped_executables_hr() {
  echo # just to simplify printing function names and results
  upgraded_mapped_executables |column -t -N'pid,comm,uid,user,path' -R1,3
}

return 0 2>&- # exit if sourced

for fn in currently_{booted_image,running_kernel,installed_kernel{,s}} last_{ch,re}boot_hr upgraded_{boot,running_kernel,mapped_executables}_hr; do
  printf '%-32s : ' "$fn"; $fn
done
example output

(I reinstalled mpg123 and rebuilt initramfs)

currently_booted_image           : /boot/vmlinuz-linux-zen
currently_running_kernel         : 6.2.10-zen1-1-zen
currently_installed_kernel       : 6.2.10-zen1-1-zen
currently_installed_kernels      : 6.2.10-zen1-1-zen
last_chboot_hr                   : 2023-04-13 16:41:59
last_reboot_hr                   : 2023-04-12 22:13:36
upgraded_boot_hr                 : yes
upgraded_running_kernel_hr       : no
upgraded_mapped_executables_hr   :
  pid  comm         uid  user      path
  907  waybar      1000  meanruse  /usr/lib/libmpg123.so.0.47.0
27794  firedragon  1000  meanruse  /usr/lib/libmpg123.so.0.47.0

________________________________________________________
Executed in    1.77 secs    fish           external
   usr time    1.11 secs    0.75 millis    1.11 secs
   sys time    0.69 secs    3.02 millis    0.69 secs

May do as a quick reminder, beware it's far from being dependable.

1 Like