2015年3月17日 星期二

Linux Daemon summary

Linux Daemon Writing HOWTO

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

#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>
int main(void) {
        
        /* Our process ID and Session ID */
        pid_t pid, sid;
        
        /* Fork off the parent process */
        pid = fork();
        if (pid < 0) {
                exit(EXIT_FAILURE);
        }
        /* If we got a good PID, then
           we can exit the parent process. */
        if (pid > 0) {
                exit(EXIT_SUCCESS);
        }

        /* Change the file mode mask */
        umask(0);
                
        /* Open any logs here */        
                
        /* Create a new SID for the child process */
        sid = setsid();
        if (sid < 0) {
                /* Log the failure */
                exit(EXIT_FAILURE);
        }
        

        
        /* Change the current working directory */
        if ((chdir("/")) < 0) {
                /* Log the failure */
                exit(EXIT_FAILURE);
        }
        
        /* Close out the standard file descriptors */
        close(STDIN_FILENO);
        close(STDOUT_FILENO);
        close(STDERR_FILENO);
        
        /* Daemon-specific initialization goes here */
        
        /* The Big Loop */
        while (1) {
           /* Do some task here ... */
           
           sleep(30); /* wait 30 seconds */
        }
   exit(EXIT_SUCCESS);
}
From here, you can use this skeleton to write your own daemons. Be sure to add in your own logging (or use the syslog facility), and code defensively, code defensively, code defensively!


#include 
#include 
#include 
#include 
#include 
#include 
int main(int argc, char* argv[])
{
FILE *fp= NULL;
pid_t process_id = 0;
pid_t sid = 0;
// Create child process
process_id = fork();
// Indication of fork() failure
if (process_id < 0)
{
printf("fork failed!\n");
// Return failure in exit status
exit(1);
}
// PARENT PROCESS. Need to kill it.
if (process_id > 0)
{
printf("process_id of child process %d \n", process_id);
// return success in exit status
exit(0);
}
//unmask the file mode
umask(0);
//set new session
sid = setsid();
if(sid < 0)
{
// Return failure
exit(1);
}
// Change the current working directory to root.
chdir("/");
// Close stdin. stdout and stderr
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
// Open a log file in write mode.
fp = fopen ("Log.txt", "w+");
while (1)
{
//Dont block context switches, let the process sleep for some time
sleep(1);
fprintf(fp, "Logging info...\n");
fflush(fp);
// Implement and call some function that does core work for this daemon.
}
fclose(fp);
return (0);
}
$ gcc -Wall deamon.c -o deamon
$ sudo ./deamon
process_id of child process 2936
$ tail -f /Log.txt
Logging info...
Logging info...
Logging info...
Logging info...
Logging info...
Logging info...
Logging info...
Logging info...
Logging info...





創建 Daemon 程式

http://felix-lin.com/linux/%E5%89%B5%E5%BB%BA-daemon-%E7%A8%8B%E5%BC%8F/


#include <syslog.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#define MAXFD   64
void
daemon_init(const char *pname, int facility)
{
    int     i;
    pid_t   pid;
    if ( (pid = fork()) != 0)
        exit(0);            /* parent terminates */
    /* 1st child continues */
    setsid();               /* become session leader */
    signal(SIGHUP, SIG_IGN);
    if ( (pid = fork()) != 0)
        exit(0);            /* 1st child terminates */
    /* 2nd child continues */
    chdir("/");             /* change working directory */
    umask(0);               /* clear our file mode creation mask */
    for (i=0; i
        close(i);
    openlog(pname, LOG_PID, facility);
}
int main()
{
    int ii = 10;
    daemon_init("TEST", 0);
    while(ii) {
        syslog(LOG_INFO, "daemon example ... %d", ii--);
        sleep(10);
    }
    exit(0);
}



/*
 * daemonize.c
 * This example daemonizes a process, writes a few log messages,
 * sleeps 20 seconds and terminates afterwards.
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <syslog.h>

static void skeleton_daemon()
{
    pid_t pid;

    /* Fork off the parent process */
    pid = fork();

    /* An error occurred */
    if (pid < 0)
        exit(EXIT_FAILURE);

    /* Success: Let the parent terminate */
    if (pid > 0)
        exit(EXIT_SUCCESS);

    /* On success: The child process becomes session leader */
    if (setsid() < 0)
        exit(EXIT_FAILURE);

    /* Catch, ignore and handle signals */
    //TODO: Implement a working signal handler */
    signal(SIGCHLD, SIG_IGN);
    signal(SIGHUP, SIG_IGN);

    /* Fork off for the second time*/
    pid = fork();

    /* An error occurred */
    if (pid < 0)
        exit(EXIT_FAILURE);

    /* Success: Let the parent terminate */
    if (pid > 0)
        exit(EXIT_SUCCESS);

    /* Set new file permissions */
    umask(0);

    /* Change the working directory to the root directory */
    /* or another appropriated directory */
    chdir("/");

    /* Close all open file descriptors */
    int x;
    for (x = sysconf(_SC_OPEN_MAX); x>0; x--)
    {
        close (x);
    }

    /* Open the log file */
    openlog ("firstdaemon", LOG_PID, LOG_DAEMON);
}

