#!/bin/bash USAGE=' USAGE: rpid [=login] pid The PID of the process for which you want to find the root PID. root_name The name (not command line) of the root process, for which to find the PID. Defaults to login. EXAMPLES: Any of these will display this help message. rpid -h rpid -help rpid --help Get the PID of the login process that is the ancestor of the current process. rpid $$ Get the PID of the first ancestor of the current process, if there is no ancestor named "not_a_process." rpid $$ not_a_process Get the PID of the current process itself, if it is named "current_process." rpid $$ current_process ' # Validate the arguments if [[ "$#" -lt 1 || "$#" -gt 2 ]]; then printf '%s' "${USAGE}" 1>&2 exit 128 fi pid="$1" # Check if the user needs help if [[ "${pid}" =~ ^(-h|-(-)?help)$ ]]; then printf '%s' "${USAGE}" 1>&2 exit 0 fi root_name="${2:-login}" get_info() { local -ri current_pid="$1" if [[ ! -r "/proc/${current_pid}/status" ]]; then exit 1; fi mapfile info < \ <(grep --null -E -m 2 '^(Name|PPid):' "/proc/${current_pid}/status" \ | sort | cut -f 2) name="${info[0]##[[:space:]]}" name="${name%%[[:space:]]}" ppid="${info[1]##[[:space:]]}" ppid="${ppid%%[[:space:]]}" } prev_pid="${pid}" current_pid="${pid}" while [[ "${name}" != "${root_name}" && -r "/proc/${current_pid}/status" ]]; do mapfile info < \ <(grep --null -E -m 2 '^(Name|PPid):' "/proc/${current_pid}/status" \ | sort | cut -f 2) name="${info[0]##[[:space:]]}" name="${name%%[[:space:]]}" prev_pid="${current_pid}" current_pid="${info[1]##[[:space:]]}" current_pid="${current_pid%%[[:space:]]}" done printf '%s\n' "${prev_pid}" if [[ "${name}" != "${root_name}" ]]; then exit 1; fi