고쳐 쓰다:

고쳐 쓰다:

crontab에서 오류가 발생하면 다음 메시지가 나타납니다.

cron: No MTA installed, discarding output

내 시스템에 MTA를 설치하고 싶지 않지만 이러한 오류 메시지도 놓치고 싶지 않습니다.

이메일을 통해 이 정보를 보내도록 cron은 어디에 구성되어 있습니까? 이 메시지가 파일로 전송되도록 변경할 수 있나요? (아마도 sysylog를 통해).

모든 cron 메시지를 기록하고 싶지 않고 오류만 기록하고 싶습니다.

내 거 rsyslog.conf:

cron.=info                    stop

*.*                          |/dev/xconsole

안타깝게도 오류 메시지에도 .info라벨이 있는 것 같습니다.

cron 오류만 기록하려면 어떻게 해야 합니까? 즉, MTA가 설치된 경우 로그 파일로 어떻게 보내며 그렇지 않은 경우 로그 파일로 무엇을 보내나요?

내 시스템은 로깅에 사용하는 Debian 10입니다 rsyslog(systemd 없음).

고쳐 쓰다:

@basin이 제안한 것처럼 각 행에 대해 개별적으로 리디렉션을 사용하는 것이 지금까지 사용한 솔루션이며 거의 문제 없이 작동합니다.

첫째, 앞서 말했듯이 저는 일반적으로 기본적으로 MTA로 전송되는 콘텐츠를 다른 곳, 즉 |/dev/xconsole각 거짓말을 개별적으로 지정하지 않고도 다른 곳으로 리디렉션하는 솔루션을 원합니다.

둘째, crontab 줄에 구문 오류가 있으면 리디렉션이 작동하지 않습니다. Cron은 여전히 ​​MTA를 통해 오류를 보내려고 시도하고 있으며 No MTA installed로그에 오류가 표시됩니다.

MTA를 통해 전송된 내용이 (직접 또는 sysylog를 통해) 로 전송되도록 리디렉션할 수 있는 방법이 있습니까 /dev/xconsole?

추가 질문:

제안된 솔루션을 사용할 때 @Binarus나만의 맞춤 sendmail스크립트를 작성하세요.

기본값을 사용하는 대신 /usr/sbin/sendmail사용자 정의 스크립트에 대해 다른 위치를 지정할 수 있습니까 /usr/local/sbin/sendmail? 의 정보는 어디에 있나요 cron? 이것은 하드코딩되어 있습니까? 아니면 cron의 구성 파일 중 하나에서 구성할 수 있습니까?sendmail/usr/sbin/

답변1

나는 해결책이 있다고 생각하지만 절반만 ​​테스트했습니다. 아쉽게도 내 시스템에 해당 장치가 없기 때문에 테스트할 수 없으며 /dev/xconsole, 그것이 무엇인지도 모르고 살펴볼 시간도 없다는 점을 인정합니다.

하지만 두 가지 이점이 있습니다. 첫째, 아래 방법은 일반적입니다. 즉, /dev/xconsole제가 사용한 것 이외의 파일 이름을 거의 확실히 사용할 수 있습니다. 둘째, 나는오직Debian Buster에서 테스트했으므로 실제로는 즉시 작동할 것입니다.

먼저 (매우 간단한) 솔루션을 보여주고, 작동 방식을 설명하고, 몇 가지 가능한 문제와 이를 우회하는 방법을 보여 드리겠습니다.

해결책

주의사항으로 먼저 보유하고 있는지 확인하시기 바랍니다 /usr/sbin/sendmail. 이건 해야 해아니요맞습니다. 이 프로그램은 일반적으로 MTA에 속하지만 MTA가 설치되어 있지 않다고 하셨습니다. 존재하는 경우 포함된 패키지를 제거합니다.

/usr/sbin/sendmail이제 다음 내용으로 스크립트를 만듭니다.

#!/bin/bash
cat >>/root/result

그에 따라 권한을 설정하십시오.

chmod a+rx,u+w,og-w /usr/sbin/sendmail

재시작 cron:

systemctl restart cron

그게 다야. cron일반적으로 이메일을 통해 전송되는 모든 오류 메시지는 이제 에 들어갑니다 /root/result.

물론 위의 단계는 루트 사용자로 수행해야 합니다.

/root/result귀하의 경우에는 아마도 다음 으로 바꾸고 싶을 것입니다 /dev/xconsole(그러나 위에서 언급한 것처럼 이것을 테스트하지 않았다는 점을 명심하십시오 :-)). 그리고 결국에는 다음 >>으로 바꿔야 합니다 >(그러나 나는 그것에 대해 전혀 모르기 때문에 /dev/xconsole, 이 내용은 틀릴 수도 있습니다.)

어떻게 작동하나요?

정의: 다음에서는 SENDMAIL을 사용하여 SENDMAIL 패키지를 참조하고 sendmail애플리케이션을 참조하겠습니다.

전자 메일 메시지를 보내는 대부분(또는 적어도 많은) 프로그램은 소켓이나 네트워크 연결을 통해 MTA와 직접 통신해야 하는 SMTP 프로토콜 스택을 기본적으로 구현하지 않으며 보안 관점에서 SMTP 라이브러리를 포함하지 않습니다. 실수는 치명적일 것이며 대부분의 경우 특수 응용 프로그램이 구출되기 때문에 이것은 필요하지 않습니다.

이러한 특수 앱 중 하나는 /usr/bin/sendmailSMTP 등이 포함되어 있고 사용이 매우 쉽다는 것입니다. 일반적인 패턴은 다음과 같습니다.

cat MyMailMessage | /usr/bin/sendmail [sendmail-options]
# OR, even shorter
/usr/bin/sendmail <MyMailMessage

즉, 애플리케이션은 메일 메시지를 구성하고(몇 개의 헤더와 실제 본문만 필요하므로 매우 간단함) 이를 서버로 파이프하고 sendmail서버는 다시 SMTP 마법을 수행합니다.

역사적으로 SENDMAIL은 한때 기본 MTA였습니다. SENDMAIL에는 MTA뿐만 아니라 MSP(Message Submission Program)도 포함되어 있습니다. MSP 부분은 /usr/sbin/sendmail오랫동안 SENDMAIL을 제거할 수 없었기 때문에 많은 애플리케이션이 실제로 여전히 메일 제출자 역할을 /usr/sbin/sendmail하거나 의존하고 있었습니다. sendmail그렇기 때문에 SENDMAIL의 경쟁사(예: POSTFIX)에서도 여전히 이 프로그램을 호환성 래퍼로 제공합니다.

cron이 점에서 해당 동작은 다른 응용 프로그램과 유사합니다. SMTP를 지원하지 않습니다. 대신 sendmail실제로 메시지를 보내는 데 의존합니다 . 헤더와 본문을 포함하여 원시 메시지를 구성하고 sendmail실제로 보내는 으로 파이프됩니다.

/usr/sbin/sendmail그래서 위에 표시된 스크립트로 대체했습니다 (MTA를 설치했기 때문에 이것은 단지 테스트용이었습니다). 이메일을 보내려고 할 때 cron호출되는 /usr/sbin/sendmail이것이 우리의 스크립트입니다. 스크립트는 단순히 표준 입력을 받아 파일로 리디렉션합니다.

참고로 cron원본 이메일 메시지를 직접 여기에 파이프하는지 sendmail, 아니면 먼저 임시 파일에 넣은 다음 해당 파일에서 리디렉션 호출을 하는지 sendmail, stdin아니면 다른 작업을 수행하는지 실제로는 알 수 없습니다.

그러나 여기서는 이것이 중요하지 않습니다. 중요한 점은 각 경우에 원본 이메일 메시지가 에서 구성되어 의 에 저장된다는 것입니다 cron( 그러나 cron이 작업은 수행될 수 있습니다).sendmailstdin

단점, 문제점, 개선점

cat스크립트 내에서 사용하는 것은 효율성 측면에서 최선의 선택이 아닐 수 있지만 예상되는 출력에 따라 달라집니다. 스크립트를 파일에 넣는 가장 좋은 방법을 설명하는 수많은 기사가 있습니다 stdin. 이것이 귀하의 질문 범위에 포함되지 않는 것 같습니다.

내 솔루션의 한 가지 단점은 명백합니다. "실제"가 필요한 경우 /usr/sbin/sendmail문제가 있습니다. 미묘한 것을 상상할 수 있습니다. 발견 여부에 따라 작동하는 일부 응용 프로그램이 있을 수 있습니다 /usr/sbin/sendmail.

예를 들어, 애플리케이션이 실행 파일을 발견하면 오류를 이메일로 보내기로 결정할 수 있고, 그렇지 않으면 로그 파일에 오류를 기록할 수 있습니다. 이제 애플리케이션의 동작이 변경됩니다. 다음에 일어날 일은 상황에 따라 크게 달라집니다. 첫째, 일반적인 위치에서는 오류 메시지를 찾지 못할 수 있습니다. 둘째, sendmail이것은 이제 간단한 스크립트이고 애플리케이션이 예상하는 대로 작동하지 않기 때문에 이상한 일이 발생할 수 있습니다.

하지만 해결책이 있습니다. 재컴파일을 허용하겠다고 언급하셨습니다 cron. 나는 소스 코드에 그것이 사용하는 MSP 이름의 정의가 config.h있다고 믿습니다(그러나 지금은 확인할 수 없습니다) . #define해결 방법은 분명합니다. 스크립트 이름을 다음으로 바꾸고 abcd1234이를 값으로 사용하거나 #define- 아마도 더 나은 방법으로 - 스크립트를 다른 디렉토리에 두는 것입니다.아니요시스템의 검색 경로에서 스크립트의 전체 경로를 #define.

이렇게 하면 별도의 #define; 하지만 스크립트는 단지 무시하기 때문에 스크립트에 해를 끼치지는 않습니다. 어쩌면 cron스크립트와 직접 오류 출력을 원하는 파일이나 장치로 직접 덤프 할 수도 있습니다 . 이것이 가능한지 결정하려면 소스 코드에 대한 추가 분석이 필요하지만 아직 수행하지 않았습니다. 나는 무슨 일이 있어도 스크립트를 고수할 것입니다. 한 가지 큰 이유는 다음 단락을 참조하십시오.

[2021년 10월 20일 업데이트됨:

2021년 10월 20일 원래 질문에 대한 내 의견에서 언급했듯이 재컴파일을 방지할 수 있는 문제를 해결하는 대체 방법이 있습니다. "실제"를 sendmail다른 곳으로 옮기고 그 자리에 스크립트를 설치하는 것입니다. 그런 다음 스크립트가 실행될 때마다 누가 호출했는지 알아내도록 합니다. 호출된 경우 cron위에 표시된 대로 작동하도록 하고, 그렇지 않은 경우 sendmail동일한 인수, 즉 stdin"relay" 및 "real" stdin을 사용하여 "real"을 호출하도록 합니다 sendmail.

]

또 다른 문제는 관심 있는 오류 메시지가 표시될 뿐만 아니라 이를 볼 때마다 cron헤더를 포함하여 원본 이메일 전체가 전송된다는 것입니다. 해결 방법은 사용 grepsed해당 친구 와 같이 관심 없는 행을 필터링하는 일부 코드를 스크립트에 추가하는 것입니다 . 하지만 그것도 이 질문의 범위를 벗어납니다.

답변2

cron에 SHELL.

Cron(특히 Debian Buster/10의 vixie-cron)은 최신 버전입니다 $SHELL.예약된 작업(5), 그리고 정의된do_command.c,

줄의 전체 명령 부분(개행 또는 % 문자까지)은 /bin/sh 또는 crontab 파일의 SHELL 변수에 지정된 쉘에 의해 실행됩니다.

320 |           char    *shell = env_get("SHELL", jobenv);
... |
348 |           execle(shell, shell, "-c", e->cmd, (char *)0, jobenv);

$SHELL -c "<command>"구문 오류나 런타임 오류에 관계없이 stdout/stderr 에 있는 모든 내용이 MTA로 전송됩니다 . (이것은 "do_command.c"에도 정의되어 있습니다.) 따라서 SHELL=/path/to/stdout/stderr/redirector이를 cron 파일에 설정하면 네 가지 문제가 모두 해결되어야 합니다.

  1. 로그 파일로 어떻게 보낼 수 있으며, MTA가 설치된 경우 무엇이 전송됩니까?

  2. 각 li[n]e를 개별적으로 지정할 필요가 없습니다.

  3. crontab 줄에 구문 오류가 있으면 리디렉션이 작동하지 않습니다.

  4. cron: No MTA installed, discarding output

출력으로 테스트 >>/tmp/test했는데 >/dev/xconsole. 또는 syslog용 래퍼처럼 타임스탬프, 세부 명령 등을 보존하는 스크립트를 작성할 수도 있습니다.

$ cat /tmp/sh-out
#!/usr/bin/sh
1>>/tmp/test 2>>/tmp/test /usr/bin/sh "$@"
$ crontab -l
SHELL=/tmp/sh-out
* * * * * echo output
* * * * * wrong-command
$ tail -f /tmp/test
output
/usr/bin/sh: 1: wrong-command: not found

다른 질문에 답변하려면,

cron은 sendmail이 위치한 곳의 정보를 어디서 얻나요 /usr/sbin/?

Debian 10과 11은 vixie-cron의 대규모 패치 버전을 사용합니다. 다음 MAILCMD과 같이 정의 됩니다 ._PATH_SENDMAIL구성.h#L24처럼 /usr/bin/sendmail.

MTA를 통해 전송된 내용이 (직접 또는 sysylog를 통해) 로 전송되도록 리디렉션할 수 있는 방법이 있습니까 /dev/xconsole?

아니요, vixie-cron은 이를 지원하지 않지만 명령이나 MTA를 변경하여 문제를 해결할 수 있습니다.

크로니는 할 수 있어요.

       -s     This option will direct Cron to send the job output to the
              system log using syslog(3).  This is useful if your system
              does not have sendmail(8), installed or if mail is
              disabled.

그러나 cronie는 Debian Experimental에만 있으며 계획은vixie-cron에서 cronie로 전환그 이후로는 소식이 없습니다2019-11-05.

안타깝게도 오류 메시지에도 .info라벨이 있는 것 같습니다.

하드코딩되어 있습니다.기타.c#L589,몸 속에void log_it(username, xpid, event, detail)

    syslog(LOG_INFO, "(%s) %s (%s)", username, event, detail);

log_it패치를 사용하여 로그 수준에 대한 지원을 추가할 수 있는 것 같습니다 . 그러나 로그 수준은 MTA로 전송되거나 완전히 삭제되므로 cron의 명령 출력과 아무 관련이 없습니다.

답변3

가장 쉬운 방법은 crontab의 모든 작업을 리디렉션하는 것입니다.

*  *  *  *  * user-name  command to be executed >/dev/null 2>>/tmp/some.log

또는 cronie다음 옵션이 있습니다.

   -m     This option allows you to specify a shell command to use for sending Cron mail output instead of using sendmail(8) This command  must  accept  a  fully
          formatted  mail message (with headers) on standard input and send it as a mail message to the recipients specified in the mail headers.  Specifying the
          string off (i.e., crond -m off) will disable the sending of mail.

cat내부 입력을 파일에 쓰는 쉘 스크립트를 작성할 수 있습니다 .

에서 비슷한 옵션을 찾지 못했지만 사용자 정의 스크립트로 바꾸면 작동할 anacron수도 있습니다./usr/bin/sendmail

답변4

운영 체제가 기본적으로 메일 시스템과 같은 것을 사용하는 경우 필요에 따라 작업 출력을 처리하는 사용자 정의 쉘 스크립트를 호출하는 sendmail사용자 정의 파일을 사용할 수 있습니다 .mailer.confcron

이 설정에는 sendmail유사한 환경이 필요하지만 sendmail데몬 자체는 비활성화되어야 합니다.아니요달리기.

mailer.conf먼저 대체 셸 스크립트를 sendmail메일을 "보내는" 구성 요소로 정의하고 셸 스크립트 자체를 생성하는 간단한 파일을 만듭니다 .

printf 'sendmail\t/etc/mail/mail-script.sh\n' > /etc/mail/mailer.conf

cat << 'EOF' > /etc/mail/mail-script.sh
#!/usr/bin/env bash

{
  date
  printf -- '--- BEGIN\n'
  cat
  printf -- '--- END\n'
} >> /var/log/cron-jobs.log
EOF

chmod 755 /etc/mail/mail-script.sh

이것으로 설정의 "이메일" 부분이 완료됩니다. 이제 테스트할 수 있는 샘플 크론 작업을 만들어 보겠습니다.

cat << 'EOF' > /root/testjob.sh 
#!/usr/bin/env bash

printf 'This is a test cron job run at %s\n' "$(date)"
EOF

chmod 755 /root/testjob.sh

/etc/crontab마지막으로 매분 실행되는 항목을 만듭니다 ./root/testjob.sh

cat << EOF >> /etc/crontab
MAILTO="foobar"
*   *   *   *   *   root    /root/testjob.sh
EOF

항목 MAILTO이 존재해야 하지만(그렇지 않으면 이메일이 생성되지 않음) 임의적일 수 있습니다. 원하는 경우 MAILTO다양한 목적으로 특정 이름을 정의하고 cron작업에서 참조하는 태그에 따라 MAILTO작업 출력을 다르게 처리 할 수 있습니다 cron.

이 모든 작업을 수행한 후 다음과 같은 출력이 축적된 것을 발견합니다 /var/log/cron-jobs.log.

# tail -f /var/log/cron-jobs.log
Tue Oct 12 14:11:00 PDT 2021
--- BEGIN
From: Cron Daemon <[email protected]>
To: foobar
Subject: Cron <root@test> /root/testjob.sh
X-Cron-Env: <SHELL=/bin/sh>
X-Cron-Env: <PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin>
X-Cron-Env: <MAILTO=foobar>
X-Cron-Env: <LOGNAME=root>
X-Cron-Env: <USER=root>

This is a test cron job run at Tue Oct 12 14:11:00 PDT 2021
--- END
Tue Oct 12 14:12:00 PDT 2021
--- BEGIN
From: Cron Daemon <[email protected]>
To: foobar
Subject: Cron <root@test> /root/testjob.sh
X-Cron-Env: <SHELL=/bin/sh>
X-Cron-Env: <PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin>
X-Cron-Env: <MAILTO=foobar>
X-Cron-Env: <LOGNAME=root>
X-Cron-Env: <USER=root>

This is a test cron job run at Tue Oct 12 14:12:00 PDT 2021
--- END
Tue Oct 12 14:13:00 PDT 2021
--- BEGIN
From: Cron Daemon <[email protected]>
To: foobar
Subject: Cron <root@test> /root/testjob.sh
X-Cron-Env: <SHELL=/bin/sh>
X-Cron-Env: <PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin>
X-Cron-Env: <MAILTO=foobar>
X-Cron-Env: <LOGNAME=root>
X-Cron-Env: <USER=root>

This is a test cron job run at Tue Oct 12 14:13:00 PDT 2021
--- END
Tue Oct 12 14:14:00 PDT 2021
--- BEGIN
From: Cron Daemon <[email protected]>
To: foobar
Subject: Cron <root@test> /root/testjob.sh
X-Cron-Env: <SHELL=/bin/sh>
X-Cron-Env: <PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin>
X-Cron-Env: <MAILTO=foobar>
X-Cron-Env: <LOGNAME=root>
X-Cron-Env: <USER=root>

This is a test cron job run at Tue Oct 12 14:14:00 PDT 2021
--- END
Tue Oct 12 14:15:00 PDT 2021
--- BEGIN
From: Cron Daemon <[email protected]>
To: foobar
Subject: Cron <root@test> /root/testjob.sh
X-Cron-Env: <SHELL=/bin/sh>
X-Cron-Env: <PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin>
X-Cron-Env: <MAILTO=foobar>
X-Cron-Env: <LOGNAME=root>
X-Cron-Env: <USER=root>

This is a test cron job run at Tue Oct 12 14:15:00 PDT 2021
--- END

관련 정보