들어가며 — 왜 지금 다시 타이머인가
최근 Hacker News 프런트페이지에 "You don't love systemd timers enough"라는 글이 올라와 수백 개의 댓글이 달리며 화제가 됐습니다. 제목부터 도발적입니다. systemd 논쟁은 리눅스 커뮤니티의 영원한 떡밥이지만, 이 글의 논지는 의외로 담백했습니다. "cron으로 스케줄링하면서 겪는 고통의 대부분은 이미 systemd 타이머가 10년 전에 해결했는데, 왜 아직도 crontab을 열고 있는가?"라는 것이죠.
댓글란의 반응도 흥미로웠습니다. "타이머 유닛 두 개 만드는 게 crontab 한 줄보다 번거롭다"는 반론과, "그 한 줄이 조용히 실패하고 있다는 걸 6개월 뒤에 알게 된다"는 재반론이 맞붙었습니다. 2026년 현재 AI 코딩 에이전트가 서버 설정 파일까지 생성해주는 시대가 되면서 "유닛 파일 두 개 작성"의 비용은 사실상 0에 수렴했고, 남은 것은 운영 품질의 차이뿐입니다.
이 글에서는 cron의 구조적 한계부터 시작해, systemd 타이머의 유닛 구조, OnCalendar 문법, 놓친 실행 캐치업, 실패 알림, 유저 타이머, 그리고 cron에서 타이머로 옮겨가는 마이그레이션 매핑까지 실무 관점에서 정리합니다.
cron의 구조적 한계
cron은 1975년에 태어난 도구입니다. 50년을 살아남은 것 자체가 위대하지만, 현대 운영 환경에서는 다음 문제들이 반복적으로 발목을 잡습니다.
1. 로깅의 부재
cron 작업의 출력은 기본적으로 로컬 메일로 발송됩니다. MTA가 설정되지 않은 서버(대부분의 클라우드 인스턴스)에서는 출력이 그냥 사라집니다. 그래서 다들 이렇게 씁니다.
crontab의 흔한 풍경 — 로그를 수동으로 파일에 욱여넣기
0 3 * * * /opt/backup.sh >> /var/log/backup.log 2>&1
이 방식의 문제는 명확합니다. 로그 로테이션을 따로 챙겨야 하고, 타임스탬프도 스크립트가 직접 찍어야 하며, "마지막 실행이 성공했는지"를 알려면 로그 파일을 파싱해야 합니다.
2. 의존성 표현 불가
"네트워크가 올라온 뒤에", "마운트가 완료된 뒤에", "다른 서비스가 떠 있을 때만" 같은 조건을 cron은 표현할 수 없습니다. 그래서 스크립트 안에 sleep과 재시도 루프가 들어가기 시작하고, 스케줄러가 해야 할 일을 셸 스크립트가 떠안게 됩니다.
3. 놓친 실행은 영원히 사라진다
새벽 3시에 백업이 돌도록 설정했는데 그 시간에 서버가 꺼져 있었다면? cron은 아무 일도 하지 않습니다. anacron이라는 보완책이 있지만 일 단위 해상도라는 한계가 있고, 별도 도구를 하나 더 관리해야 합니다.
4. 환경의 함정
cron은 거의 빈 환경 변수로 작업을 실행합니다. PATH가 달라서 "터미널에서는 되는데 cron에서는 안 되는" 디버깅 지옥은 모든 시스템 관리자의 통과의례입니다.
5. 동시 실행 제어 부재
이전 실행이 아직 끝나지 않았는데 다음 스케줄이 도래하면 cron은 그냥 또 실행합니다. flock으로 감싸는 관용구가 필요합니다.
이 다섯 가지를 표로 정리하면 이렇습니다.
| 문제 | cron | systemd 타이머 |
| --- | --- | --- |
| 로깅 | 수동 리다이렉션 | journald 자동 수집 |
| 의존성 | 불가 | After, Requires 등 유닛 의존성 |
| 놓친 실행 | 사라짐 | Persistent=true로 캐치업 |
| 환경 | 빈 환경, PATH 함정 | 유닛 파일에 명시적 정의 |
| 동시 실행 | flock 수동 처리 | 서비스 유닛은 기본 단일 인스턴스 |
| 실패 알림 | 메일(보통 미설정) | OnFailure 핸들러 |
| 리소스 제한 | 불가 | CPUQuota, MemoryMax 등 |
타이머 유닛의 구조 — .timer와 .service 페어
systemd 타이머는 두 개의 유닛 파일로 구성됩니다. "언제"를 정의하는 .timer 유닛과 "무엇을"을 정의하는 .service 유닛입니다. 이름이 같으면 자동으로 짝이 맺어집니다.
backup.timer ──────트리거──────▶ backup.service
(언제 실행할지) (무엇을 실행할지)
│ │
│ OnCalendar=... │ ExecStart=/opt/backup.sh
│ Persistent=true │ User=backup
│ RandomizedDelaySec=... │ MemoryMax=1G
▼ ▼
systemctl list-timers journalctl -u backup.service
실제 예제를 보겠습니다. 매일 새벽 3시에 백업을 실행하는 구성입니다.
/etc/systemd/system/backup.service
[Unit]
Description=Nightly backup job
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
ExecStart=/opt/scripts/backup.sh
User=backup
Nice=10
IOSchedulingClass=idle
MemoryMax=1G
TimeoutStartSec=2h
/etc/systemd/system/backup.timer
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
RandomizedDelaySec=15m
[Install]
WantedBy=timers.target
활성화는 타이머 쪽만 하면 됩니다. 서비스는 타이머가 트리거하므로 enable하지 않습니다.
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
즉시 한 번 실행해보고 싶다면 서비스를 직접 시작
sudo systemctl start backup.service
서비스 유닛에 Type=oneshot을 쓰는 이유는 "실행하고 끝나는 작업"임을 systemd에 알리기 위해서입니다. 또한 위 예제처럼 Nice, IOSchedulingClass, MemoryMax 같은 리소스 제어를 곁들이면 백업 작업이 프로덕션 트래픽을 방해하지 않게 할 수 있습니다. cron에서는 꿈도 못 꾸는 기능입니다.
OnCalendar 문법 상세
OnCalendar는 cron 표현식보다 읽기 쉽고 표현력도 높습니다. 기본 형식은 다음과 같습니다.
요일 연-월-일 시:분:초
(모든 필드는 생략 가능, * 는 와일드카드, / 는 간격, , 는 나열, .. 는 범위)
예제를 많이 보는 것이 가장 빠릅니다.
매일 새벽 3시
OnCalendar=*-*-* 03:00:00
매시간 정각
OnCalendar=hourly
위와 동일한 명시적 표현
OnCalendar=*-*-* *:00:00
15분마다
OnCalendar=*:0/15
평일(월~금) 오전 9시
OnCalendar=Mon..Fri *-*-* 09:00:00
매주 월요일과 목요일 06:30
OnCalendar=Mon,Thu *-*-* 06:30:00
매월 1일 자정
OnCalendar=*-*-01 00:00:00
매월 마지막 날 23시 (~ 접두사는 월말 기준 역산)
OnCalendar=*-*~01 23:00:00
분기 첫날 (1,4,7,10월 1일) 새벽 2시
OnCalendar=*-01,04,07,10-01 02:00:00
2시간마다, 정각이 아닌 30분에 (00:30, 02:30, ...)
OnCalendar=00/2:30:00
하나의 타이머에 여러 스케줄 — OnCalendar를 여러 줄 쓰면 OR로 합쳐짐
OnCalendar=Mon..Fri 09:00
OnCalendar=Sat,Sun 11:00
작성한 표현식이 의도대로 해석되는지 반드시 검증하세요. systemd-analyze calendar가 다음 실행 시각까지 계산해줍니다.
$ systemd-analyze calendar "Mon..Fri *-*-* 09:00:00"
Original form: Mon..Fri *-*-* 09:00:00
Normalized form: Mon..Fri *-*-* 09:00:00
Next elapse: Fri 2026-06-12 09:00:00 KST
(in UTC): Fri 2026-06-12 00:00:00 UTC
From now: 14h left
다음 5회 실행 시각을 한 번에 확인
$ systemd-analyze calendar --iterations=5 "*-*-01 02:00"
모노토닉 타이머 — 부팅/활성화 기준 상대 시간
달력 기준이 아니라 "어떤 시점으로부터 얼마 뒤"로 정의하는 타이머도 있습니다.
[Timer]
부팅 15분 뒤 첫 실행, 이후 마지막 실행 종료 1시간 뒤마다 반복
OnBootSec=15min
OnUnitActiveSec=1h
OnUnitActiveSec은 "이전 실행이 끝난 시점 기준"이므로, 작업 시간이 들쭉날쭉해도 실행 간격이 겹치지 않습니다. 폴링형 작업에 특히 유용합니다.
Persistent=true — 놓친 실행을 캐치업하다
타이머의 킬러 기능입니다. Persistent=true를 설정하면 systemd는 마지막으로 타이머가 트리거된 시각을 디스크에 기록합니다. 시스템이 꺼져 있어서 스케줄을 놓쳤다면, 다음 부팅 직후 즉시 한 번 실행해줍니다.
[Timer]
OnCalendar=daily
Persistent=true
노트북이나 간헐적으로 켜지는 개발 장비에서 "매일 백업"을 보장하고 싶을 때 anacron 없이 해결됩니다. 기록은 다음 경로에 남습니다.
$ ls /var/lib/systemd/timers/
stamp-backup.timer stamp-fstrim.timer stamp-logrotate.timer
스탬프 파일의 mtime이 마지막 트리거 시각
$ stat -c '%y' /var/lib/systemd/timers/stamp-backup.timer
2026-06-11 03:07:42.000000000 +0900
주의할 점이 하나 있습니다. 부팅 직후에는 캐치업 대상 타이머들이 한꺼번에 몰려 실행될 수 있습니다. 그래서 다음에 설명할 RandomizedDelaySec과 함께 쓰는 것이 정석입니다.
RandomizedDelaySec과 AccuracySec
여러 서버가 같은 시각에 일제히 외부 API를 때리거나 백업 스토리지에 몰리는 "thundering herd"를 피하려면 지연을 무작위화합니다.
[Timer]
OnCalendar=daily
0~4시간 사이 무작위 지연 — 서버 무리가 시간대에 골고루 분산됨
RandomizedDelaySec=4h
같은 머신에서 매번 같은 오프셋을 쓰고 싶다면 (systemd 247+)
FixedRandomDelay=true
AccuracySec은 반대로 "얼마나 정확하게 깨울 것인가"입니다. 기본값이 1분이라는 점을 모르면 당황할 수 있습니다. 초 단위 정밀 실행이 필요하면 명시적으로 줄여야 합니다.
[Timer]
OnCalendar=*-*-* 09:00:00
기본 1min → 1초 단위 정밀도로
AccuracySec=1s
반대로 전력 절약이 중요한 환경(노트북, 임베디드)에서는 AccuracySec을 늘려 CPU 웨이크업을 묶을 수 있습니다.
모니터링 — list-timers와 journalctl
cron 대비 타이머의 최대 강점은 관측 가능성입니다. 먼저 전체 타이머의 상태를 한 화면에서 봅니다.
$ systemctl list-timers --all
NEXT LEFT LAST PASSED UNIT ACTIVATES
Fri 2026-06-12 03:00:00 KST 8h left Thu 2026-06-11 03:11:02 KST 12h ago backup.timer backup.service
Fri 2026-06-12 00:00:00 KST 5h left Thu 2026-06-11 00:00:01 KST 15h ago logrotate.timer logrotate.service
NEXT(다음 실행), LAST(마지막 실행)가 바로 보입니다. crontab에서는 이 정보를 얻으려면 직접 계산해야 했죠. 개별 작업의 로그는 journald에 자동으로 쌓입니다.
백업 서비스의 모든 로그 (stdout/stderr 포함)
journalctl -u backup.service
어제 이후 로그만, 최신부터
journalctl -u backup.service --since yesterday -r
마지막 실행의 종료 코드 확인
systemctl status backup.service
실행 시간 통계가 궁금하면
journalctl -u backup.service -o json | jq -r '.MESSAGE' | grep -i finished
타임스탬프, 로그 로테이션, 종료 코드 추적이 전부 공짜로 따라옵니다.
실패 알림 — OnFailure 핸들러
"백업이 조용히 실패한 채 석 달이 지났다"는 사고를 막는 핵심 패턴입니다. 서비스 유닛에 OnFailure를 걸어두면, 해당 유닛이 실패 상태로 끝났을 때 지정한 유닛이 기동됩니다.
/etc/systemd/system/backup.service 에 추가
[Unit]
Description=Nightly backup job
OnFailure=notify-failure@%n.service
알림 핸들러는 템플릿 유닛으로 만들어 모든 작업에서 재사용합니다. %n은 실패한 유닛 이름으로 치환됩니다.
/etc/systemd/system/notify-failure@.service
[Unit]
Description=Send failure notification for %i
[Service]
Type=oneshot
ExecStart=/opt/scripts/notify-failure.sh %i
#!/usr/bin/env bash
/opt/scripts/notify-failure.sh — Slack 웹훅으로 실패 알림
set -euo pipefail
UNIT="$1"
HOST="$(hostname -f)"
실패 직전 로그 20줄을 첨부
LOG="$(journalctl -u "$UNIT" -n 20 --no-pager --output=cat)"
PAYLOAD="$(jq -n --arg t "[FAIL] $UNIT on $HOST" --arg l "$LOG" \
'{text: ($t + "\n" + $l)}')"
curl -sf -X POST -H 'Content-Type: application/json' \
-d "$PAYLOAD" "$SLACK_WEBHOOK_URL"
테스트도 간단합니다. 일부러 실패하는 서비스를 트리거해보면 됩니다.
sudo systemd-run --unit=failtest --property=OnFailure=notify-failure@failtest.service /bin/false
journalctl -u notify-failure@failtest.service
성공 알림이 필요하면 systemd 249부터 추가된 OnSuccess=도 같은 패턴으로 쓸 수 있습니다.
유저 타이머 — 루트 없이 내 작업 돌리기
개인 작업(dotfiles 백업, 메일 동기화, 개발 DB 정리)은 시스템 영역을 건드릴 필요 없이 유저 타이머로 돌립니다.
유닛 파일 위치
mkdir -p ~/.config/systemd/user
~/.config/systemd/user/mail-sync.service 와 mail-sync.timer 작성 후
systemctl --user daemon-reload
systemctl --user enable --now mail-sync.timer
systemctl --user list-timers
journalctl --user -u mail-sync.service
여기서 가장 많이 빠지는 함정이 lingering입니다. 유저 타이머는 기본적으로 해당 유저의 세션이 살아 있을 때만 돕니다. SSH 로그아웃과 함께 타이머도 멈춥니다. 로그인 여부와 무관하게 돌리려면 lingering을 켜야 합니다.
로그인 없이도 유저 systemd 인스턴스 유지
sudo loginctl enable-linger "$USER"
확인
loginctl show-user "$USER" --property=Linger
서버에서 "내 계정으로 돌아가는 개인 cron"을 대체할 때 반드시 기억해야 할 한 줄입니다.
cron에서 타이머로 — 마이그레이션 매핑 테이블
기존 crontab 항목을 OnCalendar로 옮길 때의 대응표입니다.
| cron 표현 | OnCalendar 표현 | 의미 |
| --- | --- | --- |
| `0 3 * * *` | `*-*-* 03:00:00` | 매일 03:00 |
| `*/15 * * * *` | `*:0/15` | 15분마다 |
| `0 * * * *` | `hourly` | 매시 정각 |
| `0 9 * * 1-5` | `Mon..Fri 09:00` | 평일 09:00 |
| `0 0 1 * *` | `*-*-01 00:00:00` | 매월 1일 자정 |
| `0 2 1 1,4,7,10 *` | `*-01,04,07,10-01 02:00` | 분기 첫날 02:00 |
| `@reboot` | `OnBootSec=1min` | 부팅 후 1분 |
| `@daily` | `daily` | 매일 자정 |
| `@weekly` | `weekly` | 매주 월요일 자정 |
같은 내용을 복사하기 쉬운 형태로도 남겨둡니다.
cron: 0 3 * * * → OnCalendar=*-*-* 03:00:00
cron: */15 * * * * → OnCalendar=*:0/15
cron: 0 * * * * → OnCalendar=hourly
cron: 0 9 * * 1-5 → OnCalendar=Mon..Fri 09:00
cron: 0 0 1 * * → OnCalendar=*-*-01 00:00:00
cron: 0 2 1 1,4,7,10 * → OnCalendar=*-01,04,07,10-01 02:00
cron: @reboot → OnBootSec=1min
cron: @daily → OnCalendar=daily
마이그레이션 절차는 다음 순서를 권합니다.
1. crontab -l로 전체 목록을 덤프하고 작업별로 분류합니다.
2. 각 작업에 대해 .service를 먼저 만들고 systemctl start로 수동 실행이 성공하는지 확인합니다. 이 단계에서 PATH/환경 문제를 전부 잡습니다.
3. .timer를 만들고 systemd-analyze calendar로 표현식을 검증합니다.
4. 타이머를 enable하고, 해당 crontab 줄은 주석 처리한 채 한 주기 병행 관찰합니다.
5. journalctl로 정상 동작을 확인한 뒤 crontab 줄을 삭제합니다.
일회성 작업은 systemd-run — transient 타이머
유닛 파일을 만들 것도 없는 일회성 작업은 systemd-run으로 즉석 타이머를 만듭니다. at 명령의 현대적 대체재입니다.
30분 뒤에 한 번 실행
systemd-run --on-active=30m /opt/scripts/cleanup.sh
오늘 23:00에 한 번 실행
systemd-run --on-calendar="23:00" /usr/bin/systemctl restart myapp
유저 권한으로, 2시간마다 반복
systemd-run --user --on-unit-active=2h --unit=poll-feed ~/bin/poll-feed.sh
만든 transient 타이머 확인과 취소
systemctl list-timers
systemctl stop run-r1a2b3c4.timer
transient 유닛은 재부팅하면 사라집니다. "지금부터 임시로"라는 의미에 정확히 부합하죠.
타임존 함정
스케줄러와 타임존의 조합은 늘 사고의 온상입니다. 알아둘 것 세 가지입니다.
첫째, OnCalendar는 기본적으로 시스템 로컬 타임존으로 해석됩니다. 서버마다 타임존이 다르면 같은 유닛 파일이 다른 시각에 돕니다. 명시적으로 타임존을 지정할 수 있습니다.
[Timer]
UTC로 고정 — 멀티 리전 서버에서 권장
OnCalendar=*-*-* 03:00:00 UTC
특정 지역 시간으로 지정 (tzdata 이름 사용)
OnCalendar=*-*-* 09:00:00 Asia/Seoul
둘째, DST(서머타임) 전환일에는 "존재하지 않는 시각"과 "두 번 존재하는 시각"이 생깁니다. 예컨대 유럽 서버에서 02:30 스케줄은 봄 전환일에 건너뛰어질 수 있습니다. 중요한 작업은 DST 영향이 없는 UTC 고정이 안전합니다.
셋째, Persistent 캐치업과 타임존 변경이 겹치면 직관과 다른 동작이 나올 수 있으니, 타임존을 바꾼 뒤에는 systemctl list-timers로 NEXT가 의도대로인지 반드시 확인하세요.
표현식이 어느 타임존으로 언제 도는지 즉시 검증
systemd-analyze calendar "*-*-* 03:00:00 UTC"
timedatectl # 시스템 타임존 확인
실전 레시피 모음
레시피 1 — 인증서 갱신 (certbot)
배포판 패키지가 제공하는 certbot.timer가 이미 모범 사례입니다. 직접 만들 때의 골격은 이렇습니다.
certbot-renew.timer
[Timer]
OnCalendar=*-*-* 00,12:00:00
RandomizedDelaySec=12h
Persistent=true
[Install]
WantedBy=timers.target
하루 두 번 시도 + 최대 12시간 무작위 지연은 Let's Encrypt가 권장하는 부하 분산 패턴입니다. 갱신 실패가 누적되면 인증서 만료라는 대형 사고가 되므로 OnFailure 알림은 필수입니다.
레시피 2 — DB 백업과 업로드 분리
백업 생성과 원격 업로드를 별도 유닛으로 나누고 의존성으로 묶으면, 실패 지점 파악이 쉬워집니다.
db-dump.service — 덤프 생성
[Service]
Type=oneshot
ExecStart=/opt/scripts/pg-dump.sh
덤프 성공 시에만 업로드 서비스 기동
ExecStartPost=/usr/bin/systemctl start db-upload.service
레시피 3 — 야간 배치, 리소스 제한과 함께
nightly-batch.service
[Service]
Type=oneshot
ExecStart=/opt/batch/run-nightly.sh
CPUQuota=50%
MemoryMax=2G
IOSchedulingClass=idle
4시간 넘게 걸리면 강제 종료 후 실패 처리 → OnFailure 알림 발동
TimeoutStartSec=4h
배치가 폭주해도 프로덕션 서비스의 CPU/메모리/IO를 침범하지 못하게 cgroup으로 격리하는 구성입니다.
안티패턴 — 이렇게는 쓰지 마세요
1. **서비스 유닛을 enable하는 것.** 타이머 트리거 작업인데 서비스 자체를 enable하면 부팅 때마다 실행됩니다. enable은 .timer에만.
2. **Type=simple로 장시간 배치를 돌리는 것.** oneshot이 아니면 systemd가 "시작됨"을 즉시 성공으로 간주해 실패 감지가 무뎌집니다.
3. **타이머 안에서 셸 한 줄로 모든 걸 하는 것.** ExecStart에 bash -c 한 줄짜리 파이프라인을 욱여넣으면 cron 시절의 가독성 문제가 그대로 재현됩니다. 스크립트 파일로 분리하세요.
4. **Persistent=true 남발.** 부팅 직후 즉시 실행되어도 안전한 작업에만 거세요. 네트워크가 필요한 작업이라면 After=network-online.target을 서비스에 함께 명시해야 합니다.
5. **AccuracySec 기본값(1분)을 모른 채 정밀 스케줄을 기대하는 것.**
6. **유저 타이머에 lingering을 빼먹는 것.** SSH 끊자마자 타이머가 죽습니다.
7. **모니터링 없이 이관만 하는 것.** 타이머로 옮기는 가치의 절반은 OnFailure와 journald에서 나옵니다. 알림 핸들러 없는 마이그레이션은 반쪽짜리입니다.
비판적 시각 — 그래도 cron이 맞는 경우
공정하게 반대편 논거도 정리합니다. HN 댓글란에서 설득력 있었던 주장들입니다.
- **이식성.** crontab은 BSD, macOS, 컨테이너 안 어디서나 같습니다. systemd 없는 환경(alpine 기반 컨테이너 등)이 섞인 조직이라면 cron 통일이 단순할 수 있습니다.
- **한 줄의 미학.** 정말 단순한 작업 하나에 파일 두 개 + 데몬 리로드는 과하다는 감각은 정당합니다. 다만 systemd-run 한 줄로 절충 가능합니다.
- **학습 비용.** 팀 전체가 cron 문법에 익숙하다면 전환 비용이 듭니다. 반론은 "AI 에이전트에게 유닛 파일 생성을 맡기면 된다"가 되겠지만, 리뷰할 수 있는 지식은 여전히 사람에게 필요합니다.
- **분산 스케줄링은 둘 다 못 한다.** 여러 노드에 걸친 작업 오케스트레이션은 cron도 타이머도 답이 아닙니다. 그 영역은 Kubernetes CronJob이나 워크플로 엔진의 몫입니다.
요컨대 단일 호스트의 정기 작업이라면 타이머가 거의 모든 면에서 우월하고, 이식성이 지배적 요구사항일 때만 cron이 남는다는 것이 합리적인 결론입니다.
마치며
cron에서 systemd 타이머로의 전환은 "스케줄러 교체"라기보다 "정기 작업을 일급 시민으로 승격"시키는 일에 가깝습니다. 로그는 journald로, 실패는 OnFailure로, 의존성은 유닛 그래프로, 리소스는 cgroup으로 — 이미 시스템에 있는 인프라에 정기 작업을 편입시키는 것이죠.
오늘 당장 할 수 있는 첫걸음을 제안합니다. crontab -l을 열고, 가장 중요한 작업 하나만 골라 .service + .timer 페어로 옮겨보세요. systemd-analyze calendar로 표현식을 검증하고, OnFailure 알림까지 붙이면 끝입니다. 한 번 해보면 나머지를 옮기는 건 시간문제일 겁니다.
참고 자료
- You don't love systemd timers enough (원문): https://blog.tjll.net/you-dont-love-systemd-timers-enough/
- Hacker News 토론: https://news.ycombinator.com/
- systemd.timer 공식 매뉴얼: https://www.freedesktop.org/software/systemd/man/latest/systemd.timer.html
- systemd.time — 캘린더 이벤트 문법: https://www.freedesktop.org/software/systemd/man/latest/systemd.time.html
- systemd.service 공식 매뉴얼: https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html
- systemd-run 매뉴얼 (transient 유닛): https://www.freedesktop.org/software/systemd/man/latest/systemd-run.html
- Arch Wiki — systemd/Timers: https://wiki.archlinux.org/title/Systemd/Timers
- loginctl 매뉴얼 (lingering): https://www.freedesktop.org/software/systemd/man/latest/loginctl.html
- systemd.exec — 리소스 제어 옵션: https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html
- GeekNews: https://news.hada.io/
현재 단락 (1/235)
최근 Hacker News 프런트페이지에 "You don't love systemd timers enough"라는 글이 올라와 수백 개의 댓글이 달리며 화제가 됐습니다. 제목부터 ...