понедельник, 17 мая 2010 г.

Linux: создание демона

Тема написание демонов широко освещена в интернете (Гугл), так что написанное тут не будет ни для кого секретом.
Просто опишу здесь пример реализации демона, выполняющий каждые 10 минут произвольную команду linux (в данном случае - who, список подключенных пользователей) и записывающий результат в лог.
Код на Си(c)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <syslog.h>

int Daemon(void);
char* getTime();
int writeLog(char msg[256]);
char* getCommand(char command[128]);

char* getTime() { //функция возвращает форматированную дату и время
    time_t now;
    struct tm *ptr;
    static char tbuf[64];
    bzero(tbuf,64);
    time(&now);
    ptr = localtime(&now);
    strftime(tbuf,64, "%Y-%m-%e %H:%M:%S", ptr);
    return tbuf;
}

char* getCommand(char command[128]) { //функция возвращает результат выполнения linux команды
    FILE *pCom;
    static char comText[256];
    bzero(comText, 256);
    char  buf[64];
    pCom = popen(command, "r"); //выполняем
    if(pCom == NULL) {
        writeLog("Error Command");
        return "";
    }
    strcpy(comText, "");
    while(fgets(buf, 64, pCom) != NULL) { //читаем результат
        strcat(comText, buf);
    }
    pclose(pCom);
    return comText;
}

int writeLog(char msg[256]) { //функция записи строки в лог
    FILE * pLog;
    pLog = fopen("/home/CENTRAL/skan/daemon/daemon.log", "a");
    if(pLog == NULL) {
        return 1;
    }
    char str[312];
    bzero(str, 312);
    strcpy(str, getTime());
    strcat(str, " ==========================\n");
    strcat(str, msg);
    strcat(str, "\n");
    fputs(str, pLog);
    //fwrite(msg, 1, sizeof(msg), pLog);
    fclose(pLog);
    return 0;
}

int main(int argc, char* argv[]) {
    writeLog("Daemon Start");

    pid_t parpid, sid;
    
    parpid = fork(); //создаем дочерний процесс
    if(parpid < 0) {
        exit(1);
    } else if(parpid != 0) {
        exit(0);
    } 
    umask(0);//даем права на работу с фс
    sid = setsid();//генерируем уникальный индекс процесса
    if(sid < 0) {
        exit(1);
    }
    if((chdir("/")) < 0) {//выходим в корень фс
        exit(1);
    }
    close(STDIN_FILENO);//закрываем доступ к стандартным потокам ввода-вывода
    close(STDOUT_FILENO);
    close(STDERR_FILENO);
    
    return Daemon();
}

int Daemon(void) { //собственно наш бесконечный цикл демона
    char *log;
    while(1) {
        log = getCommand("who");
        if(strlen(log) > 5) { //если в онлайне кто-то есть, то пишем в лог
          writeLog(log);
        }
        sleep(600);//ждем 10 минут до следующей итерации
    }
    return 0;
}

7 комментариев:

  1. При попытке скомпилить:

    main.cpp: In function ‘char* getTime()’:
    main.cpp:22: error: ‘time’ was not declared in this scope
    main.cpp:23: error: ‘localtime’ was not declared in this scope
    main.cpp:24: error: ‘strftime’ was not declared in this scope
    main.cpp: In function ‘char* getCommand(char*)’:
    main.cpp:35: warning: deprecated conversion from string constant to ‘char*’
    main.cpp:36: warning: deprecated conversion from string constant to ‘char*’
    main.cpp: In function ‘int main(int, char**)’:
    main.cpp:65: warning: deprecated conversion from string constant to ‘char*’
    main.cpp: In function ‘int Daemon()’:
    main.cpp:93: warning: deprecated conversion from string constant to ‘char*’

    ОтветитьУдалить
    Ответы
    1. Это C код, а не C++, юзай gcc

      Удалить
    2. root@da0f63e59b81:/daemons# gcc exDaemon.c -o exDaemon exDaemon.c: In function 'getTime': exDaemon.c:22:5: warning: implicit declaration of function 'time' [-Wimplicit-function-declaration] 22 | time(&now); | ^~~~ exDaemon.c:23:11: warning: implicit declaration of function 'localtime' [-Wimplicit-function-declaration] 23 | ptr = localtime(&now); | ^~~~~~~~~

      Удалить
    3. root@da0f63e59b81:/daemons# apt-get upgrade gcc Reading package lists... Done Building dependency tree... Done Reading state information... Done gcc is already the newest version (4:11.2.0-1ubuntu1). gcc set to manually installed. Calculating upgrade... Done 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.

      Удалить
  2. Спасибо, очень помогло.

    ОтветитьУдалить
  3. Этот комментарий был удален автором.

    ОтветитьУдалить