시스템 · 서버핵심 · 22분 읽기

예약 실행과 시간: cron·systemd timer·NTP·chrony

예약 시각과 실행 환경, 작업의 성공·중복·누락을 구분하고, 시간 동기화가 로그와 예약 작업에 미치는 영향을 설명한다.

개념부터 찾아보기

정의·역할·동작 원리를 독립 페이지에서 확인하세요. 본문의 밑줄 용어에도 설명이 있습니다.

이 노트에서 설명할 수 있게 되는 것

  1. cron과 timer가 프로세스를 시작하고 결과를 남기는 과정을 구분한다.
  2. 시각·환경·중복·누락 조건을 포함한 작업 단위를 설계한다.
  3. NTP의 시각 차이 계산과 chrony의 동기화 상태를 읽는다.

01예약 시각·실행 시작·성공은 다른 상태다

  • 예약 시스템은 정해진 조건이 충족되면 명령이나 서비스를 시작한다. 예약이 등록되었다는 사실, 데몬이 동작한다는 사실, 작업이 시작했다는 기록, 작업이 성공한 결과는 각각 별개다.
  • 로그에 명령이 찍혀 있어도 내부 명령이 권한 오류로 실패했거나 출력 파일을 만들지 못했을 수 있다.
  • 주기 작업을 하나의 프로그램처럼 설계하면 입력, 작업 계정, 환경, 종료 상태, 결과물과 소요 시간을 구분할 수 있다.
  • 정상 종료뿐 아니라 실행 누락, 중복, 지나친 지연도 운영 상태다.
    • 예를 들어 백업 가 종료 상태 0을 반환해도 복원 가능한 백업인지 확인하는 시험은 별도의 결과로 남긴다.

02벽시계·시간대·경과 시간을 구분하기

  • 벽시계는 날짜와 시각을 나타내며 인증서 유효 기간, 로그 시각, 매일 특정 시각의 일정에 사용한다.
  • 시간대는 같은 순간을 지역 시각으로 표현하는 규칙이다.
    • 장비 모두가 같은 시간대를 표시해야만 동기화된 것은 아니다.
  • 같은 실제 시각을 유지하고 UTC 또는 시간대 정보를 함께 기록하면 서로 다른 표시를 비교할 수 있다.
  • 경과 시간은 시작부터 얼마가 지났는지 측정하는 값이다.
  • 벽시계를 조정하면 단순히 두 벽시각을 뺀 시간은 잘못될 수 있으므로 프로그램의 기간 측정은 적절한 단조 시계를 사용한다.
  • 예약 작업의 달력 조건과 부팅 후 몇 분 같은 상대 조건을 나누는 이유도 이 차이 때문이다.
  • 로그를 합칠 때는 발생 시각, 수신 시각, 표시 시각을 섞지 않는다.

03NTP의 네 시각으로 지연과 오차 계산하기

  • 는 클라이언트 송신 t1, 서버 수신 t2, 서버 송신 t3, 클라이언트 수신 t4를 사용해 서버가 클라이언트보다 얼마나 앞서 있는지와 왕복 지연을 추정한다.
  • 오차 θ=((t2−t1)+(t3−t4))/2, 지연 δ=(t4−t1)−(t3−t2)다.
  • 서버 안의 처리 시간을 왕복 시간에서 빼고 양방향 지연이 비슷하다는 가정으로 오차를 추정한다.
  • 같은 기준의 밀리초 값으로 t1=1000, t2=1015, t3=1017, t4=1012라면 θ=10ms, δ=10ms다.
  • 클라이언트에서 12ms가 흘렀고 서버 처리에 2ms가 쓰였으며 서버 시계가 10ms 앞선 예다.
    • 경로의 비대칭 지연은 오차 추정에 영향을 준다.
    • 따라서 단일 응답만으로 완벽한 시각을 얻는 것이 아니라 여러 측정과 소스 선택을 이용한다.
  1. 클라이언트가 요청을 보내며 자신의 시계로 t1을 기록한다. 예시에서는 같은 단위인 밀리초 값 t1=1000을 사용한다.
  2. 서버가 자신의 시계로 수신 t2=1015와 응답 송신 t3=1017을 기록한다. 서버에서 응답을 준비하는 데 2ms가 걸린 예다.
  3. 클라이언트가 자신의 시계로 수신 t4=1012를 기록한다. 클라이언트 기준 왕복 경과 시간은 t4−t1=12ms다.
  4. 서버 처리 시간을 제외한 δ는 10ms이고 θ는 10ms다. 왕복 경로 지연이 비슷하다는 가정에서 서버 시계가 클라이언트보다 10ms 앞선 것으로 추정한다.
  5. 단일 응답에는 네트워크 지연과 비대칭의 영향이 남는다. 여러 측정과 소스 선택을 통해 시계를 조정할 근거를 얻는다.
