
Eu tenho um script que funciona bem quando eu ssh para minha instância do Ubuntu EC2 e o executo (como usuário ubuntu
)
Quero que isso aconteça quando o servidor inicializar, então adicionei ao cron como:
@reboot sleep 10 && /home/ubuntu/start.sh
No entanto, quando o cron é executado, PATH
não é o mesmo e alguns comandos falham porque os binários não são carregados:
$ echo $PATH
/home/ubuntu/.nvm/versions/node/v4.2.6/bin:/home/ubuntu/bin:/home/ubuntu/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
# in start.sh
echo "path $PATH" >> start.logs
# will log 'path /usr/bin:/bin'
Tentei adicionar source /home/ubuntu/.bashrc
meu start.sh
script porque acredito que é onde ele PATH
é construído, pelo menos parcialmente, mas isso não parece mudar muito:
# in start.sh
source /home/ubuntu/.bashrc
echo "path $PATH" >> start.logs
# will still log 'path /usr/bin:/bin'
Também verifiquei se o Cron é executado como ubuntu
e não root
, o que parece ser o caso, já que editei os cron jobs sendo logados comoubuntu
Existe uma maneira fácil de executar o cron no mesmo ambiente que obtenho após fazer login no meu servidor por ssh?
Responder1
Normalmente as variáveis de ambiente devem ser definidas em ~/.profile
, ou ~/.bash_profile
se este arquivo existir, seu shell de login é bash. Portanto, carregue este arquivo do cron job.
@reboot . ~/.profile; sleep 10 && /home/ubuntu/start.sh
~/.bashrc
é apenas para personalizações interativas, portanto você não deve carregá-lo de forma não interativa e geralmente não funcionará de qualquer maneira. Se você tiver definições de variáveis de ambiente em .bashrc
, corrija essa bagunça primeiro.
Outro lugar para definir variáveis de ambiente é ~/.pam_environment
, se você quiser que a variável tenha um valor constante (você não pode executar comandos shell neste arquivo).
VerQual é a melhor maneira independente de distribuição/shell para definir variáveis de ambiente?,Diferença entre Shell de login e Shell sem login?eExiste um arquivo equivalente ".bashrc" lido por todos os shells?para obter mais informações sobre arquivos de inicialização do shell.
Responder2
cron normalmente é executado com sh e não com bash, eles têm perfis diferentes.
tente executar o cron individual no bash, se você tiver vários env vars personalizados, você sempre pode env>/file, source /file no cron.
Responder3
Resolvi meu problema como:
- run
$ crontab -e
e add antes de todas as outras linhas.SHELL=/bin/bash
Isso forçará o cron a usar o bash. Háalternativasse você quiser fazer isso apenas para um comando - my
.bashrc
, que era o padrão que você obtém em uma instância do AWS EC2 ubuntu, tinha essas linhas:
.
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
fazer isso source /home/ubuntu/.bashrc
não faria nada no cron job. Parece servir a um propósito, então não o removi completamente, mas substituí-o por:
# If not running interactively, don't do anything
if [ -z ${RUN_BASHRC+x} ]; then
echo "might return";
else
case $- in
*i*) ;;
*) return;;
esac
fi
o que me permitiu definir um sinalizador para ignorar esse retorno antecipado.
- Finalmente, por alguns motivos, o
PATH
ainda não foi atualizado corretamente. Eu poderia consertar isso fazendo:
.
ADDITIONAL_PATH=$(sudo -Hiu ubuntu env | grep -oP "^PATH=\K.*")
PATH=$ADDITIONAL_PATH:$PATH
Não tenho 100% de certeza do que isso faz :) mas no final tenho o mesmo que PATH
faria ao fazer login com ssh.
Então, finalmente:
crontab:
SHELL=/bin/bash
@reboot RUN_BASHRC=1 /home/ubuntu/startup.sh >> /home/ubuntu/cron-startup.logs
~/.bashrc
: a substituição acima
~/start.sh
:
#!/bin/bash
ADDITIONAL_PATH=$(sudo -Hiu ubuntu env | grep -oP "^PATH=\K.*")
PATH=$ADDITIONAL_PATH:$PATH
...