Por que esse script falha quando executado no cron, mas funciona quando executado manualmente?

Por que esse script falha quando executado no cron, mas funciona quando executado manualmente?

Eu tenho um script bash relativamente simples que funciona muito bem quando invocado diretamente, mas falha quando executado pelo cron. Por que isso falha e como posso fazê-lo funcionar via cron?

#!/bin/bash
apt-get update -y
apt-get upgrade -y
apt-get install boinc-client -y

Depois que o cron tentar executá-lo, uma invocação manual resultará neste erro:

dpkg was interrupted, you must manually run 'sudo dpkg --configure -a' to correct the problem.

Mas desde que seja executado manualmente na primeira vez, funciona perfeitamente.

Responder1

A resposta usual para esse tipo de pergunta é que os cron jobs são executados em shells não interativos e sem login, portanto, a maioria dos arquivos de inicialização do shell (tanto os do sistema /etcquanto os dotfiles pessoais no diretório inicial) não são originados ( lido e executado), porque a maioria dos arquivos de inicialização do shell se aplicam a shells de login (o primeiro shell que você vê quando faz login no computador) ou shells interativos (shells que estão conectados a terminais, sessões ssh ou emuladores de terminal porque um usuário é interagindo com eles através do referido terminal).

Portanto, se você colocar um comando em um cron job que realmente depende de alguma configuração de ambiente (incluindo PATHalterações) que geralmente acontece em locais como /etc/profile, /etc/bashrc, ~/.profile, ou ~/.bashrc, essa configuração não acontecerá para um cron job. O formato de arquivo cron permite especificar variáveis ​​de ambiente para seus trabalhos, portanto, você pode querer especificá- lo BASH_ENVou ENVapontá-lo para um script de inicialização do shell para a origem. Consulte a seção "Invocação" da bash(1)página de manual.

Responder2

Isso não se qualifica como resposta, mas não posso comentar. Sugestões:

  1. acrescente o seguinte ao seu script bash. A última linha registrada na saída do email será o comando com falha.

    set -x
    set -e
    
    • certifique-se de ter o sendmail (instale um pacote fornecido como postfixou esmtp)
    • instale um leitor de e-mail (recomendado mutt)
    • garantir que o e-mail chegue até você
      • via postfix (pode ser feito automaticamente pelo instalador): root: my-user-nameadicione /etc/aliasesou/etc/postfix/aliases
      • via cron: adicione MAILTO="my-user-name"ao crontabarquivo apropriado
  2. Verifique se o script será executado em um ambiente diferente. Especifique o caminho completo para o apt-get (provavelmente não é o culpado, já que se sabe que o apt-get foi encontrado) e execute-o em um console (não terminal) fora do X. (alguns scripts de configuração do dpkg requerem uma sessão X).

    • modifique o script para usar caminhos absolutos, ou seja, /usr/bin/apt-get update -y(substitua pelo caminho correto)
    • mude para um console pressionandoctrl-alt-f1
    • mude para usuário root:sudo -i
    • inicie um shell sem login sem um ambiente: env -i /bin/bash --noprofile --norc(substitua pelo caminho correto)
    • execute o script: /my/full/path/to/cronscript. Funciona?
  3. O script tem permissão? Você está usando o sistema crontab? (mais uma vez, provavelmente não é o culpado)

    • Você declarou que está usando o crontab do sistema, portanto, ignore isso.
  4. O apt-get requer suporte de sessão (consolekit ou systemd). No entanto, este é apenas um tiro no escuro.

    • Não sei o suficiente para ajudar.

Responder3

Consegui resolvê-lo com quase nenhuma compreensão do que estava acontecendo. Acontece que mesmo que eu estivesse executando o root crontab, os comandos do apt-get ainda precisavam de um sudo na frente deles. Logicamente eu esperava que isso não fosse necessário, pois o script já estava sendo executado "como root", mas depois que adicionei o sudo... tudo funcionou exatamente como esperado.

informação relacionada