기호시각을 기록한 주체이벤트
t1클라이언트요청 송신
t2서버요청 수신
t3서버응답 송신
t4클라이언트응답 수신
원리 심화

04NTP 추정치에 남는 경로 비대칭과 시계 품질

  • t1·t4는 클라이언트 시계, t2·t3은 서버 시계로 기록된다. 네 숫자를 한 장비의 연속 시각처럼 정렬하면 앞선 서버 시계 때문에 수신 시각이 더 작게 보이는 현상을 오해할 수 있다.
  • δ는 클라이언트에서 본 전체 왕복 시간에서 서버 내부 처리 시간을 뺀 값이다. 그 결과는 왕복 네트워크 지연이며 어느 방향이 얼마나 지연됐는지 직접 나누어 주지는 않는다.
  • 왕로 지연을 d1, 복로 지연을 d2, 실제 서버 시계 차이를 θ0라 하면 단순 추정 θ에는 (d1−d2)/2가 섞인다. 두 방향 지연이 같다는 가정이 깨지면 왕복 측정만으로 이를 모두 제거할 수 없다.
  • 시간 동기화 구현은 여러 표본의 지연·흔들림과 여러 소스를 평가하여 시계 조정에 쓸 근거를 고른다. 단 한 번 작은 offset이 나온 사실과 안정적인 동기화는 다르다.
  • 의 offset·frequency·root delay·root dispersion은 서로 다른 관찰값이다. 이 낮다는 이유만으로 네트워크 지연이나 시계 오차가 항상 더 작다고 판정하지 않는다.
예제로 추적

05왕로 8ms·복로 2ms가 만드는 3ms 추정 편향

  • 서버 시계는 실제로 클라이언트보다 10ms 앞서 있다. 왕로 지연은 8ms, 서버 처리는 2ms, 복로 지연은 2ms이며 이 동안 시계 속도 차이는 무시한다.
  • 클라이언트 송신 t1=1000ms라면 서버 수신 t2=1018ms, 서버 송신 t3=1020ms, 클라이언트 수신 t4=1012ms가 된다. 서버 두 시각에는 앞선 10ms가 포함된다.
  • δ=(1012−1000)−(1020−1018)=12−2=10ms다. 이는 실제 왕로 8ms와 복로 2ms의 합과 일치한다.
  • θ=((1018−1000)+(1020−1012))/2=(18+8)/2=13ms다. 실제 차이 10ms보다 3ms 크게 추정한다.
  • 편향 3ms는 (8−2)/2와 같다. 네트워크 지연의 합을 정확히 구한 상황에서도 시계 차이 추정은 틀릴 수 있으므로 작은 왕복 지연과 경로 대칭성을 혼동하지 않는다.
값설명결과
t1클라이언트 송신1000ms
t2서버 수신1018ms
t3서버 송신1020ms
t4클라이언트 수신1012ms
θ / δ추정 offset / 왕복 지연13ms / 10ms
검증·예외

06예약 조건·실행 지연·동기화 오류의 증거 연결

  • Cronie의 0 9 1 * 1은 일·요일이 모두 제한되어 매월 1일 또는 월요일 09시에 해당한다. 1일이 아닌 월요일에도 실행되므로 매월 첫 월요일이라는 의도를 표현한 것이 아니다.
  • */20 분은 매시 00·20·40분을 고른다. 09:00 작업이 09:25까지 걸렸다면 09:20 예약과 겹칠 수 있으며 이전 종료 후 20분이라는 간격으로 해석하지 않는다.
  • 중복 방지를 위한 nonblocking 잠금 획득 실패는 내부 작업 실패와 별도로 기록한다. 작업이 시작되지 않았는데 빈 결과를 정상 완료로 세면 실제 처리 누락이 숨겨진다.
  • 시작 02:15, 끝 02:14처럼 보이는 로그는 시계 조정·다른 시간대·수집 순서 차이도 조사해야 한다. 작업 duration은 적절한 단조 시계로 측정해 벽시각의 변화와 구분한다.
  • 가 실행 중인데도 소스가 선택되지 않으면 sources와 의 선택 상태·도달성·최근 측정 정보를 함께 읽는다. 예약 누락을 하나의 탓으로 결론내리기 전에 timer/의 실제 기동 기록도 대조한다.

