** ArchLinux 는 상황이 약간 다르다!
아래 글은 Ubuntu 환경을 가정했다. ArchLinux 에선, Cron/Anacron 부터 설치해줘야 한다.
설치하고 나서 아래 내용대로 설정해주면 되겠다.
이전에 쓴 꽃삽질기를 이은 cron 과 anacron 의 환상 조합 그 두번째.
이번에는 root 가 아닌 ‘일개’ 사용자가 anacron 을 사용하는 방법에 관해 정리한다.
그냥 crontab -e
로 원하는 작업을 설정하면 되긴 하지만, cron 의 한계인, 정해진 시간에 ‘꺼져 있을 때’의 문제가 첫번째고, crontab 설정의 backup 이 불편하다는게 두번째다. (crontab -l > crontab.backup 으로 해줘야 한다.)
이 글에선, cron 이 /etc/cron.daily 등을 사용하는 방법을 흉내내어 본다. 그리하면, 파일 관리가 조금은 더 쉬워질 수 있다.
다음 글에서 큰 도움을 얻었다.
StackExchange : How can I run anacron in user mode?
Anacron 설정
anacron 은 그냥 실행시키면 /etc/anacrontab 과 /var/spool/cron/crontabs/userid 밑의 파일들을 사용한다.
그러나, 이 파일들은 일반 사용자가 접근할 수 없으므로, 사용자 홈디렉토리에 저 파일들을 만들어줘야 한다.
어느 디렉토리를 택해서 만들지는 사용자 맘이고, 나는 ~/.anacron 에 만들기로 했다.
여기에, /etc/cron.daily 역할을 할 디렉토리도 만든다. 역시 맘대로 해도 되고, jobs_todo
라고 정했다. 그리고 각각 daily, weekly, monthly 용 프로그램을 넣을 디렉토리도 만든다.
마지막으로, spool 용 디렉토리도 만든다.
mkdir ~/.anacron mkdir ~/.anacron/jobs_todo mkdir ~/.anacron/jobs_todo/anacron.daily mkdir ~/.anacron/jobs_todo/anacron.weekly mkdir ~/.anacron/jobs_todo/anacron.monthly mkdir ~/.anacron/spool
다시 말하지만, 위 디렉토리명은 모두 원하는대로 정하면 된다.
다음, 이 위치에 anacrontab (이름은 달리 정해도 된다.) 을 만든다. 그냥 편하게 /etc/anacrontab 을 복사한다.
cp /etc/anacrontab ~/.anacron/
그리고 이 파일을 편집한다.
# /etc/anacrontab: configuration file for anacron # See anacron(8) and anacrontab(5) for details. SHELL=/bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:$HOME/bin:$HOME/.local/bin # These replace cron's entries 1 5 my_anacron.daily run-parts --report $HOME/.anacron/jobs_todo/anacron.daily 7 10 my_anacron.weekly run-parts --report $HOME/.anacron/jobs_todo/anacron.weekly @monthly 15 my_anacron.monthly run-parts --report $HOME/.anacron/jobs_todo/anacron.monthly
굳이 필요는 없을 듯 하지만, PATH 에 ~/bin 과 ~/.local/bin 을 추가했다.
job-identifier 로는 원래 있던 값인 cron.* 를 my_anacron.* 로 바꿨다. 이 설정으로 인해, ~/.anacron/spool/my_anacron.daily 파일 등이 생긴다.
이 파일들은 anacron 이 사용하는 timestamp 다.
command 로는 run-parts 를 사용하기로 했는데, 사실 이 기능을 사용하고 싶어서 길을 다소 돌아온 셈이다. run-parts 는 지정한 디렉토리에 있는 파일을 모두 실행해주는 명령으로, 여기서는 .anacron/jobs_todo/anacron.daily(weekly, monthly) 등에 있는 파일들을 돌리게끔 했다.
즉, anacron 에 의해 실행되게끔 하고 싶은 파일들을 저 디렉토리들에 넣어놓으면, 자동 실행이 된다.
이 방식이 아니면, crontab 에 한 줄씩 명령을 넣어놓든가, 아니면 거기에 run-parts 를 넣어야 하는데, 그렇게 되면 역시나 ‘PC가 꺼져 있을 때 문제’를 해결할 수가 없다.
anacron(정확히는 run-parts) 용 실행파일명은 반드시!
왜 그런지는 모르겠으나, .anacron/jobs_todo/anacron.daily(weekly, monthly) 에 들어갈 파일, 즉 run-parts 가 실행할 파일들의 파일명에는 확장자(.sh)가 있어선 안된다. runme
는 되지만, runme.sh
는 안된다. runme.py
도 마찬가지. run-parts --test <dir>
로 확인해보면, 저런 파일명을 가진 파일들은 출력되지 않음을 확인할 수 있다.
왜 안되는 걸까..?
찾아보니, 파일명을 찾는 regex 때문으로 보인다. (man page 에도 이 내용이 나와있다.)
글쓴이는 regex 를 적절히 바꾸라고 하는데, 그러기엔 복잡하니, 심볼릭 링크를 사용하는 방법이 좋아 보인다.
따라서, 이 디렉토리에 실제로 파일을 넣기 보다는, 심볼릭 링크를 만들되, sh 등 확장자를 빼주면 되겠다.
이런 식으로.
ln -s ~/.local/bin/program-to-run1.sh ~/.anacron/jobs_todo/anacron.daily/program-to-run1 ln -s ~/.local/bin/program-to-run2.py ~/.anacron/jobs_todo/anacron.daily/program-to-run2
이러면 설정이 끝난 듯 한데.. 정말로?
뭔가 빠진게 있다.
설정만 했지, 실행하는 명령은 넣지 않았다.
Anacron 실행
진짜(?) anacron 은, anacron.timer 에 의해 매 시간 실행된다.
그러나 사용자에 의해 설정된 anacron 은, 매시간 알아서 돌아가질 않는다.
사용자 anacron 이 시스템 anacron 과 동일한 기능을 가지려면, 매시간 돌려주는 기능을 강제 추가해줘야 한다.
이걸 어떻게 할까?
답은 cron, 정확히는 crontab.
사용자용 crontab(crontab -e
)을 편집하여, 매시간 anacron 을 돌리게 만든다.
# Edit this file to introduce tasks to be run by cron. # # Each task to run has to be defined through a single line # indicating with different fields when the task will be run # and what command to run for the task # # To define the time you can provide concrete values for # minute (m), hour (h), day of month (dom), month (mon), # and day of week (dow) or use '*' in these fields (for 'any').# # Notice that tasks will be started based on the cron's system # daemon's notion of time and timezones. # # Output of the crontab jobs (including errors) is sent through # email to the user the crontab file belongs to (unless redirected). # # For example, you can run a backup of all your user accounts # at 5 a.m every week with: # 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/ # # For more information see the manual pages of crontab(5) and cron(8) # # m h dom mon dow command # Anacron 실행 (조금 복잡하다.) @hourly /usr/sbin/anacron -sdq -t $HOME/.anacron/anacrontab -S $HOME/.anacron/spool
- @hourly 는 “0 * * * *” 와 같다. 즉, 매시 정각에 실행된다.
- -sqd 는 anacron.service 에 있는 내용을 그대로 따라 했다. (man anacron 참고)
- -t 는 anacrontab 파일의 위치,
- -S 는 spool 디렉토리의 위치를 가리킨다.
모든 설정 끝.
모든 과정(공정?)을 정리해보면 다음과 같다.
- crontab 으로, 매시간(@hourly) 사용자 지정 anacron 을 실행하게 한다.
- anacron 은, $HOME/.anacron/spool 에서 timestamp 를 확인한 후,
- anacrontab 에서 지정한 디렉토리(.anacron/jobs_todo/anacron.daily 등)에 있는 모든 파일을 실행한다.
위 작업은 매시간 반복된다.
또, 확실하진 않지만, 이 작업과 시스템의 anacron 이 충돌할 가능성은 없다. 각각 독자로 실행되기 때문이다. 인위로 두 anacron 을 돌려봤는데, 동시에 두개가 작동하고 있었다.
$ ps aux | grep -i anacron .... root 31313 0.0 0.0 8760 748 pts/5 S+ 23:07 0:00 anacron -sd myuserid 31337 0.0 0.0 8760 748 pts/6 S+ 23:07 0:00 anacron -sd -t /home/myuserid/.anacron/anacrontab -S /home/myuserid/.anacron/spool
Anacron 실행 확인
시스템 anacron 은 systemd 로 확인할 수 있다. sudo 는 없어도 된다.
$ systemctl status anacron.service ● anacron.service - Run anacron jobs Loaded: loaded (/lib/systemd/system/anacron.service; enabled; vendor preset: enabled) Active: inactive (dead) since Fri 2020-05-22 23:00:24 KST; 11min ago Docs: man:anacron man:anacrontab Process: 30154 ExecStart=/usr/sbin/anacron -dsq (code=exited, status=0/SUCCESS) Main PID: 30154 (code=exited, status=0/SUCCESS) 5월 22 23:00:24 kdeneon systemd[1]: Started Run anacron jobs. 5월 22 23:00:24 kdeneon anacron[30154]: Anacron 2.3 started on 2020-05-22 5월 22 23:00:24 kdeneon anacron[30154]: Normal exit (0 jobs run)
이렇게 상황을 볼 수 있다. anacron.timer 로 조회하면 다음 실행 시간도 알 수 있다.
개인용 anacron 은 서비스가 아니므로 이 방식을 사용할 순 없고, 대신 cron 을 조회하면 된다.
$ systemctl status cron.service ~ ● cron.service - Regular background program processing daemon Loaded: loaded (/lib/systemd/system/cron.service; enabled; vendor preset: enabled) Active: active (running) since Fri 2020-05-22 19:37:06 KST; 3h 35min ago Docs: man:cron(8) Main PID: 1049 (cron) Tasks: 1 (limit: 4915) CGroup: /system.slice/cron.service └─1049 /usr/sbin/cron -f 5월 22 22:00:01 kdeneon anacron[23411]: Anacron 2.3 started on 2020-05-22 5월 22 22:00:01 kdeneon anacron[23411]: Will run job `my_anacron.daily' in 5 min. 5월 22 22:00:01 kdeneon anacron[23411]: Jobs will be executed sequentially 5월 22 22:05:01 kdeneon anacron[23411]: Job `my_anacron.daily' started 5월 22 22:05:01 kdeneon anacron[23411]: Job `my_anacron.daily' terminated 5월 22 22:05:01 kdeneon anacron[23411]: Normal exit (1 job run) 5월 22 22:17:01 kdeneon CRON[24569]: pam_unix(cron:session): session opened for user root by (uid=0) 5월 22 22:17:01 kdeneon CRON[24569]: pam_unix(cron:session): session closed for user root 5월 22 23:00:01 kdeneon CRON[30088]: pam_unix(cron:session): session opened for user myuserid by (uid=0) 5월 22 23:00:01 kdeneon CRON[30088]: pam_unix(cron:session): session closed for user myuserid
이 정도면 훌륭할 듯…?