[お勉強] daemonを作る
こういうことは,モチベーションがあるときにやってしまおう.
しかし,プロセス生成しかり,プログラミングの知識がないなぁ・・と嘆く.
まぁ,嘆いているヒマがあれば,コード書けと言われそうだが.あぁ,書くよ.
んで,プロセス生成をやっているうちに,daemonも作れそうだなぁと思っていたらすごいわかりやすいページがあった.
んで,これマンマコピって,実行してみた.
参考リンク:http://www.enderunix.org/documents/eng/daemon.php
/* Original source code, here. http://www.enderunix.org/documents/eng/daemon.php UNIX Daemon Server Programming Sample Program Levent Karakas <levent at mektup dot at> May 2001 */ #include <stdio.h> #include <fcntl.h> #include <signal.h> #include <unistd.h> #include <string.h> #include <stdlib.h> // invariables #define RUNNING_DIR "/tmp" #define LOCK_FILE "daemond.lock" #define LOG_FILE "daemond.log" #define PID_BUFFER_SIZE 10 void log_output( char *filename, char *message ) { FILE *logfile = fopen( filename, "a" ); if( !logfile ) return; fprintf( logfile, "%s\n", message ); fclose( logfile ); } void signal_handler( int sig ) { switch( sig ){ case SIGHUP: log_output( LOG_FILE, "hangup signal catched" ); break; case SIGTERM: log_output( LOG_FILE, "terminate signal catched" ); exit(0); break; } } void daemonize() { int i,lfp; char str[PID_BUFFER_SIZE]; if( getppid() == 1 ) { log_output( LOG_FILE, "already a daemon" ); return; } i = fork(); if( i < 0 ){ log_output( LOG_FILE, "fork error" ); exit(1); } if( i > 0 ) // this is a parent process, will exit exit(0); setsid(); // new process group setup for( i = getdtablesize(); i >= 0; --i ) close(i); i = open( "/dev/null", O_RDWR ); dup( i ); dup( i ); // set newly created file permissions umask( 027 ); chdir( RUNNING_DIR ); // open lock file lfp = open( LOCK_FILE, O_RDWR | O_CREAT, 0640 ); if( lfp < 0 ) { log_output( LOG_FILE, "can not open" ); exit(1); } if( lockf( lfp, F_TLOCK, 0 ) < 0 ) { log_output( LOG_FILE, "can not lock" ); exit(0); } // record pid to lockfile sprintf( str, "%d\n", getpid() ); write( lfp, str, strlen(str) ); // signal( SIGCHLD, SIG_IGN ); signal( SIGTSTP, SIG_IGN ); signal( SIGTTOU, SIG_IGN ); signal( SIGTTIN, SIG_IGN ); // signal handler setup signal( SIGHUP, signal_handler); signal( SIGTERM, signal_handler); } int main( int argc, void** argv ){ daemonize(); while(1) sleep(1); }
な,長い.
今までのと違って,setsidのと,openの当たりが違う感じ.
後,プロセス経由で再起動とか,停止に対応するためにsignal_handlerを実装するところが違うか.
色々調べてみると,カレントディレクトリを変更するのが行儀がいいとか,色々お作法があるらしい.
だよね,デーモンだからダイレクトにセキュリティに悪影響を及ぼしそうだ.
これでgccで生成したバイナリは,以下のような感じで起動,停止などなどができる.
これも元サイト引用だけど.
./exampled・・・実行 kill -HUP `cat /tmp/exampled.lock`・・・終了して,再起動 kill `cat /tmp/exampled.lock`・・・終了
なんかサーバっぽいもの作ってみるか.あんま意味ないけど.