SSD Nodes Learn 🎉 VPS $5.50/월부터
가이드 Matt Connor작성자 Matt Connor

cron 작업이 실행되지 않는 5가지 주요 원인 해결 방법

cron 작업이 의도대로 실행되지 않는 5가지 핵심 이유를 정리했습니다. PATH 환경 변수 설정, 퍼센트 기호 이스케이프, crontab 파일 위치, 메일로 유실되는 출력, 그리고 로그인 셸 의존성 문제를 확인하여 시스템 로그에서 원인을 정확히 파악하는 방법을 안내합니다.

cron 작업이 실행되지 않는 이유

"절대 실행되지 않는" cron 작업은 거의 항상 실행된 상태입니다. 해당 작업은 사용자의 셸이 아닌 환경에서 실행되었고, 시작 직후 실패했으며, 그 결과 메시지는 사용자가 확인하지 않는 곳으로 전송되었습니다. 거의 모든 보고 사례는 다음 5가지 원인으로 설명됩니다: 검색 경로(search path), 퍼센트 기호(%), 잘못된 crontab 파일, 메일로 전송된 출력, 그리고 로그인 세션을 요구하는 스크립트입니다.

cron은 crontab 파일을 읽어 정해진 일정에 따라 명령을 시작하는 데몬(백그라운드 서비스)입니다. cron은 사용자의 .bashrc를 읽지 않으며, 터미널을 열지 않고, 로그인 셸을 시작하지 않으며, 명령이 실패했을 때 사용자에게 알리지 않습니다. 아래의 모든 원인은 이 4가지 사실에서 비롯됩니다.

다음 순서대로 문제를 해결하십시오. 가장 먼저 모든 문제의 근간이 되는 질문부터 확인해야 합니다. cron이 실제로 작업을 실행했습니까? "cron이 작업을 시작조차 하지 않음"과 "작업이 시작되었으나 종료됨"은 공통점이 없는 서로 다른 문제이므로, 이 질문에 먼저 답하십시오.

cron이 실행되기는 했는가?

데몬의 유닛 이름은 배포판 계열에 따라 다릅니다. 두 가지를 모두 확인한 뒤 로그를 읽으십시오.

systemctl status cron
systemctl status crond
journalctl -u cron --since "2 hours ago"
journalctl -u crond --since "2 hours ago"

Debian과 Ubuntu는 유닛을 cron이라고 부릅니다. Fedora, Rocky, Alma는 crond라고 부릅니다. 특정 시스템에는 이 중 하나만 존재하므로, 두 명령 중 하나가 알 수 없는 유닛이라고 보고하는 것은 정상이며 오류가 아닙니다.

시스템이 기록한 항목을 직접 읽으십시오. 가이드에서 복사한 줄을 찾지 마십시오. cron 구현 방식과 로그 설정에 따라 문구가 다르기 때문입니다. 오직 두 가지만 확인하면 됩니다. 예약한 분에 항목이 존재하는지, 그리고 그 항목이 실행하려는 명령을 명시하고 있는지 확인하십시오. 명령이 명시된 항목이 있다면 cron은 제 역할을 다한 것이며, 실패 원인은 명령 내부에 있습니다. 항목이 전혀 없다면 cron에 예약이 등록되지 않은 것이며, 이는 아래의 3번 원인에 해당합니다.

일부 이미지에서는 cron 메시지를 저널 대신 rsyslog를 통해 파일로 보냅니다. /var/log에서 cron이나 syslog라는 이름의 파일을 찾은 뒤, 그 파일의 끝부분을 읽으십시오.

ls -l /var/log
sudo tail -n 50 /var/log/syslog

유닛과 로그가 모두 존재하지 않는다면 cron이 설치되지 않았을 수 있습니다. 최소 사양의 클라우드 이미지나 컨테이너에는 cron이 포함되지 않는 경우가 많습니다.

dpkg -l cron
rpm -q cronie
sudo apt install cron
sudo dnf install cronie
sudo systemctl enable --now cron

원인 1: cron에 PATH가 설정되지 않음

대화형 셸은 PATH/etc/profile, ~/.profile, ~/.bashrc 및 해당 파일들이 참조하는 모든 파일로부터 구성합니다. cron 작업은 이러한 파일을 실행하지 않습니다. cron은 자체적인 최소 환경에서 명령을 시작하므로, 표준 시스템 디렉터리 외부에 위치한 프로그램은 찾을 수 없습니다. /usr/local/bin, /opt 하위의 모든 항목, 언어 버전 관리자, Python 가상 환경 또는 Go 작업 공간 등이 이에 해당합니다. 작업은 첫 번째 줄에서 실패하며, 셸은 실행된 셸의 종류에 따라 "not found" 형태의 오류 메시지를 출력합니다.

작업에서 사용하는 모든 명령의 실제 경로를 찾으십시오.

command -v docker
command -v node
readlink -f "$(command -v node)"

그런 다음 해당 절대 경로를 작업에 직접 작성하거나, crontab 상단에 PATH를 한 번 설정하십시오.

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
0 3 * * * /usr/local/bin/mytool run

본인의 머신에서 echo "$PATH" 명령으로 해당 목록을 가져온 뒤, 대화형 세션에서만 존재하는 항목은 제거하십시오. 여기서 중요한 규칙은 cron이 이러한 할당 줄에서 변수를 확장하지 않는다는 점입니다. PATH=$PATH:/usr/local/bin$PATH:/usr/local/bin라는 문자열을 그대로 저장하므로, 작업은 사용할 수 없는 디렉터리만 포함된 검색 경로를 갖게 됩니다. 전체 목록을 명시적으로 작성하십시오.

버전 관리자는 경로 설정 이상의 작업이 필요합니다. nvm, pyenv, rbenv 및 asdf는 .bashrc에서 셸 함수나 shims 디렉터리를 설치하는데, cron 작업은 이 파일을 읽지 않습니다. 버전이 지정된 바이너리를 절대 경로로 호출하거나, 스크립트의 첫 번째 줄에서 관리자의 초기화 스크립트를 source 하십시오.

원인 2: 퍼센트 기호가 명령어를 종료함

crontab의 명령어 필드에서 %은 일반적인 문자가 아닙니다. 이스케이프 처리되지 않은 첫 번째 %은 명령어를 종료시킵니다. 그 뒤에 오는 모든 내용은 표준 입력으로 명령어에 전달되며, 이후 등장하는 각 %는 줄 바꿈으로 변환됩니다. 이는 프로그램에 짧은 입력을 전달하기 위한 실제 cron 기능이며, 날짜가 포함된 파일 이름이 crontab에서 흔히 발생하는 오류의 원인이기도 합니다.

0 3 * * * /usr/bin/tar -czf /srv/backups/site-$(date +%F).tar.gz /srv/site을 작성하면 tar는 서식화된 날짜를 인식하지 못합니다. cron은 첫 번째 %에서 줄을 자르므로, 셸은 미완성된 명령어 치환을 전달받고 나머지 줄은 표준 입력으로 처리됩니다. 모든 퍼센트 기호 앞에 백슬래시를 붙여 이스케이프 처리하십시오.

0 3 * * * /usr/bin/tar -czf /srv/backups/site-$(date +\%F).tar.gz /srv/site

두 계층이 해당 줄을 순서대로 읽습니다. \%는 cron 규칙이며, cron이 작업을 시작하기 전에 적용됩니다. $(date +\%F)명령어 치환이며, cron이 실행한 셸에 의해 나중에 적용됩니다. 어떤 계층이 어떤 문자를 처리하는지 이해하는 것이 핵심입니다.

더 안전한 습관은 crontab에 로직을 포함하지 않는 것입니다. 퍼센트 기호가 특별한 의미를 갖지 않는 스크립트 파일에 로직을 작성하십시오.

#!/bin/bash
set -euo pipefail
stamp="$(date +%F)"
tar -czf "/srv/backups/site-${stamp}.tar.gz" /srv/site

그러면 crontab 줄에는 경로와 리다이렉트만 남게 됩니다. 한눈에 읽을 수 있는 crontab이 디버깅하기에도 좋습니다.

원인 3: 어떤 crontab을 수정했습니까?

단일 crontab은 존재하지 않습니다. 소유자와 필드 개수가 서로 다른 여러 파일이 존재하며, 잘못된 파일에 작성된 작업은 실행되지 않습니다.

  • crontab -e는 명령을 실행하는 사용자의 crontab을 수정합니다. sudo crontab -e는 root의 crontab을 수정합니다. 같은 서버를 디버깅하는 두 사람이 서로 다른 파일을 보고 있는 경우가 흔합니다.
  • sudo crontab -l -u deploy은 다른 사용자의 crontab을 나열합니다. 작업을 실행해야 할 계정에 실제로 어떤 내용이 설치되었는지 확인하는 방법입니다.
  • /etc/crontab/etc/cron.d의 모든 파일은 일정과 명령 사이에 실행할 사용자라는 추가 필드를 하나 더 가집니다. 5개 필드로 구성된 사용자 crontab 라인을 /etc/cron.d에 붙여넣으면, 명령의 첫 단어가 사용자 이름으로 인식됩니다.
  • /etc/cron.d 내의 파일명은 영문자, 숫자, 밑줄, 하이픈으로만 구성되어야 합니다. backup.sh 또는 site.conf와 같은 이름의 파일은 이름 규칙 때문에 무시됩니다. backup으로 이름을 변경하고 로그를 다시 확인하십시오.
  • /etc/cron.d 내의 파일은 root가 소유해야 하며, 그룹이나 다른 사용자가 쓰기 권한을 가져서는 안 됩니다. ls -l /etc/cron.d는 이 두 가지 사실을 한 번에 보여줍니다.
  • /etc/cron.daily 및 그 하위 디렉터리에 배치된 스크립트도 동일한 이름 규칙을 따르며, 실행 비트가 설정되어 있어야 합니다. 실행 비트가 없으면 아무런 경고 없이 건너뜁니다.
  • /etc/cron.allow/etc/cron.deny은 누가 crontab을 설치할 수 있는지 결정합니다. 서버에 이 파일들이 존재한다면, 사용자가 crontab을 사용할 권한이 있다고 가정하기 전에 먼저 내용을 확인하십시오.

스풀 파일을 직접 수정하는 대신 crontab 명령을 사용하여 사용자 crontab을 설치하십시오. crontab은 설치 전에 파일 구문을 검사하기 때문입니다. 저장할 때 명령이 출력하는 메시지를 읽으십시오. 파일이 거부되면 이전 버전이 그대로 유지되며 변경 사항이 적용되지 않는데, 이는 cron이 작업을 무시하는 것처럼 보일 수 있습니다.

소유자는 권한도 결정합니다. root의 crontab에 등록된 작업은 root 소유의 파일을 생성하며, 이를 읽어야 하는 애플리케이션이 쓰기 작업을 수행하지 못할 수 있습니다. 일반 사용자의 crontab에 등록된 작업은 root 전용 디렉터리를 읽을 수 없습니다. 작업에 맞는 소유자를 지정하십시오. 애플리케이션 유지보수는 해당 애플리케이션의 계정으로 수행해야 하며, 이것이 WordPress wp-cron을 시스템 cron 작업으로 대체하기의 근거입니다. 작업이 생성하는 파일의 모드는 상속받은 umask에 의해 결정됩니다. 이는 셸의 umask와 다를 수 있으므로, 작업 결과물을 읽을 수 없는 경우 umask가 파일 권한을 설정하는 방법을 읽어보는 것이 좋습니다.

원인 4: 아무도 읽지 않는 메일로 출력이 전송됨

cron은 작업이 표준 출력(standard output)과 표준 에러(standard error)로 기록하는 모든 내용을 수집합니다. 작업이 조금이라도 내용을 출력하면, cron은 해당 텍스트를 로컬 메일 시스템으로 전달하며, 수신인은 crontab 소유자나 MAILTO에 지정된 계정이 됩니다. 최소한의 구성만 갖춘 VPS에는 보통 MTA(mail transfer agent)가 설치되어 있지 않으므로, 메일이 전달되지 않습니다. 에러는 잠시 발생했다가 사라져 버립니다. 이것이 바로 실패한 작업이 아무런 반응이 없는 것처럼 보이는 이유입니다.

대신 출력을 직접 관리하는 파일로 보내십시오.

0 3 * * * /usr/local/sbin/backup-site.sh >> /var/log/backup-site.log 2>&1

>>는 표준 출력을 파일에 추가(append)합니다. 2>&1은 표준 에러를 현재 표준 출력이 가리키는 곳으로 향하게 하므로, 반드시 리다이렉트 뒤에 위치해야 합니다. 반대로 2>&1 >> file와 같이 작성하면 표준 에러는 원래 목적지를 유지하게 되어, 정작 찾아야 할 에러 메시지는 파일에 기록되지 않습니다.

journal도 좋은 대안입니다. logger는 선택한 태그를 사용하여 syslog에 기록합니다.

0 3 * * * /usr/local/sbin/backup-site.sh 2>&1 | logger -t backup-site

journalctl -t backup-site으로 내용을 확인하십시오. 이렇게 하면 작업의 출력 결과가 cron 항목과 함께 기록되므로 시간 흐름을 파악하기 쉽습니다. 만약 서버에서 누가 어떤 명령을 실행했는지 기록이 필요하다면 이는 별도의 시스템 영역이며, 서버의 사용자 명령 감사하기에서 다룹니다.

crontab 상단에 MAILTO=""을 설정하면 그 아래 작업들의 메일 발송이 중단됩니다. MAILTO을 실제 메일 주소로 설정하는 것은 작동하는 MTA가 있을 때만 의미가 있으므로, 메일 기능에 의존하기 전에 서버에서 메일이 정상적으로 발송되는지 먼저 확인하십시오.

디버깅 시 한 가지 규칙은 > /dev/null 2>&1를 절대 추가하지 않는 것입니다. 이는 모든 crontab에서 가장 흔히 볼 수 있는 줄이지만, 유일한 증거를 버리는 행위입니다. 작업이 정상적으로 작동하게 된 후에 다시 추가해도 늦지 않습니다.

원인 5: 스크립트가 cron 환경에서 제공되지 않는 환경 변수를 가정함

명령어를 찾고 그 출력을 캡처한 뒤에도, 사용자의 세션이 기본적으로 제공하는 나머지 환경 요소들이 남아 있습니다.

  • 셸이 bash가 아닐 수 있습니다. ls -l /bin/sh으로 확인하십시오. Debian과 Ubuntu에서는 dash를 가리키므로, 이중 대괄호 테스트, 배열, source 등이 구문 오류로 실패합니다. 스크립트에 #!/bin/bash 줄을 추가하여 호출하거나, crontab 상단에 SHELL을 설정하십시오.
  • 작업 디렉터리가 현재 위치와 다릅니다. 모든 경로를 절대 경로로 사용하거나, 스크립트 첫 줄에서 cd를 사용하여 해당 디렉터리로 이동하십시오. 상대 경로는 "직접 실행하면 잘 되는데"라는 문제가 발생하는 가장 흔한 원인입니다.
  • 로케일이 사용자 세션과 다릅니다. 날짜나 숫자를 형식화하거나 텍스트를 정렬하는 모든 작업은 다른 LANG 환경에서 다른 결과를 출력할 수 있습니다. 이후 단계에서 해당 출력을 파싱한다면, 운에 맡기지 말고 스크립트 내에서 로케일을 직접 설정하십시오.
  • TTY(터미널)가 없습니다. 확인을 요청하거나, 편집기를 열거나, 진행률 표시줄을 그리는 명령어는 멈추거나 종료될 수 있습니다. 해당 도구가 제공하는 비대화형(non-interactive) 플래그를 추가하십시오.
  • SSH 에이전트가 없습니다. SSH_AUTH_SOCK이 cron 환경에 없으므로, 에이전트가 로드되어 있어 잘 작동하던 ssh이나 rsync 명령어가 인증에 실패하게 됩니다. 해당 작업 전용 키를 생성하고 작업 실행 사용자가 소유하도록 하십시오.
  • 사용자 세션 버스가 없으므로, cron 작업에서 systemctl --user를 호출하면 XDG_RUNTIME_DIR이 설정될 때까지 실패합니다. 이 경우 system unit을 사용하는 것이 더 나은 해결책입니다.

Fedora, Rocky, Alma에는 한 가지 의심 요소가 더 있습니다. SELinux가 cron 작업을 제한하므로, 파일 권한이 올바르게 보여도 예상치 못한 레이블이 지정된 경로에 접근하면 거부됩니다. sudo ausearch -m avc -ts recent로 거부 로그를 확인하고, 설정을 끄기 전에 서버를 위한 SELinux 기초를 읽어보십시오.

cron 환경을 확인하는 1분 진단법

cron의 환경 변수에 무엇이 포함되어 있는지 추측하지 말고 직접 확인하십시오. 모든 환경 변수를 출력하는 스크립트를 작성하고, 1분마다 실행되도록 예약한 뒤 잠시 기다렸다가 해당 파일을 읽어보면 됩니다.

cat > /home/deploy/cron-probe.sh <<'EOF'
#!/bin/bash
echo "=== probe ==="
date -Is
pwd
id
echo "SHELL=$SHELL"
echo "LANG=$LANG"
command -v node || echo "node is not on this PATH"
env | sort
EOF
chmod +x /home/deploy/cron-probe.sh

실제 작업이 실행되는 사용자의 crontab에 아래 한 줄을 추가하십시오. 이때 양쪽 경로 모두 절대 경로를 사용해야 합니다.

* * * * * /home/deploy/cron-probe.sh >> /home/deploy/cron-probe.log 2>&1

1분을 기다린 후 /home/deploy/cron-probe.log를 읽어보고, 본인의 셸에서 동일한 명령을 실행했을 때와 비교하십시오. PATH 라인, 작업 디렉터리, 로케일 설정만으로도 실패 원인을 파악할 수 있는 경우가 많습니다. 설정 시 다음 두 가지 사항에 유의하십시오. 퍼센트 기호(%)는 스크립트 내부에 위치하므로 cron의 규칙이 적용되지 않으며, 로그 경로는 해당 작업의 사용자가 쓰기 권한을 가진 곳이어야 합니다.

답을 얻은 즉시 해당 crontab 라인을 삭제하십시오. 1분마다 실행되며 파일에 내용을 추가하는 작업은 작은 디스크를 금방 채워버리며, 아무런 경고 없이 조용히 진행됩니다.

의도하신 스케줄이 맞습니까?

사용자 crontab 라인은 분, 시, 일, 월, 요일이라는 5개의 필드로 시작합니다. 이 중 두 필드는 사용자에게 혼란을 주는 방식으로 상호작용합니다.

일(day of month)과 요일(day of week)이 모두 제한되어 있고, 즉 둘 다 *가 아닐 경우, cron은 둘 중 하나라도 일치하면 작업을 실행합니다. 0 0 13 * 5는 "13일의 금요일"을 의미하지 않습니다. 이 설정은 매월 13일 자정과 매주 금요일 자정에 작업을 실행합니다. 특정 날짜를 지정하려면 두 필드 중 하나를 *으로 두고 스크립트 내부에서 다른 필드를 테스트하십시오.

cron은 시스템 시간대를 사용합니다. 많은 VPS 이미지는 UTC(협정 세계시)로 설정되어 있으므로, 03:00으로 예약한 작업은 UTC 기준 03:00에 실행되며, 이는 사용자의 오후 시간대일 수 있습니다. timedatectl은 현재 서버가 실제로 사용하는 시간대를 출력합니다. 본인의 노트북과 동일할 것이라고 가정하지 말고 직접 확인하십시오.

알아두어야 할 두 가지 스케줄 함정이 더 있습니다. @reboot은 cron 자체가 시작될 때 실행되는데, 이는 네트워크가 준비된 시점과는 다르므로 DNS나 원격 호스트가 필요한 작업은 부팅 시 실패하고 이후 수동 실행 시에는 성공할 수 있습니다. 또한, 이전 작업이 여전히 실행 중일 때 느린 작업이 다시 시작되는 것을 막을 방법은 없습니다. 작업을 락(lock)으로 감싸십시오.

*/5 * * * * /usr/bin/flock -n /tmp/backup-site.lock /usr/local/sbin/backup-site.sh >> /var/log/backup-site.log 2>&1

flock -n는 락이 이미 점유된 상태라면 즉시 작업을 포기하므로, 중복 실행이 첫 번째 작업 위에 쌓이지 않고 중단됩니다.

systemd timer가 더 나은 도구인 경우

cron은 특정 시간에 명령을 실행하는 한 가지 작업에는 적합하지만, 그 외의 모든 면에서는 취약합니다. timer를 사용하면 별도의 리다이렉트 없이도 journal을 활용할 수 있고, 나중에 쿼리할 수 있는 종료 상태를 얻을 수 있으며, network-online.target에 따른 순서 제어와 100대의 서버가 동시에 시작되지 않도록 하는 무작위 지연 기능을 사용할 수 있습니다. 작업에 이러한 기능이 필요하다면 VPS에서의 systemd 서비스 및 timer를 사용하는 것이 crontab 한 줄을 관리하는 것보다 수고가 덜 듭니다. 재시도 동작 또한 마찬가지입니다. systemd 재시작 정책이 실패 후의 동작을 결정하며, cron은 이 문제에 대해 아무런 해결책을 제시하지 못하기 때문입니다.

