O que há de errado com esses dois trabalhos cron?

13

Eu tenho os seguintes trabalhos cron definidos.

55  8   *   *   3   /usr/bin/php /home/mark/dev/processes/customClient/events.php > /home/mark/dev/processes/customClient/events-`date +%Y-%m-%d --date='last Wednesday'`-`date +%Y-%m-%d`.csv
0   9   *   *   3   /usr/bin/echo 'The csv for last week, trying my hand at automatiging this' | /usr/bin/mutt <emailaddress> -s 'Events from `date +%Y-%m-%d --date='last Wednesday'`-`date +%Y-%m-%d`' -a '/home/mark/dev/processes/customClient/events-`date +%Y-%m-%d --date='last Wednesday'`-`date +%Y-%m-%d`.csv'

Parece funcionar corretamente se eu executar o comando acima diretamente da linha de comando. Mas, quando verifiquei a execução do script hoje de manhã, recebi um e-mail informando (estou parafraseando porque os excluí acidentalmente) que os tiques anteriores não estavam fechados corretamente.

Mark D
fonte
Para sua informação, acabei de testar novamente os trabalhos do cron e obtive os seguintes erros. /bin/sh: 1: Syntax error: EOF in backquote substitution Para o primeiro trabalho cron. /bin/sh: 1: Syntax error: Unterminated quoted string Para o segundo trabalho cron.
Mark D #
2
Os backticks foram descontinuados por esse motivo; mudar para $(...)o ajudará a lidar com as questões citando ...
jasonwryan
1
Você definitivamente quer checar uma pergunta minha. Tem uma resposta de Stephane Chazelas que explica como você pode criar um shell interativo idêntico ao ambiente que seu trabalho cron verá. Se você seguir seu pequeno procedimento, receberá um prompt e poderá testar seu cronjob passo a passo e ver onde ele falhará. unix.stackexchange.com/a/56503/16841 Claro que não é 100% correspondente à sua pergunta, mas pode ajudá-lo a solucionar problemas do crontab.
jippie

Respostas:

14

Eu recomendo colocar todos os trabalhos cron não triviais em seu próprio arquivo de script de shell, por vários motivos:

  • Mais fácil para depurar: você pode simplesmente executar o script em vez de copiar colando uma linha longa e, com a linha shebang certa, ele se comporta muito mais previsivelmente do que se você tivesse os mesmos comandos diretamente no crontab
  • Mais fácil de ler: não é necessário torná-lo uma linha com mais de 200 caracteres; você pode formatá-lo de maneira agradável, para que seja fácil de ler e entender para todos
  • Adicione o script ao controle de versão
janos
fonte
8
E colocar os %caracteres problemáticos no script impedirá cronque eles sejam transformados em novas linhas, que é o seu problema real.
Ian D. Allen
Discordo. Você tende a esquecer qual script faz o quê. Estou falando por experiência própria.
Sridhar Sarnobat
30

Existem três causas comuns para os comandos do cron job se comportarem de maneira diferente em comparação aos comandos digitados diretamente em um shell interativo, em ordem aproximada de semelhança:

  • O Cron fornece um ambiente limitado, por exemplo, um número mínimo $PATHe outras variáveis ​​esperadas ausentes.
  • Cron chama /bin/shpor padrão, enquanto você pode estar usando algum outro shell interativamente.
  • Cron trata o %personagem especialmente (ele é transformado em uma nova linha no comando).
  • O Cron não fornece um ambiente terminal ou gráfico.

Você deve preceder todos os %caracteres com a \em um arquivo crontab, o que instrui o cron a colocar apenas uma porcentagem no comando. Lembre-se de que quando você usa o datecomando em um trabalho cron.

55  8   *   *   3   /usr/bin/php /home/mark/dev/processes/customClient/events.php > "/home/mark/dev/processes/customClient/events-$(date +\%Y-\%m-\%d --date='last Wednesday')-$(date +\%Y-\%m-\%d).csv"
0   9   *   *   3   /usr/bin/echo 'The csv for last week, trying my hand at automatiging this' | /usr/bin/mutt <emailaddress> -s "Events from $(date +\%Y-\%m-\%d --date='last Wednesday')-$(date +\%Y-\%m-\%d)" -a "/home/mark/dev/processes/customClient/events-$(date +\%Y-\%m-\%d --date='last Wednesday')-$(date +\%Y-\%m-\%d).csv"

Também corrigi alguns problemas de cotação:

  • Isso não estava causando problemas além da legibilidade, mas você não deve usar backticks para substituição de comandos. Em $(…)vez disso, use : suas regras de análise são mais simples.
  • Sempre use aspas duplas em torno das substituições de variáveis ​​e comandos: "$somevariable", "$(somecommand)". Aqui, a falta de aspas é inofensiva porque o datecomando nunca retornou nenhum caractere especial para os formatos usados, mas você deve se lembrar cuidadosamente de quais caracteres são especiais e verificar isso toda vez que deixar uma substituição sem aspas. Mantenha a simplicidade, sempre use aspas duplas, a menos que você queira que a divisão de campos e a geração de nome de arquivo ocorram no resultado.
  • Você tinha aspas simples, impedindo a expansão em torno de algumas substituições de comando. Use aspas duplas.
Gilles 'SO- parar de ser mau'
fonte
0

Você parece ter aninhado 'no muttcomando:

'Eventos de date +%Y-%m-%d --date='last Wednesday'- date +%Y-%m-%d'

Tente usar em "vez do interno 'para que a instrução leia

'Eventos de date +%Y-%m-%d --date="last Wednesday"- date +%Y-%m-%d'

Marko Kudjerski
fonte
Não sei se esse é o problema. Mas depois de tentar nos dois trabalhos cron, execute sem sucesso.
Mark D #