Carregar variáveis de ambiente de usuários em um cronjob

4

Como posso carregar as variáveis de ambiente dos usuários em um cronjob?

Eu tenho um cronjob que deve iniciar um script a cada minuto na minha máquina Ubuntu:

* * * * * /home/user/myscript.sh;

Neste script, quero usar variáveis de ambiente como $JAVA_HOME e $M2_HOME para iniciar automaticamente um processo de criação. O problema é que essas variáveis são definidas no .bashrc via export JAVA_HOME=/../.. .

Portanto, eu source desses arquivos antes de executar meu script:

* * * * * source ~/.bash_profile; source ~/.bashrc; /home/user/myscript.sh;

No entanto, as variáveis não estão definidas! Para testar isso eu echo as variáveis de ambiente via env para um arquivo de log:

env >> ~/env.log
echo $M2_HOME >> ~/env.log

O arquivo de log ainda não contém as variáveis. Somente o seguinte é anexado ao arquivo (no $M2_HOME etc.):

LANGUAGE=en_US:en
HOME=/home/user
LOGNAME=user
PATH=/usr/bin:/bin
LANG=en_US.UTF-8
SHELL=/bin/sh
PWD=/home/user

Se eu executar o script diretamente no meu shell, todas as variáveis serão impressas em env.log .

O mesmo acontece quando eu coloco os comandos source no arquivo de script. Somente se eu remover a palavra-chave export antes da declaração da variável, ela ficará visível pelo comando echo $var . Mas isso não é uma solução porque não gerencio essas declarações.

Eu tentei a solução de @tripplee com o problema limitado da shell sh, mas ainda não funciona. Eu reduzi ainda mais para um cronjob muito simples, sem um segundo script para mostrar a problemática:

* * * * * . $HOME/.bash_profile; . $HOME/.bashrc; env > $HOME/env.log;

cat /home/user/env.log :

LANGUAGE=en_US:en
HOME=/home/user
LOGNAME=user
PATH=/usr/bin:/bin
LANG=en_US.UTF-8
SHELL=/bin/sh
PWD=/home/user
    
por Sebastian Barth 06.03.2015 / 13:30

3 respostas

4

A sintaxe da tarefa cron é restrita a sh , portanto você não pode usar os Bashisms como ~ . Felizmente, a correção é fácil - basta substituí-la por $HOME . Da mesma forma, source precisa ser substituído por . (apenas um ponto).

É claro que os scripts que você fonte não deve usar a sintaxe Bash, se você pretende usá-los a partir de sh . Provavelmente, a correção mais fácil é migrar essas coisas para o script (ou criar um script de wrapper para o Cron ser executado).

Como dentro do seu script, você pode usar bash , se desejar, desde que a linha shebang esteja corretamente #!/bin/bash (ajuste o caminho se for necessário) em vez de #!/bin/sh .

Se você não gostar disso, por algum motivo, poderá inserir o Bash no arquivo crontab , especificando-o explicitamente:

* * * * * bash -c 'source ~/.bash_profile; source ~/.bashrc; ./myscript.sh'

Você deve conseguir ver source: command not found e export: command not found nos e-mails enviados por cron quando as coisas dão errado. Examinar a saída do erro é realmente importante para a solução de problemas.

Claro, se você tiver o padrão .bashrc no Ubuntu, ele será liberado imediatamente se você tentar obtê-lo a partir de um script não interativo. Talvez seja melhor colocar as configurações que você deseja em um uso não interativo em outro arquivo (talvez .profile , que será lido por sh por padrão)?

    
por 06.03.2015 / 13:54
4

Para adicionar a resposta de tripleee, você pode fazer com que todos os seus crons sejam avaliados no bash (ou no shell de sua escolha) especificando o shell no crontab.

SHELL=/bin/bash
* * * * * . $HOME/.bash_profile; . $HOME/.bashrc; env > $HOME/env.log;

edite e se você realmente quiser ver o que está fazendo, o seguinte comando deve torná-lo suficientemente detalhado:

/bin/bash -x -c '. $HOME/.bash_profile; . $HOME/.bashrc; env > $HOME/env.log' > /tmp/cron.'date +\%s' 

set -x ou o sinalizador -x na linha de comando fará com que a maioria das camadas imprima todas as linhas avaliadas.

Para testar na linha de comando, remova o comando \ from the date. Isso é necessário para evitar que o cron avalie% s como entrada padrão.

    
por 06.03.2015 / 14:44
0

Você não tem um tty completo no cron . Mas se você rodar via sudo -i você terá um.

* * * * * sudo -u user -i bash -c '. $HOME/.bash_profile; . $HOME/.bashrc; env > $HOME/env.log;'

Ou para iniciar o script:

* * * * * sudo -u user -i bash -c '. $HOME/.bash_profile; . $HOME/.bashrc; /home/user/myscript.sh;'

Se você colocar os comandos source em um script Bash que inicia o script de destino, você terá uma boa aparência:

* * * * * sudo -u user -i /home/user/mystarter.sh;
    
por 06.03.2015 / 14:47