단순한 작업에는 cron을 유지하십시오. 의존성이 있거나 재시도 정책이 필요한 작업은 모두 timer로 옮기십시오. 두 방식은 같은 서버에서 공존할 수 있으므로, 한 번에 모든 작업을 마이그레이션할 필요는 없습니다.

FAQ

수동으로 실행하면 잘 되는 cron 작업이 왜 cron에서는 실패합니까?

사용자의 셸과 cron의 환경이 다르기 때문입니다. 로그인 셸은 /etc/profile~/.bashrc를 읽어 PATH, 로케일, 에이전트 변수 등을 설정합니다. cron은 이러한 설정 없이, 다른 작업 디렉터리에서, 때로는 다른 셸을 사용하여 명령을 실행합니다. 모든 명령에 절대 경로를 사용하고, crontab 상단이나 스크립트 내부에 필요한 환경 변수를 직접 설정하십시오. 또한 env | sort, pwd, id의 결과를 로그 파일로 기록하는 1분 단위의 테스트 작업을 등록하면, 추측할 필요 없이 cron의 실제 환경을 직접 확인할 수 있습니다.

cron이 내 작업을 실제로 실행했는지 어떻게 확인합니까?

데몬의 로그를 확인하십시오. Debian과 Ubuntu에서는 journalctl -u cron을, Fedora, Rocky, Alma에서는 journalctl -u crond을 사용합니다. 일부 이미지에서는 메시지가 rsyslog를 통해 /var/log 아래의 파일로 전달되기도 합니다. 예약한 시간에 해당하는 항목이 있는지, 그리고 그 항목에 실행하려는 명령이 명시되어 있는지 확인하십시오. 항목이 없다면 cron이 해당 스케줄을 인식하지 못한 것이므로, 올바른 crontab을 편집했는지 다시 확인하십시오. 항목은 있는데 결과가 없다면 명령이 실행 직후 종료된 것이므로, 리다이렉션을 사용하여 출력을 캡처하십시오.

crontab 안에서 date +%Y을 사용하면 왜 오류가 발생합니까?

cron은 명령 필드에서 %을 특수 문자로 취급합니다. 이스케이프되지 않은 첫 번째 %는 명령의 끝을 의미하며, 그 뒤에 오는 모든 내용은 표준 입력으로 전달되고, 이후의 모든 %은 줄바꿈으로 변환됩니다. 따라서 날짜 형식의 파일 이름은 의도한 프로그램에 전달되지 않습니다. 각 퍼센트 기호를 \%로 이스케이프하거나, 명령을 별도의 스크립트로 옮긴 뒤 cron에서 해당 스크립트를 호출하십시오. 스크립트 내부에서는 퍼센트 기호가 특수 의미를 갖지 않습니다.

cron 작업의 출력은 어디로 갑니까?

로컬 메일 시스템으로 전달되며, crontab 소유자나 MAILTO에 지정된 수신자에게 발송됩니다. 대부분의 VPS 이미지에는 메일 전송 에이전트가 설치되어 있지 않으므로 메시지는 폐기되고 작업은 아무런 반응이 없는 것처럼 보입니다. 출력을 파일로 리다이렉트하려면 >> /path/to/log 2>&1을 사용하십시오. 표준 에러가 표준 출력을 따르도록 이 순서를 유지하거나, logger -t myjob로 파이프를 연결한 뒤 journalctl -t myjob로 읽어 들일 수 있습니다. 디버깅 중에는 > /dev/null 2>&1를 사용하지 마십시오.

cron과 systemd timer 중 무엇을 사용해야 합니까?

고정된 시간에 실행되는 단순한 명령에는 cron을 사용하십시오. 특히 systemd를 사용하지 않는 환경으로 옮겨야 할 가능성이 있는 작업에 적합합니다. 출력을 별도의 리다이렉션 없이 저널에서 확인하고 싶거나, 종료 상태를 쿼리해야 하거나, 네트워크 연결 이후 실행 순서를 제어하거나, 시작 시간을 무작위로 지연시키거나, 실패 시 재시도 정책이 필요하다면 timer를 사용하십시오. 두 방식은 같은 서버에서 공존할 수 있으므로, 필요에 따라 작업을 하나씩 전환할 수 있습니다.