07chronyd와 chronyc의 역할

  • 는 시간 소스의 측정값을 이용하여 시계를 관리하는 데몬이고, 는 상태를 조회하거나 관리하는 클라이언트다.
  • 서버 통신에는 일반적으로 123을 사용하며 의 관리 통로와 구분한다.
  • 시계를 조금씩 빠르게 또는 느리게 보정하는 는 시간을 갑자기 뛰게 하는 과 다르다.
  • 큰 은 로그 순서나 시간에 민감한 프로그램에 영향을 줄 수 있다.
  • 에서는 기준 소스와 최근 기준 시각, 시스템 시각 차이, 동기화 상태를 읽고 sources -v에서는 선택된 소스와 도달성을 읽는다.
  • ^는 서버, *는 현재 선택된 소스, ?는 아직 선택할 수 없는 상태를 나타낼 수 있다.
  • 은 기준 시계와의 계층 관계이지 정확도를 보장하는 점수는 아니다.
  • 데몬이 실행 중인 것과 외부 소스에 실제 동기화된 것은 구분한다.
bash
chronyc tracking
chronyc sources -v
timedatectl status

시간 상태를 바꾸지 않는 조회 예시. 실제 시간 서비스에 따라 출력과 동기화 상태를 함께 해석한다.

LEARN THROUGH PRACTICE

시간 서버 설정과 클라이언트의 동기화 상태 대조하기

상위 시간원, 내부 제공 범위, 클라이언트의 ·offset·지연 지표를 연결해 시간 동기화의 상태를 읽는다.

실습 구성과 전제

  • 서버·클라이언트 설정과 Cisco 장비 상태 화면을 비교한다. 정지 화면의 시각이 서로 같다는 가정은 하지 않는다.
  • 서버와 클라이언트가 연결된 허용 실습망을 가정한다. 실제 시계를 변경하는 명령은 실행하지 않고 상태 조회로 해석한다.
  1. 상위 동기화와 내부 서비스 제공을 구분한다

    • 첫 설정의 pool은 상위 시간원을 선택하고 iburst는 초기 측정 자료를 빠르게 얻도록 요청을 묶어 보낸다. allow는 지정한 네트워크에서 오는 클라이언트 요청을 허용하는 설정이다.
    • makestep 1.0 3은 초기 세 번의 시계 갱신 동안 오차가 1초보다 크면 을 허용하는 조건이다. 3초마다 시계를 강제로 바꾸라는 뜻이 아니다.
    ntp · 실습·개념 참고 화면 1원본 크기로 보기 ↗
    • pool 뒤 iburst가 붙고 driftfile, makestep 1.0 3, rtcsync 행이 보인다.
    • 별도의 allow 대역 설정이 있어 상위 시간 동기화와 내부 제공 범위를 나누어 읽을 수 있다.
    확인 기준

    allow만으로 네트워크 방화벽이나 서버의 상위 시간원이 정상이라고 결론내리지 않는다. 시계 은 예약 작업·로그 시각에 영향을 줄 수 있다.

  2. 클라이언트가 선택한 시간원을 확인한다

    • 두 번째 설정은 pool 대신 특정 내부 서버를 server 지시어로 지정한다. 서버의 주소를 설정한 사실과 실제 응답을 받아 선택한 상태는 별개다.
    • 클라이언트에서는 sources와 으로 현재 선택된 원천과 동기화 정보를 본다. 는 동작하는 데몬이고 는 그 상태를 조회·관리하는 클라이언트다.
    bash
    chronyc sources -v
    chronyc tracking

    가 동작하는 클라이언트에서 시간원과 추정 상태를 조회한다.

    ntp · 실습·개념 참고 화면 2원본 크기로 보기 ↗
    • 기존 pool 행이 주석 처리되어 있다.
    • 내부 NTP 서버 하나를 server ... iburst로 지정한 행이 보인다.
    확인 기준

    출력에서 선택된 원천 표시와 도달 상태를 확인한다. 설정 파일만으로 동기화 성공을 말하지 않는다.

  3. 동기화 표시와 시간 품질 지표를 함께 읽는다

    • Cisco 화면은 clock is synchronized와 11을 표시한다. 은 기준 시계로부터의 시간 계층이며 IP 라우터 홉 수나 오차 밀리초 값이 아니다.
    • offset 약 0.5635ms, root delay 약 23.93ms, root dispersion 약 3941.70ms를 구별한다. 작은 offset 하나만으로 절대 시각 정확도를 보장할 수 없고 상위 시간원의 품질과 불확실성도 함께 봐야 한다.
    text
    show clock
    show ntp status
    show ntp associations

    지원되는 계열 실습 장비의 상태 조회 명령이다.

    ntp · 명령·상태 출력 7원본 크기로 보기 ↗
    • show ntp status는 synchronized와 stratum 11 및 참조 서버를 표시한다.
    • offset, root delay, root dispersion이 서로 다른 밀리초 값으로 나열되고 poll interval도 별도로 보인다.
    확인 기준

    동기화됨은 현재 선택한 시간원과 동기화 관계가 있다는 상태다. 조직의 허용 오차나 믿을 수 있는 기준 시각을 만족하는지는 별도 기준으로 판단한다.

