Поэтому я пишу программу, которая будет работать как фоновый процесс в системе Linux, и я создавал функцию демона, чтобы начать процесс в фоновом режиме. Мне нужно знать, должен ли я объявлять объект внутри основного класса для запуска функции daemonize, или должен ли я сделать daemonize funciton, и это две вспомогательные функции static. Код ниже, есть ли лучший способ сделать это или один из способов более предпочтительный, чем другой? Благодарю.
#include "../Headers/LogMonitor.h"
#define RUNNING_DIR "/tmp"
#define LOCK_FILE "exampled.lock"
#define LOG_FILE "exampled.log"
LogMonitor::LogMonitor() {
// TODO Auto-generated constructor stub
}
LogMonitor::~LogMonitor() {
// TODO Auto-generated destructor stub
}
int main( int argc, const char* argv[] )
{
// Daemonize the program to run in the background
LogMonitor::daemonize();
}
void LogMonitor::signal_handler(int sig)
{
switch(sig) {
case SIGHUP:
log_message(LOG_FILE,"hangup signal caught");
break;
case SIGTERM:
log_message(LOG_FILE,"terminate signal caught");
exit(0);
break;
}
}
void LogMonitor::log_message(const char *filename, const char *message)
{
FILE *logfile;
logfile=fopen(filename,"a");
if(!logfile) return;
fprintf(logfile,"%s\n",message);
fclose(logfile);
}
void LogMonitor::daemonize()
{
int i,lfp;
char str[10];
if(getppid()==1) return; // Check if already a daemon
i = fork();
if (i < 0) exit(1); // Fork error
if (i > 0) exit(0); // Parent exits
setsid(); // Obtain a new process group
for (i = getdtablesize(); i >= 0; --i) close(i); // Close all descriptors
i = open("/dev/null",O_RDWR); // stdin
dup(i); // stdout
dup(i); // stderr
umask(027); // Set newly created file permissions
chdir(RUNNING_DIR); // Change running directory
lfp = open("exampled.lock",O_RDWR|O_CREAT,0640);
if (lfp < 0) exit(1); // Can't open
if (lockf(lfp,F_TLOCK,0) < 0) exit(0); // Can't lock
sprintf(str,"%d\n", getpid());
write(lfp,str,strlen(str)); // Record pid to lockfile
signal(SIGCHLD,SIG_IGN); // Ignore child
signal(SIGTSTP,SIG_IGN); // Ignore tty signals
signal(SIGTTOU,SIG_IGN);
signal(SIGTTIN,SIG_IGN);
signal(SIGHUP, LogMonitor::signal_handler); // Catch hangup signal
signal(SIGTERM, LogMonitor::signal_handler); // Catch kill signal
}
Современные демоны не должны основываться на себе. Вместо этого просто запустите его на переднем плане и позвольте вызывающему абоненту (то есть сценарию под именем /etc/init.d
) выбрать его демонизацию - обычно используется start-stop-daemon(8)
, хотя systemd
может сделать это самостоятельно,
/etc/init.d
(проверка файлов PID или что у вас есть). Процесс должен быть демоном, а не менеджером демона; у нас есть дюжина инструментов для этого, и нет никаких причин, по которым ваша служба заставляла меня писать еще один пользовательский класс Puppet. Чем менее вы умны, тем более вероятно, что это сработает, а это очень просто.