예전에 자주 물어보셨던 질문인 것 같은데, 아무리 찾아봐도 없네요.
내 패키지를 업데이트하는 타이머에서 실행되는 시스템 서비스가 있습니다. ssmtp
서비스에 오류가 발생할 때마다 이메일을 받고 싶습니다 .
터미널에서 루트로 실행하면 작동합니다.
# /root/bin/update 2> >(printf "Subject: ERROR from update.service\n\n$(cat -)" | sendmail [email protected])
Updating package lists... Done!
Updating packages... Done!
Removing old packages... Done!
Cleaning up... Done!
Updating dotfiles... FAILED!
Updating bpytop... Done!
Updating global npm packages... Done!
실패한 부분이 STDERR을 보냈고 오류가 의사 파일에 포착되었습니다 >()
. printf "...$(cat -)"
스트림 시작 부분에 주제를 추가합니다 . 본문이 stderr인 이메일을 받았습니다. 꽤 매끄러웠죠?
제가 하고 싶은 서비스는 바로 이것입니다. 기본적으로 표준 출력은 로그에 인쇄되지만 표준 오류는 내가 선택한 명령으로 리디렉션됩니다. 나는 이것을 처음 시도했습니다 :
ExecStart=/root/bin/update 2> >(printf "Subject: ERROR from update.service\n\n$(cat -)" | sendmail [email protected])
그러나 오류는 여전히 ssmtp 대신 저널로 전송됩니다. 나는 systemd가 stderr을 가로채서 지정된 곳으로 보낼 것이라고 생각했습니다.StandardError=
. 이 StandardError=
옵션을 사용하면 stderr을 파일 설명자나 파일로 보낼 수 있으므로 다음과 같이 시도했습니다.
ExecStart=/root/bin/update
StandardError=file:>(printf "Subject: ERROR from update.service\n\n$(cat -)" | sendmail [email protected])
그리고
StandardError=fd:printf "Subject: ERROR from update.service\n\n$(cat -)" | sendmail [email protected]
쓸모 없는. StandardError는 sendmail을 가리키는 명명된 파이프로 전송될 수 있습니다. 여기까지 하려고 이것저것 하다가 결국 포기하고 여기까지 왔습니다.
편집하다: 또한 이메일을 보내는 업데이트 스크립트에 bash 함수를 작성한 다음 스크립트의 각 명령에 대한 stderr을 해당 함수로 리디렉션하는 것도 고려했습니다. 그러나 저는 스크립트 자체에서 STDERR의 대상을 하드코딩하는 대신 시스템 수준의 솔루션을 찾고 있습니다.
답변1
나는 가능한 해결책을 생각해 냈습니다. stderr을 파일에 쓰고그 다음에우송료를 사용하십시오 ExecStartPost=
. 또한 명령을 다음으로 래핑하지 않으면 시스템 서비스 파일이 제대로 리디렉션되지 않는다는 것도 배웠습니다 /bin/bash -c ''
.
ExecStartPre=/bin/rm -f /root/update.err
ExecStart=/bin/bash -c '/root/bin/update 2>/root/update.err'
ExecStartPost=/bin/bash -c 'test -f /root/update.err && printf "Subject: ERROR from update.service\n\n$(cat /root/update.err)\n" | sendmail [email protected]'
원천:예를 들어, ExecStart에서 Systemd 서비스 표준 출력을 셸로 파이프하는 방법입니다. 큰 타격을 입었습니까?