실습에서 확인한 동작 원리

  • 상위 시간원 선택, 내부 제공 허용, 클라이언트의 실제 동기화는 별도 단계다.
  • 동기화 상태··offset·delay·dispersion을 함께 읽어야 로그와 예약 작업의 시간 신뢰도를 설명할 수 있다.

설정·출력 추가로 확인하기 5장

아래 화면을 펼쳐 위 실습의 설정값, 명령과 확인 기준을 비교해 보세요. 각 묶음은 별도 실습 기록입니다.

실습 화면 묶음 01 5장
ntp · 실습·개념 참고 화면 3원본 크기로 보기 ↗
  • 문서 문맥에 삽입된 원본 실습·개념 참고 화면이다. 예약 실행과 시간 학습 내용과 함께 당시 구성·설정·관찰 결과를 비교할 수 있다.
ntp · 실습·개념 참고 화면 4원본 크기로 보기 ↗
  • 문서 문맥에 삽입된 원본 실습·개념 참고 화면이다. 예약 실행과 시간 학습 내용과 함께 당시 구성·설정·관찰 결과를 비교할 수 있다.
ntp · 실습·개념 참고 화면 5원본 크기로 보기 ↗
  • 문서 문맥에 삽입된 원본 실습·개념 참고 화면이다. 예약 실행과 시간 학습 내용과 함께 당시 구성·설정·관찰 결과를 비교할 수 있다.
ntp · 실습·개념 참고 화면 6원본 크기로 보기 ↗
  • 문서 문맥에 삽입된 원본 실습·개념 참고 화면이다. 예약 실행과 시간 학습 내용과 함께 당시 구성·설정·관찰 결과를 비교할 수 있다.
ntp · 실습·개념 참고 화면 8원본 크기로 보기 ↗
  • 문서 문맥에 삽입된 원본 실습·개념 참고 화면이다. 예약 실행과 시간 학습 내용과 함께 당시 구성·설정·관찰 결과를 비교할 수 있다.
동작·명령 참고 문서

08cron 표현과 사용자별·시스템별 형식

  • 일반적인 의 시간 필드는 분, 시, 일, 월, 요일 순서다.
  • 15 2 * * *는 해당 일정의 시간대 기준 매일 02:15를 뜻한다.
  • 사용자 은 그 뒤에 명령이 오고, /etc/이나 /etc/.d 파일 형식에는 실행 사용자 필드가 추가된다. 사용자 에 사용자 이름을 한 칸 더 넣으면 그 이름을 명령의 일부로 해석하는 문제가 생긴다.
  • 쉼표는 값 목록, 하이픈은 범위, 슬래시 간격은 해당 필드의 범위 안에서 적용한다.
  • */15 분은 00·15·30·45분이며 직전 실행 종료 후 15분이라는 뜻은 아니다.
  • Cronie 계열에서는 일과 요일을 모두 제한하면 둘 중 하나가 맞는 날에 실행되는 규칙이 있어 “AND 조건”으로 오해하기 쉽다.
  • 구현별 문법과 시간대·일광절약시간 처리는 사용하는 문서로 확인한다.
