Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling a sd_notify(0, "WATCHDOG=1") in a service

I have a sys d service. I want to implement a watch dog for that. It's something like,

[Unit]
Description=Watchdog example service

[Service]
Type=notify
Environment=NOTIFY_SOCKET=/run/%p.sock
ExecStartPre=-/usr/bin/docker kill %p
ExecStartPre=-/usr/bin/docker rm %p
ExecStart=/usr/libexec/sdnotify-proxy /run/%p.sock /usr/bin/docker run \
    --env=NOTIFY_SOCKET=/run/%p.sock \
    --name %p pranav93/test_watchdogged python hello.py
ExecStop=/usr/bin/docker stop %p

Restart=on-success
WatchdogSec=30s
RestartSec=30s


[Install]
WantedBy=multi-user.target

According to docs I've to call sd_notify("watchdog=1") every half of the interval specified (In this case it's 15s). But I've no idea how to call that function in a service. Help would be highly appreciated.

like image 938
pnv Avatar asked Oct 05 '15 11:10

pnv


People also ask

What is Sd_notify?

Description. sd_notify() may be called by a service to notify the service manager about state changes. It can be used to send arbitrary information, encoded in an environment-block-like string. Most importantly, it can be used for start-up completion notification.

What is Type notify in systemd?

Description. systemd-notify may be called by daemon scripts to notify the init system about status changes. It can be used to send arbitrary information, encoded in an environment-block-like list of strings. Most importantly, it can be used for start-up completion notification.


2 Answers

I had to install systemd lib:

sudo apt-get install libsystemd-dev

And compile the program passing it to linker:

gcc testWatchDogProcess.c -o testWatchDogProcess -lsystemd

I´ve made some changes in @rameshrgtvl code to make it run directly without any warning or errors.

#include <systemd/sd-daemon.h>
#include <fcntl.h>
#include <time.h>
/* This should be sent once you are done with your initialization */
/* Until you call this systemd will keep your service as activating status */
/* Once you called, systemd will change the status of ur service to active */

#define true  1

int main ()
{
        sd_notify (0, "READY=1");

        /* Way to get the WatchdogSec value from service file */
        char * env;
        int interval=0;
        int isRun = true;
        env = getenv("WATCHDOG_USEC");
        if (env)
        {
                interval = atoi(env)/(2*1000000);
        }
        /* Ping systsemd once you are done with Init */
        sd_notify (0, "WATCHDOG=1");

        /* Now go for periodic notification */
        while(isRun == true)
        {
                sleep(interval);
            /* Way to ping systemd */
                sd_notify (0, "WATCHDOG=1");
        }
        return 0;
}
like image 192
fabatera Avatar answered Sep 23 '22 13:09

fabatera


Sample Service File

[Unit]
Description=Test watchdog Demo process
DefaultDependencies=false
Requires=basic.target

[Service]
Type=notify
WatchdogSec=10s
ExecStart=/usr/bin/TestWatchDogProcess
StartLimitInterval=5min
StartLimitBurst=5
StartLimitAction=reboot
Restart=always

Sample Code For testWatchDogProcess.c:

#include "systemd/sd-daemon.h"
#include <fcntl.h>
#include <time.h>

/* This should be sent once you are done with your initialization */
/* Until you call this systemd will keep your service as activating status */
/* Once you called, systemd will change the status of ur service to active */

sd_notify (0, "READY=1");

/* Way to get the WatchdogSec value from service file */
env = getenv("WATCHDOG_USEC");
if(env != NULL)
int interval = atoi(env)/(2*1000000);

/* Ping systsemd once you are done with Init */
sd_notify (0, "WATCHDOG=1");

/* Now go for periodic notification */
while(isRun == true)
{
    sleep(interval);
    /* Way to ping systemd */
    sd_notify (0, "WATCHDOG=1");
}

    return 0;

}

Note: Based on your systemd version please take care to include proper header and library during compilation.

like image 30
rameshrgtvl Avatar answered Sep 24 '22 13:09

rameshrgtvl