Sunday, June 20, 2010

Create daemon process in C

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
#include <string.h>

#define LOCKFILE "/var/lock/PROCESSNAME"

#ifdef CREATE_PID_FILE
#define PIDFILE "/var/run/PROCESSNAME.pid"
#endif

void deamon (void)
{
  pid_t pid, sid;
#ifdef CREATE_PID_FILE
  pid_t child;
  FILE *pidfp = NULL;
#endif  
  int lockfd = -1;

  /* Create the lock file */
  lockfd = open (LOCKFILE, O_RDWR | O_CREAT | O_EXCL, 0640);
  if (-1 == lockfd)
  {
    syslog (LOG_ERR, "ERROR: Unable to create lock file [" LOCKFILE "] -> %s.", strerror(errno));
    if (EEXIST == errno)
    {
      syslog (LOG_ERR, "ERROR: Another instance of this process might be already running. "
              "Please kill that process or delete the lock file and try again.");
      exit (EXIT_FAILURE);
    }
  }
  
  /* Fork the child */
  pid = fork();
  if (-1 == pid)
  {
    syslog (LOG_ERR, "ERROR: Unable to fork the child process -> %s.", strerror(errno));

    /* On failure, delete the lock file */
    if (-1 == unlink (LOCKFILE))
    {
      syslog (LOG_ERR, "ERROR: Unable to delete the lock file [" LOCKFILE "] -> %s.", strerror(errno));
    }

    exit (EXIT_FAILURE);
  }

  /* Exit from the parent */
  if (0 != pid)
  {
    exit (EXIT_SUCCESS);
  }

#ifdef CREATE_PID_FILE
  child = getpid();

  pidfp = fopen (PIDFILE, "w");
  if (NULL == pidfp)
  {
    syslog (LOG_ERR, "ERROR: Unable to open the pid file [" PIDFILE "] -> %s", strerror(errno));
    
    /* On failure, delete the lock file */
    if (-1 == unlink (LOCKFILE))
    {
      syslog (LOG_ERR, "ERROR: Unable to delete the lock file [" LOCKFILE "] -> %s.", strerror(errno));
    }

    exit (EXIT_FAILURE);
  }

  fprintf (pidfp, "%d\n", child);
  fclose (pidfp);
#endif

  /* Make the child as the leader of the process */
  sid = setsid ();
  if ((pid_t)-1 == sid)
  {
    syslog (LOG_ERR, "ERROR: Unable to create new seesion -> %s", strerror(errno));

    /* On failure, delete the lock file and pid file */
    if (-1 == unlink (LOCKFILE))
    {
      syslog (LOG_ERR, "ERROR: Unable to delete the lock file [" LOCKFILE "] -> %s.", strerror(errno));
    }

#ifdef CREATE_PID_FILE
    if (-1 == unlink (PIDFILE))
    {
      syslog (LOG_ERR, "ERROR: Unable to delete the lock file [" PIDFILE "] -> %s.", strerror(errno));
    }
#endif

    exit (EXIT_FAILURE);
  }

  /* Set the calling process's file mode creation mask */
  umask (0);

  /*
   * Changing working directory to '/' to make sure that
   * the process does not depend on any mounted partition
   * execpt the root of the filesystem
   */
  if(-1 == chdir ("/"))
  {
    syslog (LOG_ERR, "ERROR: Unable to change the directory to \"/\" -> %s", strerror(errno));

    /* On failure, delete the lock file and pid file */
    if (-1 == unlink (LOCKFILE))
    {
      syslog (LOG_ERR, "ERROR: Unable to delete the lock file [" LOCKFILE "] -> %s.", strerror(errno));
    }

#ifdef CREATE_PID_FILE
    if (-1 == unlink (PIDFILE))
    {
      syslog (LOG_ERR, "ERROR: Unable to delete the lock file [" PIDFILE "] -> %s.", strerror(errno));
    }
#endif

    exit (EXIT_FAILURE);
  }

  /* Close standard input file descriptor */
  close (0);

  /* Redirect standard output and errror to /dev/null */
  freopen ( "/dev/null", "w", stdout);
  freopen ( "/dev/null", "w", stderr);

}

Reference: http://www.netzmafia.de/skripten/unix/linux-daemon-howto.html

Saturday, June 19, 2010

Create daemon process in Python

#!/usr/bin/env python
# Filename: daemon.py

# Make the process to run in the background.

__author__ = "Karthikeyan Periasamy"
__version__ = "0.1"
__all__ = ["daemonize"]

# Standard modules
import os               # OS interface functions.
import sys              # System specific functions.
from syslog import *    # Logging functions.

# Daemon parameters
UMASK = 0       # File mode creation mask for the calling process 
WORKDIR = "/"   # The Working directory

# Find the null device /dev/null
if (hasattr(os, "devnull")):
    NULL_DEVICE = os.devnull
else:
    NULL_DEVICE = "/dev/null"
    
# Function
def daemonize (procname):
    openlog (procname, LOG_PID)
    
    try:
        # Fork the child
        syslog (LOG_INFO, "Daemizing")
        syslog (LOG_INFO, "Creating the first child")
        pid = os.fork ()
        
        # Exit from the parent
        if 0 != pid:
            syslog (LOG_INFO, "Parent exiting")
            os._exit (0)

        # Make the child as the leader of the process
        syslog (LOG_INFO, "Child created")
        syslog (LOG_INFO, "Creating a new session")
        os.setsid ()

        # Fork a child again to make sure that no terminal device is connected to it.
        syslog (LOG_INFO, "Creating the second child")
        pid = os.fork ()

        # Exit from the first child
        if 0 != pid:
            syslog (LOG_INFO, "First child exiting")
            os._exit (0)

        # Set the calling process's file mode creation mask
        syslog (LOG_INFO, "Set the calling process's file mode creation mask")
        os.umask (UMASK)

        # Changing working directory to '/' to make sure that
        # the process does not depend on any mounted partition
        # execpt the root of the filesystem
        logmsg = 'Changing working directory to "' + WORKDIR + '" to avoid dependencies'
        syslog (LOG_INFO, logmsg)
        os.chdir (WORKDIR)

        # Close standard input, output and error file descriptors
        syslog (LOG_INFO, "Closing I/O file descriptors")
        os.close (0)
        os.close (1)
        os.close (2)

        # Redirect standard output and errror to /dev/null
        os.open(NULL_DEVICE, os.O_RDWR)
        os.dup2(0, 1)
        os.dup2(0, 2)

    except:
        logmsg = "Unexpected error:" + repr (sys.exc_info()[1])
        syslog (LOG_ERR, logmsg)
        os._exit (1)


# ---------------------------------------------------------------------------
# Main program (for testing)
# ---------------------------------------------------------------------------

if __name__ == '__main__':

    daemonize("daemon_test")
    syslog(LOG_INFO, 'Daemon is sleeping for 10 seconds')

    import time
    for i in range (10):
        syslog(LOG_INFO, 'Sleeping...')
        time.sleep(1)

    syslog(LOG_INFO, 'Daemon exiting')
    sys.exit(0)

Reference: http://code.activestate.com/recipes/278731-creating-a-daemon-the-python-way/