bash
# 사용자 crontab의 작업 줄
15 2 * * * /usr/local/libexec/study-check

# /etc/cron.d/study-check의 작업 줄
15 2 * * * study /usr/local/libexec/study-check

두 줄은 서로 다른 파일 형식의 비교다. 같은 작업을 중복 등록하는 예시가 아니다.

09수동 실행과 예약 실행의 환경 차이

  • 터미널에서 되던 스크립트가 에서 실패하면 작업 디렉터리, PATH, 셸, 사용자 권한과 필요한 환경이 같은지 비교한다.
    • 은 사용자의 현재 터미널 세션을 복제하지 않는다.
  • 실행 파일 경로와 입력·출력 경로를 명확히 하고, 프로그램이 요구하는 작업 디렉터리도 정한다. 로그 파일과 잠금 파일에 대한 쓰기 권한 역시 해당 작업 계정에 있어야 한다.
  • SHELL과 PATH를 명시할 수 있지만 비밀번호나 토큰을 에 직접 쓰지 않는다.
  • 기본 출력 메일은 메일 전송 환경에 의존하므로 성공 기록을 대신하지 못한다.
  • 주기 로그를 파일로 남기면 보관·회전과 디스크 용량도 함께 설계한다.
  • 설정 변경 후에는 수동으로 같은 계정·환경을 재현한 시험과 실제 예약 실행 결과를 구분해서 기록한다.

10종료 상태를 보존하는 작업 wrapper

  • wrapper는 시작, 성공 또는 실패, 종료 상태를 일정한 형식으로 남기는 바깥 프로그램이다.
  • 아래 예시는 읽기 전용 조회 명령을 감싸는 구조다.
  • 실패 분기에서 $?를 즉시 저장해야 이후 logger 등의 성공 상태로 원래 오류를 덮어쓰지 않는다.
  • 실제 작업에서는 처리 대상 수와 결과 파일, 소요 시간 같은 업무 지표도 함께 기록할 수 있다.
  • 프로그램이 일부만 처리하고도 성공을 반환한다면 wrapper만으로 완전한 성공을 판단할 수 없다.
    • 내부 명령의 실패 전달과 완료 기준을 먼저 정의한다.
  • 반복 실행되는 작업은 이미 처리한 항목의 중복 효과를 줄이고, 중간 실패 후 어느 지점부터 다시 시작할지 정해야 한다.
  • 로그의 성공 문자열과 결과물의 실제 상태를 연결하는 것이 목적이다.
bash
#!/bin/bash
JOB_NAME=study-check
logger -t "$JOB_NAME" -- "start"
if /usr/bin/stat /etc/os-release; then
    logger -t "$JOB_NAME" -- "success"
else
    rc=$?
    logger -p user.err -t "$JOB_NAME" -- "failed rc=$rc"
    exit "$rc"
fi

stat 조회를 감싼 Bash 예시. 실제 작업의 성공 판정은 해당 명령과 결과물의 의미에 맞게 정한다.

11중복 실행과 누락 실행을 별도로 설계하기

  • 10분마다 시작하는 작업이 15분 걸리면 다음 실행과 겹칠 수 있다.
  • 같은 잠금은 같은 잠금 파일을 사용하는 작업들이 동시에 실행되는 것을 제한한다.
    • -n처럼 기다리지 않는 방식이면 이미 실행 중일 때 새 실행이 건너뛰어질 수 있으므로 그 상태를 성공과 구분해 기록한다.
  • 잠금은 하나의 서버·공유 잠금 조건에서 의미가 있으며 여러 서버의 분산 작업을 자동으로 조정하지 않는다.
  • 일반 은 시스템이 꺼져 있던 동안의 모든 일정을 저장해 재생하는 작업 큐가 아니다.
  • 누락 보완이 필요하면 anacron이나 timer의 보완 기능과 업무 자체의 처리 기준을 검토한다.
  • 중복 방지와 누락 보완은 서로 다른 문제이며 둘 다 결과 데이터의 일관성을 자동으로 보장하지 않는다.

