This page looks best with JavaScript enabled

FreeBSD Service

 ·  πŸŽƒ kr0m

Demonizing a program as a service in FreeBSD is very simple, we only need to create an RC script for it. In this article, we will explain how to do it using a very basic C program.

We create a simple program that will do nothing more than run forever:

vi kr0mUtility.c

#include <stdio.h>
#include <unistd.h>

int main(){
    while(1) {
        sleep(1);
    }
}

We compile the software:

cc kr0mUtility.c -o kr0mUtility

We create the RC script that will control our program, we create it under /usr/local/etc/rc.d/ since it is a script that is NOT part of the base system:

vi /usr/local/etc/rc.d/kr0mUtility

#!/bin/sh
#
# PROVIDE: kr0mUtility
# REQUIRE: DAEMON
# KEYWORD: shutdown

. /etc/rc.subr

name=kr0mUtility
rcvar=kr0mUtility_enable

command="/root/kr0mUtility"
start_cmd="kr0mUtility_start"
pidfile="/var/run/${name}.pid"

kr0mUtility_start(){
    echo "starting kr0mUtility."
    /usr/sbin/daemon -c -f -p ${pidfile} ${command}
}

load_rc_config $name
run_rc_command "$1"

We assign the necessary permissions to the RC script:

chmod 555 /usr/local/etc/rc.d/kr0mUtility
chown root:wheel /usr/local/etc/rc.d/kr0mUtility

NOTE: If our program forks in the background, a start_cmd or function would not be necessary, simply the command line would be enough. If only that line is put with the program shown, when the shell starts, it stays “inside” the program until we press Ctrl+c.

We register our service:

vi /etc/rc.conf

kr0mUtility_enable="yes"

We check the status of the service:

bagheera #Root:~> service kr0mUtility status

kr0mUtility is not running.

We start it:

bagheera #Root:~> service kr0mUtility start

starting kr0mUtility.

We check the service again:

bagheera #Root:~> service kr0mUtility status

kr0mUtility is running as pid 98683.

We can see the daemon process that has started our utility:

bagheera #Root:~> ps aux|grep kr0mUtility

root       98395   0.0  0.0    10812   2364  -  Ss   09:27       0:00.00 daemon: /root/kr0mUtility[98683] (daemon)
root       98683   0.0  0.0    10648   2272  -  S    09:27       0:00.00 /root/kr0mUtility
root       11987   0.0  0.0    11272   2732  0  S+   09:27       0:00.00 grep kr0mUtility

We stop the service:

bagheera #Root:~> service kr0mUtility stop

Stopping kr0mUtility.
Waiting for PIDS: 98683.

We check the status:

bagheera #Root:~> service kr0mUtility status

kr0mUtility is not running.

We check that the utility process and daemon no longer exist:

bagheera #Root:~> ps aux | grep kr0mUtility

root       54321   0.0  0.0    11272   2732  0  S+   09:27       0:00.00 grep kr0mUtility

If our utility requires any other service in the RC script, we must indicate it using the REQUIRE parameter. We can get a list of available services with:

grep PROVIDE /etc/rc.d/*
grep PROVIDE /usr/local/etc/rc.d/*

There are some dependencies that have been grouped together so that we don’t have to include them one by one:

  • NETWORK/NETWORKING: This is a dummy dependency, for services which require networking to be operational before starting.
  • SERVERS: This is a dummy dependency, for early-start servers relying on some basic configuration.
  • DAEMON: This is a dummy dependency, to ensure that general purpose daemons are run after the above are(NETWORKING SERVERS).
  • LOGIN: This is a dummy dependency to ensure user services such as xdm, inetd, cron and kerberos are started after everything else, in case the administrator has increased the system security level and wants to delay user logins until the system is (almost) fully operational.
  • FILESYSTEMS: This is a dummy dependency, for services which require filesystems to be mounted before starting. Β It also serves as the default early / late divider; after this point, rc.d directories are rescanned to catch scripts from other filesystems than /.

The KEYWORDS can also be useful:

  • nojail: The service is not for jail(8) environment. The automatic startup and shutdown procedures will ignore the script if inside a jail.
  • nojailvnet: only allow vnet-enabled jails
  • nostart: The service is to be started manually or not started at all. The automatic startup procedure will ignore the script. In conjunction with the shutdown keyword, this can be used to write scripts that do something only at system shutdown.
  • shutdown: This keyword is to be listed explicitly if the service needs to be stopped before system shutdown.

In the article about Django we can find an example of a real service such as Daphne.

If you liked the article, you can treat me to a RedBull here