/* firstdaemon.c */
int main()
{
    skeleton_daemon();

    while (1)
    {
        //TODO: Insert daemon code here.
        syslog (LOG_NOTICE, "First daemon started.");
        sleep (20);
        break;
    }

    syslog (LOG_NOTICE, "First daemon terminated.");
    closelog();

    return EXIT_SUCCESS;
}
  • Compile the code: gcc -o firstdaemon daemonize.c
  • Start the daemon: ./firstdaemon
  • Check if everything is working properly: ps -xj | grep firstdaemon
  • The output should be similar to this one:
+------+------+------+------+-----+-------+------+------+------+-----+
| PPID | PID  | PGID | SID  | TTY | TPGID | STAT | UID  | TIME | CMD |
+------+------+------+------+-----+-------+------+------+------+-----+
|    1 | 3387 | 3386 | 3386 | ?   |    -1 | S    | 1000 | 0:00 | ./  |
+------+------+------+------+-----+-------+------+------+------+-----+
What you should see here is:
  • The daemon has no controlling terminal (TTY = ?)
  • The parent process ID (PPID) is 1 (The init process)
  • The PID != SID which means that our process is NOT the session leader (because of the second fork())
  • Because PID != SID our process can't take control of a TTY again
Reading the syslog:
  • Locate your syslog file. Mine is here: /var/log/syslog
  • Do a: grep firstdaemon /var/log/syslog
  • The output should be similar to this one:
  firstdaemon[3387]: First daemon started.
  firstdaemon[3387]: First daemon terminated.


daemon(3) - Linux man page

http://linux.die.net/man/3/daemon
#include <unistd.h>
int daemon(int nochdir, int noclose);
If nochdir is zero, daemon() changes the calling process's current working directory to the root directory  ("/"); otherwise, the current working directory is left unchanged.
If noclose is zero, daemon() redirects standard input, standard output and standard error to /dev/null; otherwise, no changes are made to these file descriptors.

example
Calling daemon() will detach your process from a controlling tty, close stdin/stdout, and will also fork & exit the parent so that your process becomes a child of init. For debugging, I added a -f option. If you specify -f, the program won't call daemon() so that you'll get your printfs. If you don't specify -f, the application will call daemon() and you won't see any more printfs.

#include 
#include 
#include 
#include 
#include 


int main(int argc, char** argv)
{
  bool run_in_foreground;
  int loop_count;
  int c;

  opterr = 0;

  while((c = getopt(argc, argv, "f")) != -1)
  {
    switch(c)
    {
    case 'f':
      run_in_foreground = true;
      break;

    case '?':
      printf("Unrecognized option '%c'.\n", optopt);
      return 1;

    default:
      abort();
    }
  }


  printf("This is my application...\n");

  if(!run_in_foreground)
  {
    printf("This is the last message you'll see, since I'm going to call daemon()\n");
    daemon(0,0);
  }
  else
  {
    printf("I'm in the foreground, so you'll still see my printfs\n");
  }


  for(loop_count = 0; loop_count < 10; loop_count++)
  {
    printf("Loop count is %d\n", loop_count);
    sleep(1);
  }

  return 0;
}

Upstart Intro, Cookbook and Best Practises
http://upstart.ubuntu.com/getting-started.html
http://upstart.ubuntu.com/cookbook/

How to correctly add a custom daemon to init.d?


Runit
http://smarden.org/runit/
http://smarden.org/runit/runsv.8.html

start-stop-daemon - start and stop system daemon programs

http://manpages.ubuntu.com/manpages/precise/man8/start-stop-daemon.8.html

systemd is a system and service manager for Linux
https://wiki.archlinux.org/index.php/systemd


Making scripts run at boot time with Debian

https://www.debian-administration.org/article/28/Making_scripts_run_at_boot_time_with_Debian

http://xmodulo.com/how-to-automatically-start-program-on-boot-in-debian.html

https://help.ubuntu.com/community/UbuntuBootupHowto

How to run a program when boot up?
http://en.kioskea.net/faq/3348-ubuntu-executing-a-script-at-startup-and-shutdown

To execute a script at startup of Ubuntu

  • Edit /etc/rc.local and add your commands
  • The script must always end with exit 0

To execute a script upon rebooting Ubuntu

  • Put your script in /etc/rc0.d
  • Make it executable (sudo chmod +x myscript)
  • Note: The scripts in this directory are executed in alphabetical order

The name of your script must begin with K99 to run at the right time. 

To execute a script at shutdown

  • Put your script in /etc/rc6.d
  • Make it executable (sudo chmod +x myscript)
  • Note: The scripts in this directory are executed in alphabetical order

The name of your script must begin with K99 to run at the right time




沒有留言:

張貼留言

追蹤者