12systemd service는 작업, timer는 시작 조건

  • service에는 실행 계정·명령·환경·제한을 두고 timer에는 언제 해당 unit을 활성화할지를 둔다.
  • 같은 기본 이름의 timer는 기본적으로 해당 service를 시작한다.
  • 은 시작 작업의 완료를 기다리는 형태이며, 반복 실행할 작업에 RemainAfterExit=yes를 무심코 넣으면 완료 후에도 active로 남아 다음 timer가 새 작업을 시작하지 않을 수 있다.
  • 는 달력 시각을, OnBootSec나 OnUnitInactiveSec는 기준 이벤트 이후의 상대 시간을 표현한다.
  • timer가 만료될 때 대상 service가 이미 active이면 별도 인스턴스를 자동 생성하여 겹쳐 실행하지 않는다.
  • 작업의 결과와 오류는 service를 조회하고, 다음·이전 예정 시각은 timer를 조회하는 식으로 역할을 나눠 읽는다.
  1. timer가 달력 시각이나 기준 이벤트를 바탕으로 다음 활성화 시점을 계산한다. 예시의 는 매일 02:15 조건이며 실제 시각에는 지연 설정도 관여한다.
  2. 조건이 도달하면 연결된 service의 시작을 요청한다. service가 이미 active라면 같은 unit의 별도 인스턴스를 겹쳐 시작하지 않는다.
  3. 비활성 service가 시작되면 지정한 User·환경·제한으로 ExecStart 명령을 실행한다. 은 명령의 완료를 기다린다.
  4. 명령의 종료 결과가 service 상태에 반영된다. RemainAfterExit를 사용하지 않는 성공한 oneshot은 완료 후 inactive로 돌아가 다음 실행 대상이 될 수 있다.
  5. timer의 다음 시점 계산과 service의 실제 성공·실패는 별개로 기록된다. 의 놓친 시각 보완도 매 누락 횟수를 모두 재생하는 방식은 아니다.
ini
# study-check.service
[Unit]
Description=Study read-only scheduled check
[Service]
Type=oneshot
User=study
ExecStart=/usr/local/libexec/study-check
NoNewPrivileges=true
PrivateTmp=true

# study-check.timer
[Unit]
Description=Schedule study check
[Timer]
OnCalendar=*-*-* 02:15:00
Persistent=true
RandomizedDelaySec=60
[Install]
WantedBy=timers.target

서로 다른 두 unit 파일의 내용이다. study 계정과 wrapper가 준비되고 접근권한이 맞는 시스템 timer 예시.

13Persistent·지연·로그로 실행 생애를 추적하기

  • timer의 =true는 비활성 기간에 실행 시점을 놓쳤을 때 다시 활성화하면서 보완 실행할 수 있게 한다.
    • 놓친 모든 횟수를 개별적으로 전부 재생하는 의미는 아니다.
  • 는 여러 장비의 같은 작업이 한꺼번에 시작되는 것을 줄이는 지연이며, 실제 시작 시각에는 timer 정확도 설정과 시스템 부하도 영향을 준다.
  • 을 해석한 다음 timer의 상태와 연결된 service의 실제 종료 상태를 대조한다.
  • 로그는 RHEL의 /var/log/, 계열의 /var/log/ 또는 journal 등에 나타날 수 있으며 실제 위치는 로깅 구성에 따라 달라진다.
  • 시작 기록만 보지 않고 성공·실패·duration·예상 heartbeat 누락을 연결해야 주기 작업의 상태를 설명할 수 있다.
bash
systemd-analyze calendar "*-*-* 02:15:00"
systemctl list-timers --all
systemctl show study-check.service -p Result -p ExecMainStatus
journalctl -u study-check.service -u study-check.timer

예약 표현과 실제 service 결과를 구분하여 조회한다. 로그에는 계정·경로 등이 포함될 수 있어 공개 시 필요한 부분만 사용한다.

학습 확인

이해했는지 확인하기

  • 같은 작업의 예약 등록·시작·종료·업무 결과를 각각 확인한다.
  • 작업 계정의 환경과 중복·누락 처리 방법을 설명한다.
  • 시간대와 동기화 상태, 로그 발생·수신 시각을 구분한다.

함께 확인할 공식 자료