/ usr / bin / mail call no ExecStart não enviando nenhum email

5

Eu tenho o seguinte serviço configurado:

[Unit]
Description=SCollector
After=NetworkManager.service

[Service]  
Type=simple
ExecStart=/bin/sh -c "/opt/scollector/scollector /opt/scollector/collectors || (echo '' | /usr/bin/mail -s 'scollector died' [email protected] && exit -1)"
Restart=on-failure

[Install]
WantedBy=multi-user.target    

Por algum motivo, esse comando mail nunca envia nenhum email quando o processo scollector sai com não-0. Isso funciona AOK quando executado na linha de comando, /bin/sh call e tudo. Capturei STDOUT e STDERR de mail e não está causando erros. Não há nada em maillog .

O que dá? Por que não envia e-mails?

    
por alienth 22.09.2015 / 04:04

2 respostas

7

/usr/bin/mail realiza um duplo fork para daemonizar sendmail para enviar o email. Este sendmail proc é conhecido por init , então normalmente ele não seria afetado por nada que acontece com o pai original - exceto no caso do systemd, que o neto de renome ainda está no mesmo cgroup do serviço original. Quando systemd destrói as coisas, ele mata todos os processos dentro do cgroup, incluindo o conhecido processo sendmail .

O comando mail correu bem, mas sendmail foi morto pelo systemd antes de ter a chance de fazer o que queria.

Você pode contornar isso definindo KillMode na seção Unit como process (o padrão é control-group ). Isso fará com que systemd apenas mate o processo que foi acionado diretamente.

Curiosamente, a maneira como eu tropecei nisso foi através do uso de strace . Um strace normal não revelou nada, mas o mail de repente começou a funcionar ao usar strace -f . strace -f estava fazendo com que o processo principal continuasse até que todas as crianças e netos órfãos tivessem se envolvido.

    
por 22.09.2015 / 04:04
1

O questionador identificou o problema; mas a solução xyr é uma bodge, e a descrição xyr da mecânica está incorreta.

O comando mail não não executa um fork duplo. Ele se bifurca apenas uma vez e o processo de correção do sendmail é seu filho imediato que não é reparado em nada. Ele simplesmente escolhe se waitpid() para essa criança ou não, antes de sair.

O mesmo acontece com o shim do sendmail em si. Não duplica o garfo. Em alguns MTSes nem sequer bifurca. Em outros, ele bifurca apenas uma vez e escolhe se espera ou não dependente de alguma opção configurável de "modo de entrega".

A maneira correta de contornar o problema é dupla:

  1. Defina mailx da opção sendwait documentada e padronizada. Isso resolve especificamente os problemas de enfileiramento assíncrono, fazendo com que mailx espere que o processo filho shim do sendmail termine. (Infelizmente, embora esta opção esteja disponível desde pelo menos 1986 e esteja documentada para mailx no SVID, o bsd-mailx não a possui. Heirloom-mailx a possui, no entanto.)
  2. Defina o que estiver em uso na MTS para usar um modo de enfileiramento / entrega síncrono, se já não estiver usando um.
    • Se estiver usando o netqmail, não faça nada. O shim do sendmail do netqmail é sempre enfileirado e síncrono, diretamente carregando o qmail-inject para qmail-queue sem bifurcar.
    • Se estiver usando o Postfix, não faça nada. A correção sendmail do Postfix é sempre enfileirada e síncrona, forçando uma vez e aguardando que postdrop termine antes de sair.
    • o exim tem a opção de linha de comando -odf .

Leitura adicional

por 04.10.2015 / 14:30

Tags