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:
#include <stdio.h>
#include <unistd.h>
int main(){
while(1) {
sleep(1);
}
}
We compile the software:
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:
#!/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:
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:
kr0mUtility_enable="yes"
We check the status of the service:
kr0mUtility is not running.
We start it:
starting kr0mUtility.
We check the service again:
kr0mUtility is running as pid 98683.
We can see the daemon process that has started our utility:
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:
Stopping kr0mUtility.
Waiting for PIDS: 98683.
We check the status:
kr0mUtility is not running.
We check that the utility process and daemon no longer exist:
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 /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.