리눅스 크론이 돈다고 찍히는데 실제로는 안 돌 때

세 줄 요약
증상: syslog 에는 크론 실행 줄이 매일 찍히는데 결과물이 없습니다.
원인: 쓸 권한 없는 곳으로 로그를 넘겨 명령이 시작도 못 했거나, cron.d 파일 이름에 점이 있어 무시됐거나, 스스로 지워진다던 크론이 남아 있었습니다.
해결: 로그 파일이 실제로 생겼는지 보고, 파일 이름을 고치고, 결과물의 마지막 날짜를 따로 감시합니다.

크론의 실행 기록은 "명령을 시작했다"는 뜻일 뿐 "끝까지 돌았다"는 뜻이 아닙니다. 이 차이 때문에 두 달 가까이 아무 일도 안 한 크론을 몰랐습니다. 실제로 겪은 세 가지를 적습니다.

돈다고 찍히는데 안 도는 세 가지 모습

경우 보인 것 실제
가 syslog 에 매일 실행 줄 57일 동안 수집 0회, 로그 파일 자체가 없음
나 cron.d 파일을 고쳤음 그 작업이 돌지 않음
다 "끝나면 스스로 지워진다"고 함 임시 크론 둘이 종료일이 지나도 매일 돎

가의 경우 syslog 에는 아래 모양의 줄이 매일 있었습니다. 그 밖에 남은 흔적은 메일 서버가 없어 출력을 버렸다는 한 줄뿐이었습니다.

CRON[...]: (ubuntu) CMD (cd /opt/app && ./venv/bin/python collect.py >> /var/log/collect.log 2>&1)
CRON[...]: (CRON) info (No MTA installed, discarding output)

가. 리다이렉트에서 먼저 실패

일반 사용자(ubuntu)로 도는 크론이 root 소유인 /var/log 아래로 >> 리다이렉트를 걸어 두었습니다. 셸은 명령을 실행하기 전에 리다이렉트할 파일부터 엽니다. 파일을 만들 권한이 없으니 거기서 실패하고, 파이썬은 한 번도 실행되지 않았습니다. 실패가 명령 앞에서 일어나 아무 출력도 남지 않았습니다.

나. 파일 이름의 점

/etc/cron.d 안의 파일은 이름에 점이 있으면 크론이 무시했습니다. .disabled, .bak_시각 처럼 붙인 파일은 내용이 맞아도 돌지 않습니다. 데비안 계열에서 이 폴더는 run-parts 이름 규칙을 따르는 것으로 알려져 있습니다.

다. 자기 종료는 약속일 뿐

"완료되면 스스로 크론을 지운다"는 것은 그 스크립트가 제대로 돈다는 전제 위에 있습니다. 스크립트가 죽거나 완료 조건에 끝내 닿지 못하면 크론은 남습니다.

실제로 하나는 8월 5일, 다른 하나는 9월 10일에 끝나야 했는데 9월 11일에 확인했을 때 둘 다 크론 파일이 남아 매일 돌고 있었습니다. 반대로 작업이 끝나지 않았는데 크론만 먼저 사라지는 경우도 생각할 수 있습니다. 어느 쪽이든 그 작업 혼자서는 알릴 방법이 없습니다.

세 경우 모두 "실행 기록이 있다"를 "잘 돌았다"로 읽은 것이 공통점입니다. 크론은 정해진 시각에 명령을 시작해 줄 뿐이고, 그 명령이 무엇을 했는지는 알려 주지 않습니다.

세 경우를 각각 이렇게 고쳤다

가. 사용자 크론의 로그는 그 사용자가 쓸 수 있는 폴더에 둡니다.

23 17 * * * ubuntu cd /opt/app && ./venv/bin/python collect.py >> /opt/app/logs/collect.log 2>&1

가의 경우 결정적 단서는 로그 파일이 아예 없다는 것이었습니다. 로그가 있는데 비어 있는 것과, 로그 파일 자체가 없는 것은 다른 신호입니다. 앞의 것은 명령이 돌았지만 할 말이 없었다는 뜻일 수 있고, 뒤의 것은 명령이 시작조차 못 했다는 뜻일 수 있습니다.

나. 쓸 파일은 점 없는 이름으로 두고, 끄려면 이름을 바꾸는 대신 다른 폴더로 옮기거나 줄을 주석 처리합니다.

ls /etc/cron.d/ | grep '\.'

다. 임시 크론은 등록부 파일에 한 줄(크론 이름, 완료 표시, 종료일)을 남기고, 작업과 따로 도는 감시 스크립트가 하루 두 번 읽게 했습니다. 감시자는 끝났는데 크론이 남음, 안 끝났는데 크론이 사라짐, 종료일 넘김, 진행 멈춤을 봅니다. 감시자 자신은 심장박동 파일을 남기고 다른 감시가 그 파일의 시각을 봅니다.

제대로 도는지 보는 법

  • 크론을 건 다음 날 로그 파일이 실제로 생겼는지 봅니다. 없으면 그것이 가장 강한 단서입니다.
  • syslog 에서 No MTA 줄이 같은 시각에 찍히는지 봅니다.
  • 실행 줄이 아니라 결과물로 판정합니다. DB 라면 마지막으로 들어온 날짜를 봅니다.
ls -l /opt/app/logs/
grep CRON /var/log/syslog | tail -n 20
sqlite3 /opt/app/data.sqlite3 "SELECT MAX(created_at) FROM rows;"

크론 로그가 있어도 끝부분을 안 보면 같은 실수를 합니다. 그 이야기는 로그로 상태를 판정하다 틀리는 경우에 적었습니다.

확인한 환경

항목 내용
운영체제 리눅스 서버(크론 사용자 ubuntu)
확인한 날짜 2026년 9월 11일(가, 다), 2026년 7월 25일(나)

관련 글

이 글의 내용은 2026년 10월 5일에 마지막으로 확인했습니다. 틀린 곳을 발견하시면 연락처로 알려 주세요.