1. systemd의 logrotate 기본구성 과 분석
syslog가 log 파일을 생성을 한다고 하면, 매번 Log를 주기적으로 backup을 하여 보관의 필요성을 느낄 것이며, 이를 위해서 사용되어지는 program이 logrotate이다
syslog가 log 파일을 생성을 한다고 하면, 매번 Log를 주기적으로 backup을 하여 보관의 필요성을 느낄 것이며, 이를 위해서 사용되어지는 program이 logrotate이다
만약 기본설치가 되어있다면, /etc/logrotate.conf 설정이 존재할 것이다.
다만 logrotate가 자동으로 실행되는 program이 아니며, Linux Filesystem에 따라 sysvInit 일 경우는 cron 을 이용하여 주기적으로 호출되고,
다만 logrotate가 자동으로 실행되는 program이 아니며, Linux Filesystem에 따라 sysvInit 일 경우는 cron 을 이용하여 주기적으로 호출되고,
systemd일 경우는 timer를 이용하여 이를 주기적으로 호출되어 동작가능하다
- syslog 관련내용
logrotate를 알기전에 syslogd에 대해 알자.
https://ahyuo79.blogspot.com/2019/04/syslog.html
https://ahyuo79.blogspot.com/2019/04/syslog.html
- 기본설정파일
- /etc/logrotate.conf :
- /etc/logrotate.d/btmp : 기본으로 설치됨
- /etc/logrotate.d/wtmp
- systemd의 timer 사용시 분석할 파일
- /lib/systemd/system/logrotate.timer
- /lib/systemd/system/logrotate.service
- /etc/systemd/system/timers.target.wants/logrotate.timer (Timer가 enable일 경우 존재)
1.1 logrotate 의 timer 와 service 분석
- logrotate 의 service 와 timer 분석
반드시 logrotate.service 와 logrotate.timer 의 prefix name이 logrotate.는 이름으로 동일해야 제대로 동작한다
logrotate.service는 logrotate.timer가 주기적으로 호출되어 를 구동하는 구조로 동작되어있기 때문에, systemd의 timer 현재 systemctl enable이 된 상태이다.
- logrotate.timer 구조 파악
분석으로 보면 매일 밤 12시, 즉 0시에 동작이 되며, Timer를 확인하는 주기는 12시간으로 정확성을 많이 떨어트리지만, Persistent를 이용
$ cat /lib/systemd/system/logrotate.timer [Unit] Description=Daily rotation of log files Documentation=man:logrotate(8) man:logrotate.conf(5) [Timer] OnCalendar=daily AccuracySec=12h Persistent=true [Install] WantedBy=timers.target
// systemctl enable logrotate.timer 할 경우 아래 link 생성됨 // systemctl disable logrotate.timer 할 경우 아래 link 제거됨 // timers.target.wants에 timer가 존재하는 것은 현재 enable 되는 상태 $ ls -al /etc/systemd/system/timers.target.wants/logrotate.timer /etc/systemd/system/timers.target.wants/logrotate.timer -> /lib/systemd/system/logrotate.timerrotate.timer
$ systemctl status logrotate.timer // 매일 0시에 Trigger되어 동작함 $ systemctl is-enabled logrotate.timer // logrotate.timer enable enabled
systemd.timer 의 OnCalendar 설정정보 시간설정방법
onCalendar Time 설정을 보면 전부 0시기준으로 동작
daily → *-*-* 00:00:00
시간동기화문제
OnCalendar 일반적으로 사용할 경우 time-sync.target 이후에 설정하도록 의존성을 넣는다고한다.
https://www.freedesktop.org/software/systemd/man/systemd.timer.html#Default%20Dependenciessystemd.timer 관련전체정보
https://www.freedesktop.org/software/systemd/man/systemd.timer.html
https://www.freedesktop.org/software/systemd/man/systemd.timer.html
기타 다른예제 (좋은예제)
- 상위 timer에 의해 실행되는 logrotate.service
기존의 Service 구조와 다르게 [Install] Section 이 없으며, *wants 및 에 위치 하지도 않는다
현재 systemctl disable logrotate.service 인 상태이지만 상위 timer가 구동을 시켜준다.
$ cat /lib/systemd/system/logrotate.service [Unit] Description=Rotate log files Documentation=man:logrotate(8) man:logrotate.conf(5) RequiresMountsFor=/var/log ConditionACPower=true [Service] Type=oneshot ExecStart=/usr/sbin/logrotate /etc/logrotate.conf # performance options Nice=19 IOSchedulingClass=best-effort IOSchedulingPriority=7 # hardening options # details: https://www.freedesktop.org/software/systemd/man/systemd.exec.html # no ProtectHome for userdir logs # no PrivateNetwork for mail deliviery # no ProtectKernelTunables for working SELinux with systemd older than 235 MemoryDenyWriteExecute=true PrivateDevices=true PrivateTmp=true ProtectControlGroups=true ProtectKernelModules=true ProtectSystem=full RestrictRealtime=true $ systemctl status logrotate.service // logrotate.service 동작시간 확인 $ systemctl is-enabled logrotate.service // logrotate.timer에 의해 동작 static
1.2 logrotate 설정분석
기본적으로 설정은 /etc/logrotate.conf에서 하지만, 확장설정이 가능하므로,
아래와 같이 include를 사용하여 /etc/logrotate.d 안에 있는 존재하는 모든 파일도 허용한다
- 기본설정구성
$ cat /etc/logrotate.conf # see "man logrotate" for details # rotate log files weekly weekly # keep 4 weeks worth of backlogs rotate 4 # create new (empty) log files after rotating old ones create # use date as a suffix of the rotated file dateext # uncomment this if you want your log files compressed #compress # packages drop log rotation information into this directory include /etc/logrotate.d # system-specific logs may be also be configured here.
- /var/log/btmp 설정
실패한 Login 정보 (lastb 명령어로 확인)
$ cat /etc/logrotate.d/btmp # no packages own btmp -- we'll rotate it here /var/log/btmp { missingok monthly create 0600 root utmp rotate 1 }
- /var/log/wtmp 설정
사용자의 Login/out과 시스템정보를 관리 (last 명령어로 확인)
$ cat /etc/logrotate.d/wtmp
# no packages own wtmp -- we'll rotate it here
/var/log/wtmp {
missingok
monthly
create 0664 root utmp
minsize 1M # 상위 monthly 와 별개로 사이즈가 넘으면 rotate
rotate 1
}
last 와 lastb
- /var/log/message 와 /var/log/test 설정 예
$ cat /etc/logrotate.d/test1 // kill -HUP syslogd 재시작 /var/log/messages /var/log/test { missingok ## 로그파일을 없어도, 에러없이 진행 (nomissingok 로그파일 없으면 에러발생 default) monthly rotate 5 dateext ## 저장된 log에 날짜표시 # ifempty ## ifempty 이 default (log파일 비어 있어도 rotate 진행) # nosharedscripts ## nosharedscripts 이 default 이며, 상위 /var/log/test*이면 여러개를 다 실행 postrotate ## logroate가 실행된 후 script로 kill로 Signal 전송하여 Refresh /bin/kill -HUP 'cat /var/run/syslogd.pid 2> /dev/null' 2> /dev/null endscript $ kill -l HUP INT QUIT ILL TRAP ABRT BUS FPE KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH IO PWR SYS RTMIN RTMIN+1 RTMIN+2 RTMIN+3 RTMIN+4 RTMIN+5 RTMIN+6 RTMIN+7 RTMIN+8 RTMIN+9 RTMIN+10 RTMIN+11 RTMIN+12 RTMIN+13 RTMIN+14 RTMIN+15 RTMAX-14 RTMAX-13 RTMAX-12 RTMAX-11 RTMAX-10 RTMAX-9 RTMAX-8 RTMAX-7 RTMAX-6 RTMAX-5 RTMAX-4 RTMAX-3 RTMAX-2 RTMAX-1 RTMAX ## 1 -HUP SIGHUP Refresh ##-2 INT SIGINT Interrupt (Ctrl+C) ##-3 QUIT SIGQUIT Quit (Ctrl+z) (이하 생략) }
Process에 문제가 있어서 다시 시작하고자 할 때에는 SIGHUP, SIGTERM, SIGKILL
kill 명령어
https://ko.wikipedia.org/wiki/Kill https://en.wikipedia.org/wiki/SIGHUP
$ cat /etc/logrotate.d/test2 // kill -HUP syslogd 재시작 /var/log/test { missingok daily rotate 10 dateext sharedscripts ## sharedscripts /var/log/news/* 같이 log가 여러개 중복될때 한번만실행 postrotate /bin/kill -HUP 'cat /var/run/syslogd.pid 2> /dev/null' 2> /dev/null endscript } /var/log/messages { missingok daily rotate 20 dateext postrotate /bin/kill -HUP 'cat /var/run/syslogd.pid 2> /dev/null' 2> /dev/null endscript } $ cat /etc/logrotate.d/test3 // kill -HUP syslogd 재시작 /var/log/messages { rotate 3 minsize 1M sharedscripts postrotate /bin/kill -HUP 'cat /var/run/syslogd.pid 2> /dev/null' 2> /dev/null endscript }
$ cat /var/lib/logrotate.status // 각 logroate가 된 후 상태확인
logrotate state -- version 2
"/var/log/test" 2020-08-06-0:0:58
"/var/log/wtmp" 2020-07-10-11:0:0
"/var/log/btmp" 2020-07-10-11:0:0
"/var/log/message" 2020-07-10-11:0:0
logrotate(cron) and syslogd
http://heart4u.co.kr/tblog/370
logrotate manual
https://jlk.fjfi.cvut.cz/arch/manpages/man/logrotate.8
https://linux.die.net/man/8/logrotate
https://jlk.fjfi.cvut.cz/arch/manpages/man/logrotate.8
https://linux.die.net/man/8/logrotate
logrotate in yocto
https://stackoverrun.com/ko/q/11519947
https://stackoverrun.com/ko/q/11519947
2. systemd 의 timer 사용방법
systemd의 timer는 monotonic timer 와 calendar time(Realtime)으로 구분이되는데, 거의 monotonic timer를 많이 사용할 것이므로 아래로 처럼 구성한다
- 현재 Timer 구성확인
$ systemctl list-timers // Timer 상태확인 or $ systemctl list-timers --all | cat // 모든 Timer 상태확인 (inactive timer 포함) or $ systemctl list-timers | cat NEXT LEFT LAST PASSED UNIT ACTIVATES Tue 2020-07-17 17:44:51 KST 7h left Mon 2020-07-16 17:44:51 KST 16h ago systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service Wed 2020-07-18 00:00:00 KST 14h left Tue 2020-07-17 00:00:36 KST 9h ago logrotate.timer logrotate.service
- monotonic timer 예제
$ cat monotonic.timer // booting 후 15분 후 동작후 매주 돌아가는 timer (미테스트) [Unit] Description=Run foo weekly and on boot [Timer] OnBootSec=15min OnUnitActiveSec=1w [Install] WantedBy=timers.target
- realtime timer 예제
$ realtime.timer // 일주일에 한번 12:00am on Monday 동작 (미테스트) [Unit] Description=Run foo weekly [Timer] OnCalendar=weekly Persistent=true # Persistent true이며, Timer가 실행한 서비스 Trigger정보를 Disk가 저장후 Timer가 동작할때, 즉각 Service 동작하도록 설정 [Install] WantedBy=timers.target
Realtime 으로 Monotonic Timer 구현
2.1 systemd 의 TEST Timer 구성
Timer를 잘 사용하기 위해서 monotonic timer 기반으로 구성 후 간단한 예제를 만들고, 이를 테스트 할 수 있는 shell script 와 함께
내부의 환경변수 값들을 변경해보면 직접 테스트 진행.
- Test Timer 전체구성
- /usr/bin/foo.sh
- /lib/systemd/system/foo.timer
- /lib/systemd/system/foo.service
- timer로 실행될 service의 shell script 작성
$ vi /usr/bin/foo.sh // 주기적으로 실행할 Shell Script #!/bin/sh # Author: Jeonghun # WAIT_100MS() { sleep 0.1 } # NOW 현재시간 # UPTIME 은 부팅후 시간 측정용 1st arg (Booting 후 Sec) 2nd arg (Idle Time Sec) NOW=$(date +"%H:%M:%S") UPTIME=`cat /proc/uptime` echo -e "\x1b[1;93m *** TIMER $NOW $UPTIME \x1b[0m" > /dev/kmsg $ chmod +x /usr/bin/foo.sh // 실행권한 설정
- systemd 의 foo.timer 작성 (sample)
$ vi /etc/systemd/system/foo.timer or $ vi /lib/systemd/system/foo.timer [Unit] Description=Run 3 Secs foo timer from 1 min after boot [Timer] OnBootSec=1min OnUnitActiveSec=3s #OnActiveSec=3s [Install] WantedBy=timers.target # # # [Timer] Section # # 반드시 Monotonic Timer로 설정시 아래 설정을 포함을 해야하며, 중복 설정도 가능 # OnActiveSec=, OnBootSec=, OnStartupSec=, OnUnitActiveSec=, OnUnitInactiveSec= # # 상위 설정을 한 후 세부 설정을 별도로 진행 $ systemctl enable foo.timer Created symlink /etc/systemd/system/timers.target.wants/foo.timer → /etc/systemd/system/foo.timer. $ ls -al /etc/systemd/system/timers.target.wants/foo.timer // 생성된 링크확인
https://www.freedesktop.org/software/systemd/man/systemd.timer.html
- systemd 의 timer 에 의해 실행될 service 설정
$ vi /etc/systemd/system/foo.service
or
$ vi /lib/systemd/system/foo.service // 상위 foo.timer에 의해 실행되므로 별도로 service 설정을 안해도 됨
[Unit]
Description=TEST
Requires=local-fs.target
After=local-fs.target
[Service]
Type=simple
ExecStart=/usr/bin/foo.sh
https://coderoad.ru/9619362/%D0%97%D0%B0%D0%BF%D1%83%D1%81%D0%BA-a-cron-%D0%BA%D0%B0%D0%B6%D0%B4%D1%8B%D0%B5-30-%D1%81%D0%B5%D0%BA%D1%83%D0%BD%D0%B4
AccuracySec=의 이해
2.2 TEST(foo.timer) 설정 변경 테스트
Timer의 설정의 의미를 알기 위해서 foo.timer의 설정값에 변경하여 개별 테스트 진행하며, 아래와 같이 그 결과도 알아본다.
- foo.timer 수정 후 테스트 및 분석 (전체 2번실행)
[Timer] OnBootSec=1min OnActiveSec=3s # OnBootSec Booting 후 실행되는 Timer 설정 1분이며, OnStartupSec= 값도 동일하게 설정 # OnStartupSec OnBootSec 거의 유사하지만 다른점은 service manager가 동작한 시점부터라고함 (아직 정확한 차이는 모름) # OnActiveSec Timer 자신이 Active 된 순간의 시간이라고 하는데, # AccuracySec Timer를 확인하는 주기 미설정시 기본 1분
// 1st TEST, 상위설정값 TEST 많이 다르며, 전체 2번만 동작 *** TIMER 14:55:59 14.64 0.77 // OnActiveSec 14초 Timer가 Active되는 순간 *** TIMER 14:56:55 70.89 47.92 // OnBootSec 70초 (AccuracySec 1분, 정확성이 떨어짐) // 2nd TEST, 상위설정값 TEST 많이 다르며, 전체 2번만 동작 *** TIMER 15:21:56 14.81 0.90 *** TIMER 15:22:53 72.45 50.00 // OnBootSec 72초 (AccuracySec 1분, 정확성이 떨어짐)
- foo.timer 수정 후 테스트 및 분석 (전체 1번실행)
[Timer]
OnBootSec=1min
AccuracySec=3s
# AccuracySec Timer를 확인하는 주기를 설정이며, 기본은 1분이지만,3초로 변경, 즉 정확성을 높임
// 1st TEST 상위 설정값대로 동작하며, 전체 1번만 동작 *** TIMER 15:33:52 62.05 39.34 // OnBootSec 62초 (AccuracySec 3초 이내) // 2nd TEST 상위 설정값대로 동작하며, 전체 1번만 동작 *** TIMER 15:38:43 62.95 40.51 // OnBootSec 62초 (AccuracySec 3초 이내)
- foo.timer 수정 후 테스트 및 분석 (계속실행)
[Timer] OnBootSec=1min OnUnitActiveSec=3s # OnBootSec Booting 후 실행되는 Timer 설정 1분이며, OnStartupSec= 값도 동일하게 설정 # OnUnitActiveSec 마지막(OnBootSec)에 Timer가 실행한 Unit(즉 서비스) Active가 되었을때 기준으로 3초 설정 # AccuracySec Timer를 확인하는 주기 미설정시 기본 1분
// 1st TEST, 상위설정값과 많이 다르지만 계속동작 *** TIMER 14:51:42 73.61 50.83 // OnBootSec 73초 (AccuracySec 때문에 정확성이 떨어짐) *** TIMER 14:52:19 111.12 87.40 // OnUnitActiveSec 111-73= 38초 *** TIMER 14:52:43 134.63 110.23 // OnUnitActiveSec 134-111= 23초 *** TIMER 14:53:01 153.08 128.23 // OnUnitActiveSec 153-134= 19초 *** TIMER 14:53:19 171.37 146.09 // 2nd TEST, 상위설정값과 많이 다르지만 계속동작 *** TIMER 15:02:58 78.25 55.14 // OnBootSec 78초 *** TIMER 15:03:32 111.50 87.60 *** TIMER 15:04:04 143.61 118.85 *** TIMER 15:04:19 158.80 133.61 *** TIMER 15:04:33 173.25 147.56
- foo.timer 수정 후 테스트 및 분석 (계속실행)
[Timer] OnBootSec=1min OnUnitActiveSec=3s AccuracySec=3s # OnUnitActiveSec 마지막(OnBootSec)에 Timer가 실행한 Unit(즉 서비스) Active가 되었을때 기준으로 3초 설정 # OnUnitInactiveSec 마지막(OnBootSec)에 Timer가 실행한 Unit(즉 서비스) inActive가 되었을때 기준으로 시간설정 # AccuracySec Timer를 확인하는 주기를 설정이며, 기본은 1분이지만,3초로 변경, 즉 정확성을 높임
// 1st TEST 상위 설정값과 유사하게 동작 (3~6 초) *** TIMER 15:14:11 60.66 37.90 // OnBootSec 60초 (AccuracySec 3초 이내) *** TIMER 15:14:17 66.65 43.66 // OnUnitActiveSec 3초 (AccuracySec 3초 이내) *** TIMER 15:14:21 70.65 47.49 *** TIMER 15:14:27 76.65 53.23 *** TIMER 15:14:31 80.65 57.03 *** TIMER 15:14:37 86.64 62.80 *** TIMER 15:14:41 90.64 66.65 *** TIMER 15:14:47 96.65 72.41 *** TIMER 15:14:51 100.64 76.23 *** TIMER 15:14:57 106.65 81.98 *** TIMER 15:15:01 110.64 85.82 *** TIMER 15:15:07 116.65 91.63 *** TIMER 15:15:11 120.65 95.41 *** TIMER 15:15:14 123.70 98.31 *** TIMER 15:15:20 129.65 103.99 // 2nd TEST 상위 설정값과 유사하게 동작 (3~6 초) *** TIMER 15:18:38 62.95 40.17 // OnBootSec 62초 (AccuracySec 3초 이내) *** TIMER 15:18:44 68.94 45.94 // OnUnitActiveSec 3초 (AccuracySec 3초 이내) *** TIMER 15:18:50 74.94 51.72 *** TIMER 15:18:54 78.95 55.56 *** TIMER 15:19:00 84.95 61.33 *** TIMER 15:19:04 88.95 65.16 *** TIMER 15:19:10 94.95 70.94 *** TIMER 15:19:14 98.94 74.77 *** TIMER 15:19:20 104.94 80.57 *** TIMER 15:19:24 108.94 84.39 *** TIMER 15:19:30 114.95 90.17 *** TIMER 15:19:34 118.94 94.01 *** TIMER 15:19:40 124.94 99.87 *** TIMER 15:19:44 128.95 103.73
- foo.timer 수정 후 테스트 및 분석 (계속실행)
[Timer] OnBootSec=1min OnUnitActiveSec=1s AccuracySec=3s # OnUnitActiveSec 마지막(OnBootSec)에 Timer가 실행한 Unit(즉 서비스) Active가 되었을때 기준으로 1초 설정 # AccuracySec Timer를 확인하는 주기를 설정이며, 기본은 1분이지만,3초로 변경, 즉 정확성을 높임
// 1st TEST 상위 설정값과 가장유사하게 동작 2-4초 간격 *** TIMER 15:27:55 61.66 38.97 // OnBootSec 61초 (AccuracySec 3초 이내) *** TIMER 15:27:59 65.65 42.82 // OnUnitActiveSec 1초 (AccuracySec 3초 이내) *** TIMER 15:28:03 69.65 46.64 *** TIMER 15:28:05 71.66 48.50 *** TIMER 15:28:09 75.65 52.26 *** TIMER 15:28:13 79.65 56.07 *** TIMER 15:28:15 81.65 57.98 *** TIMER 15:28:19 85.65 61.80 *** TIMER 15:28:23 89.66 65.65 *** TIMER 15:28:25 91.65 67.52 *** TIMER 15:28:29 95.65 71.35 *** TIMER 15:28:33 99.66 75.17 *** TIMER 15:28:35 101.65 77.06 *** TIMER 15:28:39 105.65 80.92 *** TIMER 15:28:43 109.65 84.74 *** TIMER 15:28:45 111.65 86.63 *** TIMER 15:28:49 115.66 90.47 *** TIMER 15:28:53 119.65 94.29 *** TIMER 15:28:55 121.66 96.18 *** TIMER 15:28:59 125.66 99.99 // 2nd TEST 상위 설정값과 가장유사하게 동작 *** TIMER 15:30:39 63.05 40.48 // OnBootSec 63초 (AccuracySec 3초 이내) *** TIMER 15:30:43 67.04 44.33 // OnUnitActiveSec 1초 (AccuracySec 3초 이내) *** TIMER 15:30:47 71.04 48.17 *** TIMER 15:30:50 74.04 51.06 *** TIMER 15:30:54 78.04 54.87 *** TIMER 15:30:58 82.04 58.69 *** TIMER 15:30:59 83.30 59.84 *** TIMER 15:31:03 87.04 63.42 *** TIMER 15:31:07 91.04 67.23 *** TIMER 15:31:10 94.04 70.10 *** TIMER 15:31:14 98.04 73.91 *** TIMER 15:31:18 102.04 77.74 *** TIMER 15:31:20 104.04 79.61 *** TIMER 15:31:24 108.04 83.43 *** TIMER 15:31:28 112.04 87.29 *** TIMER 15:31:30 114.04 89.20 *** TIMER 15:31:34 118.04 93.01 *** TIMER 15:31:38 122.04 96.81 *** TIMER 15:31:40 124.04 98.69 *** TIMER 15:31:42 126.39 100.92 *** TIMER 15:31:46 130.04 104.45
2.3 systemd 의 timer 와 service 동시 설정
지금까지는 상위 service는 timer가 실행을 해줄 때까지 기다리고 동작을 했지만, service도 별도로 동작가능하도록 설정하여, 동시 설정하여 사용하자
주로 이렇게 사용하는 이유는 booting 후 꼭 실행을 해야하는 경우가 될 것 같다.
- systemd의 timer 와 service 두개 중복 설정
// 상위 foo.timer의 실행과 foo.service 독자적인 실행으로 중복실행방법 $ vi /etc/systemd/system/foo.service or $ vi /lib/systemd/system/foo.service [Unit] Description=TEST Requires=local-fs.target After=local-fs.target [Service] Type=simple ExecStart=/usr/bin/foo.sh [Install] WantedBy=multi-user.target $ systemctl enable foo.service // 이제 foo.service로도 동작가능 (timer가 죽어도 동작가능) Created symlink /etc/systemd/system/multi-user.target.wants/foo.service → /etc/systemd/system/foo.service. $ ls -al /etc/systemd/system/multi-user.target.wants/foo.service // 생성된 링크확인