본문 바로가기
C

[C] Linux에서 System Log 사용 방법(openlog, syslog, closelog)

by Junk_Seo 2023. 11. 10.
반응형

1. 개요

  • glibc(GNU C Library)는 system log를 남기기 위한 라이브러리를 제공하고 있다. 
  • syslog.h 에서 제공해 주는 system log를 남기는 방법을 정리합니다.

2. syslog.h

  • syslog.h는 glibc에 포함되어 있기 때문에 따로 설치가 필요하지 않습니다.
  • syslog man page에서 확인이 가능합니다.
    • closelog, openlog, syslog, vsyslog - send messages to the system logger
  • syslog를 사용하면 /var/log/syslog 파일에 쓰인다.

3. 함수 설명

    3.1. openlog()

    • 함수 원형
      • void openlog(const char *ident, int option, int facility);
    • 설명
      • 시스템 로거와 연결을 생성하는 함수입니다.
      • openlog() 사용은 선택 사항입니다. (syslog()에 의해 자동으로 호출되는 경우, ident는 NULL로 설정됩니다.)
    • 파라미터 설명
      ident
      • 로그 앞에 추가되는 메시지입니다.
      • ident가 NULL로 설정되면 프로그램 이름으로 설정됩니다.
      option
      • 연결 옵션으로 비트 마스크로 구성됩니다.
      • 옵션 종류 다음과 같으며, 자세한 설명은 syslog man page 참고합니다.
        • LOG_CONS
        • LOG_NDELAY
        • LOG_NOWAIT
        • LOG_ODELAY
        • LOG_PERROR
        • LOG_PID
      facility
      • 메시지를 기록하는 프로그램 유형을 지정합니다.
      • 종류는 다음과 같으며, 자세한 설명은 syslog man page 참고합니다.
        • LOG_AUTH
        • LOG_AUTHPRIV
        • LOG_CRON
        • LOG_DAEMON
        • LOG_FTP
        • LOG_KERN
        • LOG_LOCAL0 ~ LOG_LOCAL7
        • LOG_LPR
        • LOG_MAIL
        • LOG_NEWS
        • LOG_SYSLOG
        • LOG_USER(기본값)
        • LOG_UUCP

    3.2. syslog()

    • 함수 원형
      • void syslog(int priority, const char *format,...);
    • 설명
      • 로그 메시지를 생성하는 함수입니다.
    • 파라미터 설명
      priority
      • 메시지의 중요성을 결정합니다.
      • 종류는 다음과 같으며, 자세한 설명은 syslog man page 참고합니다.
        • LOG_EMERG
        • LOG_ALERT
        • LOG_CRIT
        • LOG_ERR
        • LOG_WARNING
        • LOG_NOTICE
        • LOG_INFO
        • LOG_DEBUG
      format
      • 포맷을 설정하는 파라미터입니다.
      • 실제 로그 내용을 작성합니다.

    3.3. closelog()

    • 함수 원형
      • void closelog(void);
    • 설명
      • system 로그를 쓰는 데 사용한 파일 디스크립터를 닫아줍니다.
      • openlog()를 사용하여 system 로그 파일 디스크립터를 얻었다면 closelog()를 사용하여 system 로그 파일 디스크립터를 닫아줘야 합니다.

    3.4. vsyslog()

    • 함수 원형
      • void vsyslog(int priority, const char *format, va_list ap);
    • 설명
      • syslog() 함수와 동일한 작업을 수행하지만 stdarg(3) 가변 인수 목록 매크로를 사용하여 얻은 인수 집합을 사용한다는 차이점이 있습니다.
      • 자세한 설명은 syslog와 stdarg(3) man page를 참고합니다.

4. 사용 예제

    4.1. 예제 1)

    • 소스 코드
      int fn_TestSystemLog1()
      {
          openlog("MY LOG 1", LOG_CONS | LOG_PID, LOG_USER);
       
          syslog(LOG_INFO, "seo91_test log print!!!!");
       
          closelog();
       
          return 0;
      }​
      openlog() 함수를 사용하여 로그 앞에 추가할 메시지 "MY LOG 1"을 설정합니다.
      syslog() 함수를 사용하여 System Log에 출력할 메시지를 설정합니다.'
      closelog() 함수를 사용하여 닫습니다.
    • 결과 출력
      /var/log/syslog 파일에 시스템 로그가 출력되는 것을 확인할 수 있습니다.

    4.2. 예제 2)

    • 소스 코드
      int fn_TestSystemLog2()
      {
          syslog(LOG_INFO, "seo91_test log print!!!!");
       
          closelog();
       
          return 0;
      }
      openlog() 함수를 사용하지 않고 syslog() 함수를 바로 호출하여 System Log에 출력할 메시지를 설정하였습니다.
      closelog() 함수를 사용하여 닫습니다.

    • 결과 출력
      /var/log/syslog 파일에 시스템 로그가 출력되는 것을 확인할 수 있습니다.

    4.3. 예제 3)

    • 소스 코드
      #define SYSTEM_LOG(fmt,...) { \
              openlog("MY LOG 1", LOG_CONS | LOG_PID, LOG_USER); \
              syslog(LOG_INFO, fmt, ##__VA_ARGS__); \
              closelog(); \
              }
       
      ...
       
      int fn_TestSystemLog2()
      {  
          int nData = 1;
          char szData[10]= "1234";
          SYSTEM_LOG("log test1 [%d]", nData);
          SYSTEM_LOG("log test2 [%s]", szData);
          SYSTEM_LOG("log test3");
          return 0;
      }
      예제 2)의 함수를 define 함수로 만들어서 사용하였습니다.

    • 결과 출력
      /var/log/syslog 파일에 시스템 로그가 출력되는 것을 확인할 수 있습니다.

