상세 컨텐츠

본문 제목

[리눅스] SYSLOG로 CPU 정보 출력하는 리눅스서비스 만들기 #1

카테고리 없음

by 힐둔 2023. 5. 15. 11:49

본문

아래 이미지처럼 10초마다 CPU 사용량을 계산해서 출력해주는 프로그램이 있다고 해보자.

 

1. 프로그램을 작성하고 (아래 파일)

2. 컴파일하고 (gcc -o printcpu printcpu.cpp)

3. 실행 시킨다.  (./printcpu)

 

 

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>



int main() {
     time_t t;
     struct tm *tm;
     double a[4], b[4], loadavg;
     while (1) {
         t = time(NULL);
         tm = localtime(&t);
         FILE *fp = fopen("/proc/stat","r");

         fscanf(fp,"%*s %lf %lf %lf %lf",&a[0],&a[1],&a[2],&a[3]);
         fclose(fp);

         sleep(1);

         fp = fopen("/proc/stat","r");
         fscanf(fp,"%*s %lf %lf %lf %lf",&b[0],&b[1],&b[2],&b[3]);
         fclose(fp);

         loadavg = ((b[0]+b[1]+b[2]) - (a[0]+a[1]+a[2])) / ((b[0]+b[1]+b[2]+b[3]) - (a[0]+a[1]+a[2]+a[3]));
         printf("%04d-%02d-%02d %02d:%02d:%02d CPU usage : %.2f%%\n",
             tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
            tm->tm_hour, tm->tm_min, tm->tm_sec, loadavg * 100);

        sleep(9);
    }
    return 0;
}

 

 

이제 이걸 서비스로 만들어보자.

su 권한으로 로그인해서

1.  cd /etc/systemd/system으로 간다. 

2. 만들고 싶은 서비스 이름을 만든다. 난,printcpu.service 라는 이름으로 간단하게 만들어봤다.

3. 위에서 만들었던 printcpu라는 binary를 /usr/sbin에 옮겨야 한다. (아래 ExecStart로 지정했으므로.)

[Unit]
Description=System CPU check

[Service]
ExecStart=/usr/sbin/printcpu 
Restart=on-failure

[Install]
WantedBy=multi-user.target

 

 

이제 서비스를 시작해보자.

아래와 같이 만든 서비스 파일을 로드 하고, printcpu라는 서비스를 시작하도록 한다.

위에서 /etc/systemd/system/printcpu.service라고 만들었으니 서비스 이름은 printcpu.service나 printcpu로 입력 하면 된다.

sudo systemctl daemon-reload
sudo systemctl start printcpu.service

 

systemctl status printcpu로 잘 실행되고 있는지 확인해보자.

 

일단 서비스는 잘 시작 했으나, 10초에 한번씩 로그를 찍게 만드는 부분이 어디에 남아 있는지 보자.

systemd 로그는 기본적으로 /var/log/ 아래에 syslog에 남는다.

sudo vi /var/log/syslog 라는 명령으로 실행해보면 아래와 같이 printcpu라는 서비스가 시작 했다라는 것만 로그에 남고 실제 printf 로 찍은 로그는 남지 않는 걸 확인할 수 있다.

 

 

다시 코드를 살펴보자. printf로 찍은 걸 syslog()를 이용하도록 변경해보자.

syslog.h를 include 해주고, openlog() 함수를 사용하여 로그에 대한 설정을 합니다. 첫 번째 인자는 로그 이름을 지정하는데, 여기서는 "printcpu"라고 지정하고, 두 번째 인자는 로그 옵션을 지정하는데, LOG_PID 옵션을 사용하면 프로세스 ID가 로그에 추가된다. 마지막으로  세 번째 인자는 로그 타입을 지정하는데, LOG_DAEMON을 사용하면 로그를 시스템 로그에 기록하게 된다. 그리고 기존에 printf를 syslog() 함수로 변경한다. 첫 번째 인자에 로그 레벨을 지정할 수 있는데, LOG_INFO를 설정했다. 마지막으로 closelog() 함수를 사용하여 로그를 닫아주었다.

 

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <syslog.h>

int main() {
    time_t t;
    struct tm *tm;
    double a[4], b[4], loadavg;

    openlog("printcpu", LOG_PID, LOG_DAEMON);

    while (1) {
        t = time(NULL);
        tm = localtime(&t);
        FILE *fp = fopen("/proc/stat","r");

        fscanf(fp,"%*s %lf %lf %lf %lf",&a[0],&a[1],&a[2],&a[3]);
        fclose(fp);

        sleep(1);
 
        fp = fopen("/proc/stat","r");
        fscanf(fp,"%*s %lf %lf %lf %lf",&b[0],&b[1],&b[2],&b[3]);
        fclose(fp);
 
        loadavg = ((b[0]+b[1]+b[2]) - (a[0]+a[1]+a[2])) / ((b[0]+b[1]+b[2]+b[3]) - (a[0]+a[1]+a[2]+a[3]));
 //       printf("%04d-%02d-%02d %02d:%02d:%02d CPU usage : %.2f%%\n",
 //           tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
 //           tm->tm_hour, tm->tm_min, tm->tm_sec, loadavg * 100);
 
        syslog(LOG_INFO, "%04d-%02d-%02d %02d:%02d:%02d CPU usage : %.2f%%\n",
            tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
            tm->tm_hour, tm->tm_min, tm->tm_sec, loadavg * 100);
 
        sleep(9);
    }
 
    closelog();
    return 0;
 }

 

다시 컴파일하고, binary를 /usr/sbin에 옮긴다. 기존에 서비스가 돌고 있으므로 정지를 시켜줘야 한다. 이땐 sudo systemctl stop printcpu를 이용하자. binary 파일 복사가 되었으면 다시 서비스를 시작해보자. 그리고 /var/log/syslog를 보면 아래와 같이 의도한대로 INFO type으로 printcpu라는 이름으로 로그가 남는 걸 확인할 수 있다. 

 

일단 불필요한 로그가 많이 남으므로 서비스는 종료해놓도록 하자. 

댓글 영역