Skip to content

Instantly share code, notes, and snippets.

@tkapias
Last active June 1, 2024 12:05
Show Gist options
  • Save tkapias/d66d86fe5c3c7df1470288b27559e296 to your computer and use it in GitHub Desktop.
Save tkapias/d66d86fe5c3c7df1470288b27559e296 to your computer and use it in GitHub Desktop.
lservices - colorized and searchable table of all SystemD units & unit-files - extracted functions from my .bashrc
#!/usr/bin/env bash
# executed by bash(1) for non-login shells.
# ==============================
# FUNCTIONS
# ==============================
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Output a table with header
# uses skim for fuzzy and preview, or default to less or cat.
# skim can use tmux if present.
# from skim 'f1' will cat unit config and status to terminal.
outputviewer() {
if command -v sk-tmux 1> /dev/null; then
$3 sk-tmux -d 75% --case=smart --no-sort --layout=reverse-list --exit-0 --color=dark,bg+:237 --no-mouse --cycle --multi --ansi --tabstop=2 --header-lines=1 \
--prompt="$1" \
--preview-window="right:45%:wrap" \
--bind="ctrl-a:select-all,ctrl-d:deselect-all,ctrl-t:toggle-all,ctrl-p:toggle-preview,f1:execute-silent:($4; $2; echo)" \
--preview="echo -e \"\\\e[1;37mKEYS: \\\e[1;33m󰗼\\\e[1;36menter/esc \\\e[1;33m󰱑\\\e[1;36mtab \\\e[1;33m󰜺\\\e[1;36mctrl-c \\\e[1;33m\\\e[1;36mctrl-a \\\e[1;33m\\\e[1;36mctrl-d \\\e[1;33m/\\\e[1;36mctrl-t \\\e[1;33m󱂩\\\e[1;36mctrl-p\\\n\\\e[1;37mPREVIEW: \\\e[0m\\\n\"; $2"
elif command -v less 1> /dev/null; then
less --no-lessopen --use-color --quit-if-one-screen --ignore-case --LONG-PROMPT --RAW-CONTROL-CHARS --QUIET --no-init --chop-long-lines --tilde --mouse --header 1 --prompt "$1"
else
cat
fi
}
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# colorized and searchable table of all SystemD units & unit-files
# per type,user or system, with a header and a preview.
lservices() {
Help() {
cat <<- HEREDOC
List Systemd units or c-groups.
Simplified and colorful, optional preview and fuzzy search with skim.
Syntax: lservices [-h] [-c] [-p] [-a|-d|m|P|s|S|t|T] [<username>]
Output: ServiceName UID STATE DESCRIPTION
options:
-h Print this Help.
-c Display Systemd c-groups list with systemd-cgls.
-p Disable the pager feature.
Change default listing (service,scopes,socket):
-a List service related units (service,scope,socket,target,timer,slice).
-d List devices.
-m List mounts and automounts.
-P List paths.
-s List slices.
-S List swaps.
-t List targets.
-T List timers.
<username> [root] display --system services,
[other] display --user services,
[empty] default to current user.
HEREDOC
}
local _LIST="service,scope,socket"
local _LISTGREP='\.service|\.scope|\.socket'
local OPTIND=0
while getopts ":hcpadmPsStT" option; do
case $option in
h) Help; return 0 ;;
c) systemd-cgls -la
return 0 ;;
p) local _NOPAGER=1;;
a) local _LIST="service,scope,socket,target,timer,slice"
local _LISTGREP='\.service|\.scope|\.socket|\.target|\.timer|\.slice';;
d) local _LIST="device"
local _LISTGREP="\.$_LIST";;
m) local _LIST="mount,automount"
local _LISTGREP='\.mount|\.automount';;
P) local _LIST="path"
local _LISTGREP="\.$_LIST";;
s) local _LIST="slice"
local _LISTGREP="\.$_LIST";;
S) local _LIST="swap"
local _LISTGREP="\.$_LIST";;
t) local _LIST="target"
local _LISTGREP="\.$_LIST";;
T) local _LIST="timer"
local _LISTGREP="\.$_LIST";;
\?) echo -e "Unknown option: -$OPTARG \n" >&2; Help; return 1;;
: ) echo -e "Missing argument for -$OPTARG \n" >&2; Help; return 1;;
* ) echo -e "Unimplemented option: -$option \n" >&2; Help; return 1;;
esac
done
shift $((OPTIND-1))
if [[ -z $1 ]]; then
local _UID=$(id -u)
else
local _UID=$(id -u $1)
fi
if [[ "$_UID" == "0" ]]; then
local _SYSTEMCTL="systemctl --system"
local _SUDO="sudo TMUX=$TMUX TMUX-PANE=$TMUX-PANE"
local _LOADED=$(sudo systemctl list-units --system -q --plain --full --no-pager -t "$_LIST" | grep -E "$_LISTGREP")
local _OTHER=$(sudo systemctl list-unit-files --system -q --plain --full --no-pager --state disabled,indirect -t "$_LIST" | grep -E "$_LISTGREP")
elif [[ "$_UID" == "$(id -u)" ]]; then
local _SYSTEMCTL="systemctl --user"
local _SUDO=""
local _LOADED=$(systemctl list-units --user -q --plain --full --no-pager -t "$_LIST" | grep -E "$_LISTGREP")
local _OTHER=$(systemctl list-unit-files --user -q --plain --full --no-pager --state disabled,indirect -t "$_LIST" | grep -E "$_LISTGREP")
else
local _SUDO="sudo TMUX=$TMUX TMUX-PANE=$TMUX-PANE"
local _SYSTEMCTL="machinectl -q shell --uid=$_UID .host /usr/bin/systemctl --user"
local _LOADED=$(sudo machinectl -q shell --uid="$_UID" .host /usr/bin/systemctl list-units --user -q --plain --full --no-pager -t "$_LIST" | grep -E "$_LISTGREP")
local _OTHER=$(sudo machinectl -q shell --uid="$_UID" .host /usr/bin/systemctl list-unit-files --user -q --plain --full --no-pager --state disabled,indirect -t "$_LIST" | grep -E "$_LISTGREP")
fi
local _LOADED=$(echo "$_LOADED" | awk ' \
BEGIN {
red = "\033[1;31m"
green = "\033[1;32m"
yellow = "\033[1;33m"
blue = "\033[1;36m"
reset = "\033[0m"
map["running"] = green
map["start"] = green
map["listening"] = green
map["active"] = green
map["mounted"] = green
map["plugged"] = green
map["waiting"] = green
map["exited"] = yellow
map["stop"] = yellow
map["failed"] = red
map["dead"] = red
}
match($0,/^(.*)\.([a-z]+)\s*[a-z-]+\s*([a-z]+)\s([a-z]+)\s*(.*)$/,a) {
status = a[4]
if ( status in map )
$0 = blue a[1] "\t" a[2] reset "\t" map[status] status reset "\t" a[5]
else
$0 = blue a[1] "\t" a[2] reset "\t" a[4] "\t" a[5]
}
{ print } '
)
local _OTHER=$(echo "$_OTHER" | awk ' \
BEGIN {
red = "\033[1;31m"
yellow = "\033[1;33m"
blue = "\033[1;36m"
reset = "\033[0m"
map["disabled"] = red
map["indirect"] = yellow
map["enabled"] = yellow
}
match($0,/^(.*)\.([a-z]+)(\s*)([a-z]+)\s*([a-z]+)$/,a) {
status = a[4]
preset = a[5]
$0 = blue a[1] "\t" a[2] reset "\t" map[status] status reset "\t(preset: " map[preset] preset reset ")"
}
{ print } '
)
local _OUTPUT=$(printf "%s\n%s" "$_LOADED" "$_OTHER" | sort -f -u -t$'\t' -k 1,2)
printf "Unit\tType\tState\tComments\n%s" "$_OUTPUT" | column -s$'\t' -t | outputviewer "Systemd states for '$_LIST' as '$(id -u -n $_UID)' > " "SYSTEMD_URLIFY=0 SYSTEMD_COLORS=1 $_SYSTEMCTL -q --plain --full --no-pager --output=short status -- {1}.{2} | cat" "$_SUDO" "echo; SYSTEMD_URLIFY=0 SYSTEMD_COLORS=1 $_SYSTEMCTL -q --plain --full --no-pager --output=short cat -- {1}.{2} | cat; echo"
}
@tkapias
Copy link
Author

tkapias commented May 22, 2024

image

@tkapias
Copy link
Author

tkapias commented May 22, 2024

Edited Revision 8:

  • Use Skim for fuzzy search and preview the status of the units.
  • Added a static header for skim, less and cat.
  • Added a generated prompt for skim and less.

@tkapias
Copy link
Author

tkapias commented May 22, 2024

Edited Revision 10:

  • Skim bind 'f1' to silently print the unit config file and the status of the highlighted line to the terminal.

@tkapias
Copy link
Author

tkapias commented May 22, 2024

Edited Revisions 11, 12:

  • Added a function to check requirements.
  • Replaced machinectl with systemctl -m.
  • Added TERM=linux when needed for systemctl to not decorate lines.
  • Added some Tmux env variables to sudo.

@tkapias
Copy link
Author

tkapias commented Jun 1, 2024

Edited Revision 16:

  • More optional options for skim to disable h-scroll

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment