Cron은 가끔씩만 출력 및 오류에 대한 이메일을 보냅니다.

Cron은 가끔씩만 출력 및 오류에 대한 이메일을 보냅니다.

데비안 8.1에서 나는 사용하고 있습니다불다stackoverflow.com 웹사이트에 액세스할 수 있는지 감지하는 기능:

(에코>/dev/tcp/stackoverflow.com/80) &>/dev/null || echo "스택오버플로우에 액세스할 수 없습니다."

sh이는 Bash에만 적용되며 .default 쉘에는 영향을 미치지 않습니다 cron.

의도적으로 스크립트를 시도하면 다음과 같은 결과를 sh얻습니다.

$ /bin/sh: 1: cannot create /dev/tcp/stackoverflow.com/80: Directory nonexistent

SHELL따라서 다음을 개인 crontab( via 로 설정하지 않음 /bin/bash) 에 넣으면 crontab -e스크립트가 1분마다 실행되기를 원하므로 위의 오류가 이메일당 1분에 한 번씩 전송되기를 원합니다.

* * * * * (echo >/dev/tcp/stackoverflow.com/80) &>/dev/null || echo "Stackoverflow에 액세스할 수 없습니다."

실제로 예상한 대로 /var/log/syslog이 항목이 매분 실행되는 것을 볼 수 있습니다.

#sudo grep 스택오버플로우 /var/log/syslog
8월 24일18:58:01로컬호스트 CRON[13719]: (mat) CMD ((echo >/dev/tcp/stackoverflow.com/80) &>/dev/null || echo "stackoverflow에 액세스할 수 없습니다.")
8월 24일18:59:01로컬호스트 CRON[13723]: (mat) CMD ((echo >/dev/tcp/stackoverflow.com/80) &>/dev/null || echo "stackoverflow에 액세스할 수 없습니다.")
8월 24일19:00:01로컬호스트 CRON[13727]: (mat) CMD ((echo >/dev/tcp/stackoverflow.com/80) &>/dev/null || echo "stackoverflow에 액세스할 수 없습니다.")
...

이 명령은 지난 2시간 동안 120회 이상 실행되었으며 출력을 wc -l.

하지만, 이러한 120개 이상의 셸 명령(반복: 셸 명령 쌍이 유효하지 않음 /bin/sh)이 실행되었으므로 다음과 같은 결과만 얻습니다.이메일:

첫 번째는 19:10:01, 두 번째는 20:15:01, 세 번째는 20:57:01입니다.

세 메시지의 내용은 모두 예상한 대로 정확하게 읽었으며 (의도적으로) 호환되지 않는 셸에서 스크립트를 실행할 때 예상되는 오류 메시지도 정확하게 포함했습니다. 예를 들어, 제가 받은 두 번째 이메일은 다음과 같았습니다(나머지 두 이메일은 거의 동일했습니다).

~에서[이메일 보호됨]  2015년 8월 24일 월요일 20:15:01
에서:[이메일 보호됨](크레인 데몬)
도착하다:[이메일 보호됨]
주제: Cron (echo >/dev/tcp/stackoverflow.com/80)&>/dev/null || echo "Stackoverflow에 액세스할 수 없습니다."
...

/bin/sh: 1: /dev/tcp/stackoverflow.com/80을 생성할 수 없습니다: 디렉토리가 존재하지 않습니다`

/var/log/mail.log님이 보낸 이메일 3개는 다음과 같습니다.오직지난 몇 시간 동안 보내고 받은 메시지입니다.

그렇다면 잘못된 스크립트에 의해 생성된 위 출력으로 인해 cron에서 수신할 것으로 예상되는 100개 이상의 추가 이메일은 어디에 있습니까?

결론적으로:

  1. 이 시스템에서는 메일이 올바르게 구성되어 있으며 문제 없이 메일을 보내고 받을 수 있습니다 /usr/bin/sendmail.
  2. Cron은 올바르게 설정되어 예상대로 작업을 인식하고 구성된 시간에 정확하게 실행합니다. 나는 다른 많은 작업과 예약 옵션을 시도했고 cron은 예상대로 정확하게 실행했습니다.
  3. 스크립트언제나출력을 작성하므로(아래 참조) cron이 호출할 때마다 출력을 이메일로 보낼 것으로 예상합니다.
  4. 결과는 가끔 나에게 우편으로 전달되며 대부분의 경우 무시됩니다.

위의 관찰 결과로 이어지는 명백한 오류를 해결하는 방법에는 여러 가지가 있습니다.

  1. SHELL=/bin/bash내 에서 그렇게 할 수 있습니다 crontab.
  2. heartbeat.shwith를 만들고 #!/bin/bash호출 할 수 있습니다 .
  3. /bin/bash -c ...inside 를 사용하여 스크립트를 호출할 수 있습니다 crontab.
  4. 잠깐만요. 이 모든 것이 sh.

그러나 이 중 어느 것도 이 문제의 핵심 문제를 해결하지 못합니다. 즉, 이 경우 cron스크립트조차도 안정적으로 메일을 보낼 수 없다는 것입니다.언제나출력을 생성합니다.

나는 스크립트가 항상 wrong.sh다음을 생성하여 출력을 생성한다는 것을 확인했습니다.고의로부적절한 쉘을 사용하면 표시되는 것과 동일한 오류가 /bin/sh발생합니다 .)cron

#!/bin/sh
(echo >/dev/tcp/stackoverflow.com/80) &>/dev/null || echo "Stackoverflow에 액세스할 수 없습니다."

이제 스크립트 호출을 반복하여 완료되는 항목이 있는지 확인할 수 있습니다.아니요출력을 생성합니다. 사용불다:

$ true인 경우; do [[ -n $(./wrong.sh 2>&1 ) ]] echo $?;

수천 번의 호출에도 불구하고 출력을 생성하지 않고 스크립트가 완료되는 상황을 재현할 수 없습니다.

이렇게 예측할 수 없는 행동이 나타나는 이유는 무엇일까요? 누구든지 이것을 재현할 수 있습니까? 나에게는 cron이 스크립트의 출력을 놓칠 수 있는 경쟁 조건이 있을 수 있는 것 같습니다. 아마도 대부분 오류가 셸 자체에서 발생하는 상황과 관련이 있을 것입니다. 감사합니다!

답변1

&추가 테스트를 해보니 결과가 엉망이 될 것 같습니다 . 지적하신대로 &>/dev/null그렇습니다세게 때리다문법, 아니통사론. 결과적으로 sh서브쉘이 생성되어 배경으로 설정됩니다. 물론 서브쉘은 echostderr을 생성하지만 내 이론은 다음과 같습니다.

  1. cron은 서브쉘의 stderr을 캡처하지 않으며
  2. 서브셸의 배경은 항상 성공적으로 완료되며 || echo ....

...크론 작업에서 출력이 발생하지 않으므로 메일이 없습니다. vixie-cron 소스 코드를 읽어보니 작업의 stderr 및 stdout이 cron에 의해 캡처되지만 서브쉘에 의해 확실히 손실되는 것 같습니다.

/bin/sh 환경에서 직접 테스트해 보세요(여기에 "bar"라는 파일이 없다고 가정).

(grep foo bar) &
echo $?

답변2

다음 crontab을 사용하여 Ubuntu 15.04에서 동작을 재현할 수 있습니다.

* * * * * { echo job 0; } & sleep 5
* * * * * { echo job 1; } &
* * * * * { sleep 5; echo job 2; } &

job 0매분마다 cron으로부터 다음 내용이 포함된 이메일을 받습니다.job 1 가끔(최근 10분 동안 5~6회), 없음 job 2.

따라서 cron은 하위 프로세스가 종료될 때까지 기다린 다음 당시에 흡수할 수 있는 모든 stdout/stderr 출력이 포함된 이메일을 보내는 것처럼 보입니다. 고아가 된 손자 프로세스의 지연된 출력은 단순히 삭제됩니다.

답변3

위의 설명 외에도 조금 더 간단한 설명이 있을 수 있는지 궁금합니다.

모든 쉘은 작업을 수행하기 전에 명령줄을 확장/처리한다는 점을 기억하세요. 따라서 sh"&"로 확장하면 명령줄이 종료되고 이를 백그라운드에 넣으려고 하며(기본적으로 낮은 우선순위) 리디렉션된 내용에 따라 stdin/stdout/stderr이 제대로 할당되지 않습니다. 따라서 "경합 조건"은 쉘(sh)이 라인을 처리하는 속도에 따라 달라질 수 있으며, 이는 분명히 시스템의 로드(및 이후에 시스템과 상호 작용하는 방식 cron)에 따라 달라집니다.

관련 정보