2017-02-20 5 views
1

Мне нужно запустить скрипт Perl в качестве службы (например, daemon). Я нашел программу C ниже и вообще работает нормально. Однако, если скрипты perl умирают с исключением, я не получаю никакого сообщения об ошибке. Как я могу получить ошибку от perl?Перенаправить STDERR из службы в syslog

Терминал (т. Е. STDERR) недоступен, я предполагаю, что наилучшей идеей было бы получить сообщения об ошибках в syslog.

#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> 
#include <signal.h> 
#include <syslog.h> 


int main(int argc, char *argv[]) {  
    pid_t pid, sid;  

    if(argc < 1) { 
     printf("At least one argument expected.\n"); 
     return EXIT_FAILURE; 
    } 

    char arg[1000]; 
    strcpy(arg, argv[1]); 
    int i = 2; 
    for(i = 2; i < argc; i++) { 
     strcat(arg, " "); 
     strcat(arg, argv[i]);  
    } 

    /* 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); 
    } 

    /* Open a connection to the syslog server */ 
    openlog ("mediationd", LOG_PID, LOG_DAEMON); 
    syslog(LOG_NOTICE, "Successfully started daemon\n"); 

    /* Try to create our own process group */ 
    sid = setsid(); 
    if (sid < 0) { 
     syslog(LOG_ERR, "Could not create process group\n"); 
     closelog(); 
     exit(EXIT_FAILURE); 
    } 

    /* Catch, ignore and handle signals */ 
    signal(SIGCHLD, SIG_IGN); 
    signal(SIGHUP, SIG_IGN); 

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

    /* An error occurred */ 
    if (pid < 0) { 
     syslog(LOG_ERR, "Could not fork second time\n"); 
     closelog(); 
     exit(EXIT_FAILURE); 
    } 

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

    /* Change the file mode mask */ 
    umask(0);  

    /* Change the current working directory */ 
    if ((chdir("/")) < 0) { 
     syslog(LOG_ERR, "Could not change working directory to /\n"); 
     exit(EXIT_FAILURE); 
    } 

    /* Close the standard file descriptors */ 
    close(STDIN_FILENO); 
    close(STDOUT_FILENO); 
    close(STDERR_FILENO); 

    /* Starting the perl script which does the job. 
    * Note, this perl scripts runs forever till it is terminated by 'kill' command */ 
    system(arg); 

    /* Terminate the daemon */ 
    syslog (LOG_NOTICE, "Daemon terminated."); 
    closelog(); 
    return EXIT_SUCCESS; 
} 

Я написал эту крошечную программу простым копировать/вставить, так как у меня нет понятия о С. Не было бы хорошо, если кто-то может предоставить некоторые «готовые к использованию» код.

Update

Я обновил свой код, как показано ниже. Кажется, что он работает хорошо, но я ничего не пропускаю или должен добавить что-то еще?

/* Close the standard file descriptors */ 
close(STDIN_FILENO); 
close(STDOUT_FILENO); 

/* Redirect STDERR to syslog, i.e. logger */ 
FILE *fl; 
fl = popen("logger --id --priority user.error", "w"); 
if (fl == NULL) { 
    syslog(LOG_ERR, "Could not open 'looger'\n"); 
    exit(EXIT_FAILURE); 
} 
int nf = fileno(fl); 
dup2(nf, STDERR_FILENO); 

/* Starting the perl script which does the job. 
* Note, this perl scripts runs forever till it is terminated by 'kill' command */ 
system(arg); 
close(STDERR_FILENO); 

/* Terminate the daemon */ 
syslog (LOG_NOTICE, "Daemon terminated\n"); 
closelog(); 
return EXIT_SUCCESS; 
+0

Возможный дубликат [In C как вы перенаправляете stdin/stdout/stderr в файлы при выполнении execvp() или аналогичного вызова?] (Http://stackoverflow.com/questions/14543443/in-c-how- do-you-redirect-stdin-stdout-stderr-to-files-when-making-an-execvp-or) – Toby

+0

@Toby Это не очень хороший дубликат. Вход в систему syslog не предусматривает прямой записи в файл. – Kenster

+0

С 12k повторениями вы должны знать, что мы не являемся кодовым сервисом. И почему этот помеченный perl ** и ** C? Если вы намереваетесь написать Perl-версию, C бесполезен, если вы хотите, чтобы C-код был исправлен, почему даже упоминать Perl? – Olaf

ответ

1

Если вы хотите сделать это на родном языке Perl, это работает для меня:

use IO::Handle; 
open(SYSLOG, "| /usr/bin/logger -t hello") or die("syslog problem $!"); 
*STDERR = *SYSLOG; 
autoflush STDERR 1; 

Если Perl падает с die() или подобное, вы увидите лог сообщений.

Смежные вопросы