Again and again

When you have worked with Solaris 11 or 10 you have surely used SMF and loved it to a varying degree. Since 11.3 there is something new in it: SMF knows now a concept called “periodic and scheduled services”.

What is special about those new kinds of services? Well quite simple.Periodic services are services that are running from the start of the service until the system stops every soandso seconds. For example run the method defined in service periodic/dbcheck every 60 seconds.Scheduled services are running from the start of the service until the system stops in the configured schedule. For example run the method defined in service scheduled/dbbackup daily at 01:00 am.

Sounds familiar. Well, yeah. You can think about it as a cron on steroids. But there are some reasons why this is better than just cron.

You can use all advantages of SMF for example like the simple delegation of administrative tasks to other users. You can the pkg format to simply add an action to a package that add such an service.

For me even more important is that periodic services knows the concept of jitter. This is quite useful: Simple cron has a slight disadvantage. Imagine you have for example several zones zones with a process scheduled to start at 01:00. In this case cron will start them at the same time.

You get a formidable thundering herd of processes. Despite the fact that system are quite powerful today, wouldn’t it be nice that not all processes start at the same time but at point in time with a slight difference. The mentioned parameter jitter enables such a slight difference. On the other side there is a parameter called delay that configures what the delay of the start after the service got into the online state.

Another interesting capability is the ability to set a parameter called recover. In case your system was down for a while and server method should have run during the downtime, the service will be started during startup in case this parameter is set to true.

Preparations

In order to demonstrate this i have to prepare a few things first. We need a method-script. I will just use a short script that is doing nothing except saying that it does nothing.

root@nfsclient:~# cat <<EOT > /root/scripts/db_check.sh
#!/bin/bash
echo "do nothing"
EOT
root@nfsclient:~# chmod +x /root/scripts/db_check.sh
root@nfsclient:~# /root/scripts/db_check.sh 
do nothing
root@nfsclient:~# cp /root/scripts/db_check.sh /root/scripts/db_backup.sh

We will use this script later on in the examples.

Periodic services

Okay, lets try a periodic service at first. Create a XML manifest for it.

cat <<EOT > periodic.xml
<?xml version='1.0'?>
<!DOCTYPE service_bundle
 SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>
<service_bundle type='manifest' name='periodic/checkdb'>
<service type='service' version='1' name='periodic/checkdb'>
<instance name='default' enabled='false'>
<periodic_method 
 period='60'
 delay='5' 
 jitter='5'
 exec='/root/scripts/db_check.sh' timeout_seconds='0'>
<method_context>
 <method_credential user='root' group='root'/>
</method_context>
</periodic_method>
</instance>
<template>
<common_name><loctext xml:lang="C">Sample Periodic
Service</loctext></common_name>
<description><loctext xml:lang="C">What this service does
periodically.</loctext></description>
</template>
</service>
</service_bundle>
EOT

Based on this manifest file the script runs every 60 to 65 seconds and the first time after 5 seconds after the service got online :-) To install this service, i will use the manifest-import.

root@nfsclient:~# cp periodic.xml /lib/svc/manifest/site/
root@nfsclient:~# svcadm restart manifest-import

Due to the enabled='false' in the manifest it’s initially disabled.

root@nfsclient:~# svcs periodic/checkdb
STATE          STIME    FMRI
disabled       12:21:51 svc:/periodic/checkdb:default

So we enable the service no

root@nfsclient:~# svcadm enable periodic/checkdb
root@nfsclient:~# svcs periodic/checkdb
STATE          STIME    FMRI
online         12:22:37 svc:/periodic/checkdb:default

Okay, the periodic services know two parameters. NRUN and LRUN. NRUN tells you when the service will run the next time. LRUN tells you when the service did run the last time.

root@nfsclient:~# svcs -o LRUN periodic/checkdb
LRUN
12:22:46
root@nfsclient:~# svcs -o NRUN periodic/checkdb
NRUN
12:23:42
root@nfsclient:~# svcs -o LRUN periodic/checkdb
LRUN
12:22:46
root@nfsclient:~# svcs -o LRUN periodic/checkdb
LRUN
12:23:42
root@nfsclient:~# svcs -o NRUN periodic/checkdb
NRUN
12:24:43

As you see the service is not running in perfect 60 interfaces but in the configured interval with some jitter in it.

Scheduled services

Okay, now lets do the same for a scheduled service.

cat <<EOT > scheduled.xml
<?xml version='1.0'?>
<!DOCTYPE service_bundle
 SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>
<service_bundle type='manifest' name='scheduled/backupdb'>
<service type='service' version='1' name='scheduled/backupdb'>
<instance name='default' enabled='false'>
<scheduled_method
    interval='day'
    hour='12'
    minute='40'
    exec='/root/scripts/db_backup.sh'
    timeout_seconds='0'>
    <method_context>
        <method_credential user='root' group='root' />
    </method_context>
</scheduled_method>
</instance>
<template>
<common_name><loctext xml:lang="C">Sample Scheduled
Service</loctext></common_name>
<description><loctext xml:lang="C">What this service does
on the configured schedule</loctext></description>
</template>
</service>
</service_bundle>
EOT

Now we have to install and enable this service as well.

root@nfsclient:~# cp scheduled.xml /lib/svc/manifest/site/
root@nfsclient:~# svcadm restart manifest-import
root@nfsclient:~# svcs  scheduled/backupdb
STATE          STIME    FMRI
disabled       12:35:40 svc:/scheduled/backupdb:default
root@nfsclient:~# svcadm enable svc:/scheduled/backupdb:default

When we look at the NRUN value, we will see that this service will run 12:40:44 (in reality it was around 8 o’clock in the evening … this happens without resetting the time in a Virtualbox)

root@nfsclient:~# svcs -o NRUN scheduled/backupdb 
NRUN
12:40:44

As we have just created this schedules service, obviously there is no last run-date so far.

root@nfsclient:~# date; svcs -o LRUN scheduled/backupdb 
Thu May  4 12:40:19 UTC 2017
LRUN
-

However when we wait until the configured time and ask for the last run timestamp, we will see a value here.

root@nfsclient:~# date; svcs -o LRUN scheduled/backupdb 
Thu May  4 12:41:19 UTC 2017
LRUN
12:40:44

As indicated by the NRUN value, the service ran at 12:40:44 and so is now the the LRUN value.

List of scheduled services

It’s quite easy to find out, which scheduled services are active in the system.

root@nfsclient:~# svcs -o NRUN,LRUN,ASTATE,fmri | grep "scheduled"
12:47:45 12:46:45 scheduled                                           svc:/periodic/checkdb:default
12:40:44 12:40:44 scheduled                                           svc:/scheduled/backupdb:default

An alternative way to do so, would be checking which services are dependend to the restarter svc:/system/svc/periodic-restarter:default. This is the delegated restarter used to do the scheduled and periodic restart.

root@nfsclient:~# svcs -o fmri,lrun,nrun -R svc:/system/svc/periodic-restarter:default
FMRI                                               LRUN     NRUN
svc:/application/security/compliance:default       -        -
svc:/periodic/checkdb:default                      17:32:23 17:33:26
svc:/scheduled/backupdb:default                    12:40:44 12:40:44