wazuh-logcollector 日志采集进程

367 阅读1分钟

logcollector进程主函数

int main(int argc, char **argv)
{
    int c;
    int debug_level = 0;
    int test_config = 0, run_foreground = 0;
 
    /* Set the name */
    OS_SetName(ARGV0);
 
    // Define current working directory
    char * home_path = w_homedir(argv[0]);
    if (chdir(home_path) == -1) {
        merror_exit(CHDIR_ERROR, home_path, errno, strerror(errno));
    }
 
    const char *cfg = OSSECCONF;
    gid_t gid;
    const char *group = GROUPGLOBAL;
    lc_debug_level = getDefine_Int("logcollector", "debug", 0, 2);
 
    /* Setup random */
    srandom_init();
 
    ...
 
 
    /* Check if the group given is valid */
    gid = Privsep_GetGroup(group);
    if (gid == (gid_t) - 1) {
        merror_exit(USER_ERROR, "", group, strerror(errno), errno);
    }
 
    /* Privilege separation */
    if (Privsep_SetGroup(gid) < 0) {
        merror_exit(SETGID_ERROR, group, errno, strerror(errno));
    }
 
    /* Check current debug_level
     * Command line setting takes precedence
     */
    if (debug_level == 0) {
        /* Get debug level */
        debug_level = lc_debug_level;
        while (debug_level != 0) {
            nowDebug();
            debug_level--;
        }
    }
 
    mdebug1(WAZUH_HOMEDIR, home_path);
    os_free(home_path);
 
    /* Init message queue */
    w_msg_hash_queues_init();
 
    /* Read config file */
    if (LogCollectorConfig(cfg) < 0) {
        merror_exit(CONFIG_ERROR, cfg);
    }
 
    /* Exit if test config */
    if (test_config) {
        exit(0);
    }
 
    /* No file available to monitor -- continue */
    if (logff == NULL) {
        os_calloc(2, sizeof(logreader), logff);
        logff[0].file = NULL;
        logff[0].ffile = NULL;
        logff[0].logformat = NULL;
        logff[0].fp = NULL;
        logff[1].file = NULL;
        logff[1].logformat = NULL;
 
        minfo(NO_FILE);
    }
 
    /* No sockets defined */
    if (logsk == NULL) {
        os_calloc(2, sizeof(logsocket), logsk);
        logsk[0].name = NULL;
        logsk[0].location = NULL;
        logsk[0].mode = 0;
        logsk[0].prefix = NULL;
        logsk[1].name = NULL;
        logsk[1].location = NULL;
        logsk[1].mode = 0;
        logsk[1].prefix = NULL;
    }
 
    /* Start signal handler */
    StartSIG(ARGV0);
 
    // Set max open files limit
    struct rlimit rlimit = { nofile, nofile };
 
    if (setrlimit(RLIMIT_NOFILE, &rlimit) < 0) {
        merror("Could not set resource limit for file descriptors to %d: %s (%d)", (int)nofile, strerror(errno), errno);
    }
 
    if (!run_foreground) {
        /* Going on daemon mode */
        nowDaemon();
        goDaemon();
    }
 
    /* Create PID file */
    if (CreatePID(ARGV0, getpid()) < 0) {
        merror_exit(PID_ERROR);
    }
 
    /* Start the queue */
    if ((logr_queue = StartMQ(DEFAULTQUEUE, WRITE, INFINITE_OPENQ_ATTEMPTS)) < 0) {
        merror_exit(QUEUE_FATAL, DEFAULTQUEUE);
    }
 
    /* Main loop */
    LogCollectorStart();
 
    return (0);
}

消息队列声明与定义

/**
 *  Starts a Message Queue.
 *  @param key path where the message queue will be created
 *  @param type WRITE||READ
 *  @param n_attempts Number of attempts to connect to the queue (0 to attempt until a successful conection).
 *  @return
 *  UNIX -> OS_INVALID if queue failed to start
 *  UNIX -> int(rc) file descriptor of initialized queue
 *  WIN32 -> 0
 */
int StartMQ(const char *key, short int type, short int n_attempts) __attribute__((nonnull));

在函数声明末尾__attribute__((nonnull)); 使用nonnull能够将可能为空的值暴露出来,这样能够找出任何潜伏在调用代码中的空指针bug。如果key为空编译时将报错误,不至于到运行时才报错误。

/* Start the Message Queue. type: WRITE||READ */
int StartMQ(const char *path, short int type, short int n_attempts)
{
    if (type == READ) {
        return (OS_BindUnixDomain(path, SOCK_DGRAM, OS_MAXSTR + 512));
    }
 
    /* We give up to 21 seconds for the other end to start */
    else {
        int rc = 0, sleep_time = 5;
        short int attempt = 0;
 
        // If n_attempts is 0, trying to reconnect infinitely
        while ((rc = OS_ConnectUnixDomain(path, SOCK_DGRAM, OS_MAXSTR + 256)), rc < 0){
            attempt++;
            mdebug1("Can't connect to '%s': %s (%d). Attempt: %d", path, strerror(errno), errno, attempt);
            if (n_attempts != INFINITE_OPENQ_ATTEMPTS && attempt == n_attempts) {
                break;
            }
            sleep(sleep_time += 5);
        }
 
        if (rc < 0) {
            return OS_INVALID;
        }
 
        mdebug1("Connected succesfully to '%s' after %d attempts", path, attempt);
        mdebug1(MSG_SOCKET_SIZE, OS_getsocketsize(rc));
        return (rc);
    }
}

用unix domain socket作为消息队列。读消息队列的时候用OS_BindUnixDomain()数据报socket读,写的时候用OS_ConnectUnixDomain()

版权声明:本文为CSDN博主「x-ghost」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:blog.csdn.net/MEIYOUDAO_J…