我守护进程的代码是:
static int daemonize( const char *lockfile )
{
pid_t pid, sid, parent;
int lfp = -1;
char buf[16];
/* already a daemon */
if ( getppid() == 1 ) return 1;
/* Each copy of the daemon will try to
* create a file and write its process ID
* in it. This will allow administrators
* to identify the process easily
*/
/* Create the lock file as the current user */
if ( lockfile && lockfile[0] ) {
lfp = open(lockfile,O_RDWR|O_CREAT,LOCKMODE);
if ( lfp < 0 ) {
syslog( LOG_ERR, "unable to create lock file %s, code=%d (%s)",
lockfile, errno, strerror(errno) );
exit(EXIT_FAILURE);
}
}
/* If the file is already locked, then to ensure that
* only one copy of record is running. The filelock function will fail
* with errno set to EACCESS or EAGAIN.
*/
if (filelock(lfp) < 0) {
if (errno == EACCES || errno == EAGAIN) {
close(lfp);
//return(1);
exit(EXIT_FAILURE);
}
syslog(LOG_ERR, "can't lock %s: %s", lockfile, strerror(errno));
exit(EXIT_FAILURE);
}
ftruncate(lfp, 0);
sprintf(buf, "%ld", (long)getpid());
write(lfp, buf, strlen(buf)+1);
/* Drop user if there is one, and we were run as RUN_AS_USER */
if ( getuid() == 0 || geteuid() == 0 ) {
struct passwd *pw = getpwnam(RUN_AS_USER);
if ( pw ) {
syslog( LOG_NOTICE, "setting user to " RUN_AS_USER );
setuid( pw->pw_uid );
}
}
/* Trap signals that we expect to recieve */
signal(SIGCHLD,child_handler);
signal(SIGUSR1,child_handler);
signal(SIGALRM,child_handler);
/* Fork off the parent process */
pid = fork();
if (pid < 0) {
syslog( LOG_ERR, "unable to fork daemon, code=%d (%s)",
errno, strerror(errno) );
exit(EXIT_FAILURE);
}
/* If we got a good PID, then we can exit the parent process. */
if (pid > 0) {
/* Wait for confirmation from the child via SIGTERM or SIGCHLD, or
for two seconds to elapse (SIGALRM). pause() should not return. */
alarm(2);
pause();
exit(EXIT_FAILURE);
}
/* At this point we are executing as the child process */
parent = getppid();
/* Cancel certain signals */
signal(SIGCHLD,SIG_DFL); /* A child process dies */
signal(SIGTSTP,SIG_IGN); /* Various TTY signals */
signal(SIGTTOU,SIG_IGN);
signal(SIGTTIN,SIG_IGN);
signal(SIGHUP, SIG_IGN); /* Ignore hangup signal */
signal(SIGTERM,SIG_DFL); /* Die on SIGTERM */
/* Change the file mode mask */
umask(0);
/* Create a new SID for the child process */
sid = setsid();
if (sid < 0) {
syslog( LOG_ERR, "unable to create a new session, code %d (%s)",
errno, strerror(errno) );
exit(EXIT_FAILURE);
}
/* Change the current working directory. This prevents the current
directory from being locked; hence not being able to remove it. */
if ((chdir("/")) < 0) {
syslog( LOG_ERR, "unable to change directory to %s, code %d (%s)",
"/", errno, strerror(errno) );
exit(EXIT_FAILURE);
}
/* Redirect standard files to /dev/null */
freopen( "/dev/null", "r", stdin);
freopen( "/dev/null", "w", stdout);
freopen( "/dev/null", "w", stderr);
/* Tell the parent process that we are A-okay */
kill( parent, SIGUSR1 );
return 0;
}
我想在我开始使用时只运行一个程序实例:
service [script] start
但是,只要此命令执行两次或更多次,它就会在运行条件中创建相同数量的守护程序进程。我想摆脱这种行为。任何建议都将受到高度赞赏。
答案 0 :(得分:2)
不要使用文件锁;相反,使用O_EXCL
标记open()
,如果文件已存在,则会EEXIST
失败。这通常是使用pid文件完成的,因为它无论如何都需要是独占的。
答案 1 :(得分:0)
pid文件的另一种替代方法是从守护程序打开tcp / udp端口。尝试打开同一端口时,运行守护程序的另一个实例将失败。