FreeBSD-init

From wikinotes
Revision as of 15:29, 20 February 2022 by Will (talk | contribs)

Documentation

official tutorial https://docs.freebsd.org/en/articles/rc-scripting/#rcng-dummy

Locations

/etc/rc.d/* system rc scripts
/usr/local/etc/rc.d/* user rc scripts

Managing Services

All daemons are enabled, and primarily configured in the /etc/rc.conf. rcvars (variables which can be overridden in rc.conf) are listed in the program's rcscript /usr/local/etc/rc.d.

# /etc/rc.conf:
sshd_enable="YES"
sshguard_enable="YES"
sshguard_whitelist="/etc/sshguard.whitelist"

Services can be managed from the commandline very simply:

service sshguard start              # start   service
service sshguard stop               # stop    service
service sshguard restart            # restart service

Force Starting Broken InitScripts

Sometimes, you don't have time to troubleshoot why a particular command is not working. You can get around this in two ways:

rc.local method

# /etc/rc.local
/usr/local/etc/rc.d/${MY_SERVICE} start # bypass rc.d init and run

crontab method

su
crontab -u
# crontab

@reboot  /usr/local/etc/rc.d/<my_service> start
https://forums.freebsd.org/threads/31249/

Init Scripting

NOTE:

Checkout the following initscripts (in my saltstack repostiory) for simple examples:

  • taskwarrior's taskd
  • minecraft
https://www.freebsd.org/doc/en/articles/rc-scripting/rcng-dummy.html Official Documentation
/etc/rc.subr Library of rc-script functions

Skeleton File

#!/bin/sh

# PROVIDE: myservice                   # allows other services to require 'myservice'
# REQUIRE: DAEMON                      # before this service starts, DAEMON must be provided
# KEYWORD: shutdown                    # this service must be killed before the system shuts down

. /etc/rc.subr                         # source rc.subr, generic rc-script functions
# General Commands

name="myservice"                        # mandatory unique-name for script
rcvar="myservice_enable"                # name of variable in /etc/rc.conf used to enable service
# Read User-Configuration in /etc/rc.conf
# Set Variables that can be used in rc.conf

load_rc_config $name                             # load variables from /etc/rc.conf

: ${myservice_enable:=NO}                       # rc.conf variables, and their defaults
: ${myservice_config=/etc/myservice.conf}
: ${myservice_user=will}
# Environment Variables
${name}_env="VAR=value VAR2=value" # you can set environment variables for the command this way
# Builtin Variables thave affect CLI command to be run
${name}_user=myuser                                    # user to run command as (using su)
pidfile=/var/run/myservice/myservice.pid                # pidfile path
command=/usr/local/bin/myservice                       # path to binary
command_args="-d -p ${pidfile}"                         # arguments to use against $command
command_interpreter=/usr/local/bin/python2.7           # use different interpreter than /bin/sh
# Other Builtin Variables

# Command is not run if files do not exist
required_files="/etc/${name}.conf /usr/share/misc/${name}.rules"
# Start/Stop/Restart/... Functions

start_cmd="${name}_start"            # override default /etc/rc.subr start function with the function ${name}_start
stop_cmd=":"                         # use default /etc/rc.subr stop_cmd function

start_precmd="echo start"            # runs before 'start'
start_postcmd="echo end"             # runs after successful 'start'

dummy_start()                        # define your own functions
{
    echo "Nothing started."
}
# run Command

run_rc_command "$1"                   # based on above conts, run command using /etc/rc.subr function

Debugging

You can create 'debug mode' for a particular init script by adding the following lines to it's init script (just below the shebang), then rebooting and checking /tmp/output.txt.

set -xv
exec 1>/tmp/output.txt 2>&1

Daemonize Non-Daemon Programs

FreeBSD provides the program daemon which manages forking processes along with their pidfile. Simply use this as your command instead. Note that you will need to manage your status/stop manually if running the program this way.

pidfile=/var/run/program_name.pid

is_running(){
    if [ -f $pidfile ]; then
        pgrep `cat $pidfile`
        return $0
    fi

    return 1
}

program_status(){
    if is_running; then
        echo "${name} is running"
    else
        echo "${name} is not running"
    fi
}

program_stop() {
    if is_running; then
        echo "stopping ${name}"
        kill -15 `cat pidfile`
    else
        echo "${name} is not running"
    fi
}


status_cmd=program_status
stop_cmd=program_stop

command="/usr/sbin/daemon"
command_args="-u $command_user -f -p $pidfile    $program_name -x -y -z"