How to Use status_of_proc Function in Linux Init Scripts: A Deep Dive into Process Status Checking


8 views

When working with Linux init scripts (particularly in Debian-based systems), you might encounter the status_of_proc function that isn't available in your regular shell environment. This function typically appears in LSB-compliant init scripts but remains undefined elsewhere.

The function is part of the /lib/lsb/init-functions package in Debian/Ubuntu systems. This library provides various helper functions for init scripts that comply with the Linux Standard Base specification.


# Source the LSB init functions
. /lib/lsb/init-functions

Here's how you can use status_of_proc in your own scripts:


#!/bin/sh

### BEGIN INIT INFO
# Provides:          my_service
# Required-Start:    $network $local_fs
# Required-Stop:     $network $local_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: My custom service
### END INIT INFO

# Load LSB functions
. /lib/lsb/init-functions

case "$1" in
    status)
        status_of_proc -p /var/run/my_service.pid "/usr/sbin/my_service" "My Service"
        ;;
    *)
        echo "Usage: $0 {start|stop|restart|status}"
        exit 1
        ;;
esac

For cases where you can't rely on the LSB functions, here's the complete function implementation:


status_of_proc() {
    local pidfile daemon name status OPTIND
    pidfile=
    OPTIND=1
    while getopts p: opt; do
        case "$opt" in
            p)
                pidfile="$OPTARG"
                ;;
        esac
    done
    shift $(($OPTIND - 1))
    
    if [ -n "$pidfile" ]; then
        pidfile="-p $pidfile"
    fi
    
    daemon="$1"
    name="$2"
    status="0"
    
    pidofproc $pidfile $daemon > /dev/null || status="$?"
    
    if [ "$status" = 0 ]; then
        log_success_msg "$name is running"
        return 0
    else
        if [ "$status" = 4 ]; then
            log_failure_msg "could not access PID file for $name"
            return $status
        else
            log_failure_msg "$name is not running"
            return $status
        fi
    fi
}

1. Checking service status with PID file:

status_of_proc -p /var/run/nginx.pid nginx "Nginx Web Server"

2. Checking service status without PID file:

status_of_proc /usr/sbin/sshd "SSH Daemon"

If you get "function not found" errors:

  1. Ensure /lib/lsb/init-functions exists
  2. Verify you've sourced the file with . /lib/lsb/init-functions
  3. Check for proper file permissions (should be readable)

For systems without LSB functions, you can implement similar functionality:


check_service_status() {
    local pidfile="$1"
    local process_name="$2"
    local service_name="$3"
    
    if [ -f "$pidfile" ]; then
        local pid=$(cat "$pidfile")
        if ps -p "$pid" > /dev/null 2>&1; then
            echo "[OK] $service_name is running (pid $pid)"
            return 0
        else
            echo "[FAIL] $service_name pid file exists but process is not running"
            return 1
        fi
    else
        if pgrep -x "$process_name" > /dev/null; then
            echo "[OK] $service_name is running"
            return 0
        else
            echo "[FAIL] $service_name is not running"
            return 1
        fi
    fi
}

The status_of_proc function is a valuable utility found in Linux init scripts, particularly in Debian-based systems. This shell function isn't a built-in bash command, but rather part of the LSB (Linux Standard Base) init-functions script that gets sourced by system init scripts.

This function is typically defined in /lib/lsb/init-functions on Debian/Ubuntu systems. The standard init script boilerplate includes:


. /lib/lsb/init-functions

This sourcing makes all LSB helper functions available to the script.

The function performs several key operations:


status_of_proc() {
    local pidfile daemon name status OPTIND
    pidfile=
    OPTIND=1
    while getopts p: opt; do
        case "$opt" in
            p) pidfile="$OPTARG" ;;
        esac
    done
    shift $(($OPTIND - 1))
    if [ -n "$pidfile" ]; then
        pidfile="-p $pidfile"
    fi
    daemon="$1"
    name="$2"
    status="0"
    pidofproc $pidfile $daemon > /dev/null || status="$?"
    if [ "$status" = 0 ]; then
        log_success_msg "$name is running"
        return 0
    else
        if [ "$status" = 4 ]; then
            log_failure_msg "could not access PID file for $name"
            return $status
        else
            log_failure_msg "$name is not running"
            return $status
        fi
    fi
}

Here's how to properly use it in your own scripts:


#!/bin/sh

### BEGIN INIT INFO
# Provides:          mydaemon
# Required-Start:    $network $remote_fs $syslog
# Required-Stop:     $network $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: My custom daemon
### END INIT INFO

# Load LSB functions
. /lib/lsb/init-functions

DAEMON=/usr/sbin/mydaemon
NAME=mydaemon
PIDFILE=/var/run/mydaemon.pid

case "$1" in
    start)
        log_daemon_msg "Starting $NAME"
        start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON
        log_end_msg $?
        ;;
    stop)
        log_daemon_msg "Stopping $NAME"
        start-stop-daemon --stop --quiet --pidfile $PIDFILE --exec $DAEMON
        log_end_msg $?
        ;;
    status)
        status_of_proc -p $PIDFILE $DAEMON $NAME
        exit $?
        ;;
    restart)
        $0 stop
        $0 start
        ;;
    *)
        echo "Usage: $0 {start|stop|status|restart}"
        exit 1
        ;;
esac

exit 0

Problem: Function not found
Solution: Ensure you've sourced init-functions before calling it:


if [ -f /lib/lsb/init-functions ]; then
    . /lib/lsb/init-functions
else
    echo "LSB functions not available" >&2
    exit 1
fi

Problem: Different path on some systems
Solution: Use this more robust sourcing approach:


for path in /lib/lsb/init-functions /etc/init.d/functions; do
    [ -f "$path" ] && . "$path" && break
done

For systems without LSB support, you can define your own version:


status_of_proc() {
    local pidfile="$1"
    local process="$2"
    local name="$3"
    
    if [ -f "$pidfile" ]; then
        local pid=$(cat "$pidfile" 2>/dev/null)
        if [ -n "$pid" ] && ps -p "$pid" >/dev/null 2>&1; then
            echo "$name is running with pid $pid"
            return 0
        else
            echo "$name is not running but pid file exists"
            return 1
        fi
    else
        if pgrep -f "$process" >/dev/null; then
            echo "$name is running but no pid file"
            return 0
        else
            echo "$name is not running"
            return 3
        fi
    fi
}

The function returns standardized exit codes:

  • 0 - Process is running
  • 1 - General failure
  • 3 - Process not running
  • 4 - Could not access PID file