5. syslog message repeated

  • syslog에 동일한 로그 메시지를 짧은 기간 내에 기록하면, syslog 데몬은 이를 통합하고 반복 횟수를 나타내는 수를 추가합니다.
  • 해당 동작은 "/etc/rsyslog.conf" 또는 "/etc/syslog.conf" 설정 파일에서 "RepeatedMsgReduction" 구성 옵션에 의해 제어되며, 기본적으로 활성화되어 있습니다.
  • "message repeated"는 syslog 데몬 설정을 수정하면 비활성화할 수 있지만, 로그의 크기가 증가하고 가독성이 저하될 수 있으므로 권장하지 않습니다.

    5.1. 프로그램에서 "message repeated" 증상 확인

    • 프로그램에서 "syslog.h"에서 제공해 주는 syslog API를 사용하여 동일 log message를 반복적으로 남기는 경우 증상을 확인할 수 있습니다.
    • 소스 코드
      #include <stdio.h>
      #include <stdlib.h>
      #include <syslog.h>
       
      #define SYSTEM_LOG(ident, fmt,...) { \
              openlog(ident, LOG_CONS | LOG_PID | LOG_ODELAY, LOG_USER); \
              syslog(LOG_INFO, fmt, ##__VA_ARGS__); \
              closelog(); \
              }
       
      int fn_SyslogTest()
      {
          SYSTEM_LOG("system log test", "log test");
       
          return 0;
      }
       
      int main(int argc, char** argv)
      {
          int nMenu = 0;
       
          while (1)
          {
              printf("==== MENU ==== \n");
              printf("0 : Quit \n");
              printf("1 : Run \n");
              printf("============== \n");
              printf("cmd no. = ");
              scanf("%d", &nMenu);
       
              switch (nMenu)
              {
              case 0:
                  goto LABEL_ESC;
              case 1:
                  fn_SyslogTest();
                  break;
              default:
                  printf("unknown menu... \n");
              }
          }
       
      LABEL_ESC:
       
          return 0;
      }​​
      시스템 로그를 기록하도록 작성한 소스코드입니다.
      프로그램 실행 후 1을 입력하면 시스템 로그를 기록하여 0을 입력하면 프로그램을 종료합니다.
    • 실행 확인
      1을 입력하면 시스템 로그를 기록합니다.
    • System Log 확인
      짧은 기간 동안 동일한 syslog를 기록하면 최초 한 번 syslog 기록 후 더 이상 기록이 되지 않습니다.
    • 프로그램 재실행
      프로그램 종료 후 재실행하면 "message repeated..." 메시지를 출력합니다.
      위 메시지에서 "message repeated 5..."는 동일 메시지를 5번 기록 요청을 했다는 의미입니다.

5.2. 프로그램에서 "message repeated" 우회하기

    • 짧은 기간에 여러 번의 시스템 로그를 기록해야 하는 경우 message repeated로 인해 확인이 어렵습니다.
    • 따라서 이를 우회하기 위해 시스템 로그를 기록할 때 count와 같이 메시지를 변화하여 사용합니다.
    • 소스 코드
      #include <stdio.h>
      #include <stdlib.h>
      #include <syslog.h>
       
      #define SYSTEM_LOG(ident, fmt,...) { \
              openlog(ident, LOG_CONS | LOG_PID | LOG_ODELAY, LOG_USER); \
              syslog(LOG_INFO, fmt, ##__VA_ARGS__); \
              closelog(); \
              }
       
      int fn_SyslogTest(int nData)
      {
          SYSTEM_LOG("system log test", "log test");
       
          return 0;
      }
       
      int main(int argc, char** argv)
      {
          int i = 0;
          int nMenu = 0;
       
          while (1)
          {
              printf("==== MENU ==== \n");
              printf("0 : Quit \n");
              printf("1 : Run \n");
              printf("============== \n");
              printf("cmd no. = ");
              scanf("%d", &nMenu);
       
              switch (nMenu)
              {
              case 0:
                  goto LABEL_ESC;
              case 1:
                  fn_SyslogTest(i++);
                  break;
              default:
                  printf("unknown menu... \n");
              }
          }
       
      LABEL_ESC:
       
          return 0;
      }​
      시스템 로그를 기록할 때마다 count를 증가시킨 값을 메시지에 추가합니다.
    • 실행 결과
      시스테 로그 기록 시 count 값을 증가시키자 짧은 시간에 여러 번의 메시지를 기록하여도 정상적으로 확인할 수 있습니다.

6. 참고

반응형