Skip to content

Instantly share code, notes, and snippets.

@jirutka
Last active April 11, 2018 23:50
Show Gist options
  • Save jirutka/5cf0e731dbc39a3a6fff0c6e1a2c2510 to your computer and use it in GitHub Desktop.
Save jirutka/5cf0e731dbc39a3a6fff0c6e1a2c2510 to your computer and use it in GitHub Desktop.
Script for finding PID of running OpenRC service and vice versa.
#!/bin/sh
#---help---
# Usage: rc-service-pid [-h | SVCNAME | PID]
#
# Prints list of running OpenRC services with their PIDs (services which PID
# cannot be resolved are omitted). If SVCNAME is provided, prints only PID
# of service with name SVCNAME. If PID is provided, prints name of the
# service that started process with the given PID or its ancestor.
#
# Source: <https://gist.github.com/jirutka/5cf0e731dbc39a3a6fff0c6e1a2c2510>
#---help---
set -eu
# Set pipefail if supported.
if ( set -o pipefail 2>/dev/null ); then
set -o pipefail
fi
OPENRC_LIB='/lib/rc'
help() {
sed -En '/^#---help---/,/^#---help---/p' "$0" | sed -E 's/^# ?//; 1d;$d;'
exit ${1:-0}
}
# Prints names of started (running) services in all runlevels.
started_services() {
rc-status --servicelist --no-color \
| grep '\[ *started *\]' \
| sed -En 's/ *([^ ]+).*/\1/p'
}
# Prints value $2 of the service with name $1.
service_get_value() {
RC_SVCNAME="$1" "$OPENRC_LIB"/bin/service_get_value "$2"
}
# Prints PID of the service with name $1.
service_pid() {
local pidfile=$(service_get_value "$1" pidfile || echo "/run/$1.pid")
local pid=$(head -n 1 "$pidfile" 2>/dev/null)
[ "$pid" ] && printf '%d\n' "$pid" || false
}
# Returns 0 if PID $1 is descendant of PID $2, 10 otherwise.
is_pid_descendant() {
local pid="$1"
local apid="$2"
ps -o pid= -o ppid= | sort -nr -k 1 | awk -v pid=$pid -v apid=$apid '
{
if ($1 == pid) {
if ($2 == apid) { found = 1; exit 0 }
pid = $2
}
}
END { if (!found) exit 10 }
'
}
# Print all started services with known PID
if [ $# -eq 0 ]; then
for svc in $(started_services); do
pid=$(service_pid $svc) && printf '%s\t%d\n' $svc $pid
done
# Print help
elif [ "$1" = -h ]; then
help 0
# Invalid usage
elif [ $# -gt 1 ]; then
help 100
# Find service by PID
elif [ "$1" -eq "$1" ] 2>/dev/null; then # if $1 is a number
for svc in $(started_services); do
pid=$(service_pid $svc) || continue
if [ "$pid" -eq $1 ] || is_pid_descendant $1 $pid; then
printf '%s\t%d\n' $svc $pid; exit 0
fi
done
exit 1
# Find PID of the service
else
service_pid "$1"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment