【问题标题】:Redirect STDERR from service to syslog将 STDERR 从服务重定向到 syslog
【发布时间】:2017-07-09 17:54:38
【问题描述】:

我必须将 Perl 脚本作为服务(即守护程序)运行。我在下面找到了 C 程序,总的来说它工作正常。但是,如果 perl 脚本因异常而死掉,我不会收到任何错误消息。如何从 perl 中获取错误?

终端(即 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;
}

我通过简单的复制/粘贴来编写这个小程序,因为我不知道 C。如果有人能提供一些“准备使用”的代码,那就太好了。

更新

我更新了我的代码,如下所示。它似乎运行良好,但是我错过了什么还是应该添加其他内容?

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

【问题讨论】:

  • @Toby 这不是一个很好的副本。通过 syslog 记录不涉及直接写入文件。
  • 拥有 12k 代表,您应该知道我们不是编码服务。为什么这被标记为 perl and C?如果你打算写一个 Perl 版本,C 没用,如果你想修复 C 代码,为什么还要提到 Perl?
  • 我删除了perl标签,事实上哪个程序写入STDERR并不重要。

标签: c unix daemon syslog


【解决方案1】:

如果你想用原生 Perl 来做,这对我有用:

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

如果 Perl 以 die() 或类似名称崩溃,您将看到日志消息。

【讨论】:

  • 我很不情愿地接受你的回答。我会更喜欢 Tie::Syslog 之类的东西,但我的代码将大胆地运行在以前没有运行过自定义 perl 脚本的地方,而且显然 Tie::Syslog 并没有那么普遍安装。
猜你喜欢
  • 2021-01-13
  • 2014-07-22
  • 1970-01-01
  • 2022-01-18
  • 2013-08-05
  • 1970-01-01
  • 1970-01-01
  • 2017-07-21
  • 2012-08-07
相关资源
最近更新 更多