Como fazer com que o CRON chame os PATHs corretos

124

Estou tentando fazer com que o cron chame os PATHs corretos. Quando executo um script Python a partir do shell, o script funciona bem, pois usa os PATHs definidos no bashrc, mas quando eu uso o cron, todos os PATHs não são usados ​​no bashrc. Existe um arquivo no qual eu possa inserir os PATHs para o cron como bashrc ou uma maneira de chamar os PATHs a partir do bashrc?

Desculpe, acho que não escrevi isso corretamente, posso executar o script correto (o que significa que o PATH para o script no crontab não é o problema aqui); é apenas quando esse script está sendo executado que eu executo uma compilação e isso usa o CAMINHOS definidos .bashrc. Quando executo o script quando estou logado, os .bashrcPATHs são puxados. Como o cron não roda em um shell, por exemplo, ele não puxa .bashrc. Existe uma maneira de extrair isso sem precisar escrever um wrapper de script bash?

chrissygormley
fonte
também ter um olhar para a sugestão dada aqui para saber como obter as configurações bashrc de trabalho para cronjobs: stackoverflow.com/q/15557777/1025391
moooeeeep
2
O comando mágico, simples e correto de incluir seu perfil no ambiente atual é source /etc/profile: ele deve comer .bashrce muitas outras coisas potencialmente ausentes para você. O fornecimento explícito de perfis se torna bastante útil se você deseja que alguns scripts executem "autônomo", ele também protege de ambientes estranhos e ...
exa
1
@exa +100 Isso faz com que shscripts chamados pelo crontab funcionem. Você pode confirmar se ele atualiza o caminho adicionando um trabalho como * * * * * echo $PATH > ~/crontab_path.txte verificando o arquivo após um minuto.
geotheory

Respostas:

177

Eu usei /etc/crontab. Eu usei vie entrei nos CAMINHOS que eu precisava nesse arquivo e o executei como root. O crontab normal substitui os PATHs que você configurou. Um bom tutorial sobre como fazer isso .

O arquivo cron em todo o sistema se parece com o seguinte:

This has the username field, as used by /etc/crontab.
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file.
# This file also has a username field, that none of the other crontabs do.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow user   command
42 6 * * *   root    run-parts --report /etc/cron.daily
47 6 * * 7   root    run-parts --report /etc/cron.weekly
52 6 1 * *   root    run-parts --report /etc/cron.monthly
01 01 * * 1-5 root python /path/to/file.py
chrissygormley
fonte
17
Isso funciona com o crontab -e no nível do usuário e é mais seguro também.
Robert Brisita 5/09/2013
2
Posso usar o bash em vez de sh?
qed
1
é estranho (para mim) que o PATH padrão definido em / etc / crontab, como mostrado por @chrissygormley, e também definido em meu (Ubuntu) crontab, seja diferente do caminho em / etc / environment, especificamente ele coloca / sbin e / bin à frente de / usr / sbin e / usr / bin. Agora mudei isso no meu / etc / crontab para torná-lo o mesmo que o ambiente do usuário.
22415 scoobydoo
Não está funcionando para mim .. Estou enviando conteúdo cron para um arquivo. Cron é executado, o arquivo cria, mas não está colocando nenhum conteúdo nele.
Volatil3
2
Parece que nem todos os caminhos definidos /etc/crontabestão disponíveis para cron quando executados como root no Ubuntu 14.04. ( sudo crontab -e)
David Oliver
50

Provavelmente, o cron está sendo executado em um ambiente muito escasso. Verifique as variáveis ​​de ambiente que o cron está usando, anexando um trabalho fictício que despeja envem um arquivo como este:

* * * * * env > env_dump.txt

Compare isso com a saída de envem uma sessão shell normal.

Você pode anexar suas próprias variáveis ​​de ambiente ao crontab local, definindo-as na parte superior do seu crontab.

Aqui está uma solução rápida para anexar $PATHao crontab atual:

# echo PATH=$PATH > tmp.cron
# echo >> tmp.cron
# crontab -l >> tmp.cron
# crontab tmp.cron

O crontab resultante será semelhante à resposta de chrissygormley, com PATH definido antes das regras do crontab.

joemaller
fonte
22

Você deve colocar caminhos completos no seu arquivo crontab. Essa é a opção mais segura.
Se você não quiser fazer isso, pode colocar um script de wrapper em torno de seus programas e definir o PATH lá.

por exemplo

01 01 * * * command

torna-se:

01 01 * * * /full/path/to/command

Além disso, qualquer coisa chamada from crondeve ter muito cuidado com os programas executados e provavelmente definir sua própria opção para a PATHvariável.

EDITAR:

Se você não souber onde está o comando que deseja executar a which <command>partir do seu shell, ele informará o caminho.

EDIT2:

Portanto, quando seu programa estiver em execução, a primeira coisa que ele deve fazer é definir PATHe qualquer outra variável necessária (por exemplo LD_LIBRARY_PATH) os valores necessários para a execução do script.
Basicamente, em vez de pensar em como modificar o ambiente cron para torná-lo mais adequado ao seu programa / script - faça seu script manipular o ambiente fornecido, definindo um apropriado quando ele for iniciado.

Douglas Leeder
fonte
1
se o seu em seu uso caminho 'que comando' e ele vai te dar o caminho completo
Paul Whelan
@ Douglas Leeder - Quando você diz colocar o caminho completo no cron, você quer dizer colocá-lo no crontab ou em outro arquivo? Se é assim, como você faria isso se o comando cron for: '01 01 * * * command '. Graças
chrissygormley
@chrissygormley - Sim crontab.
Douglas Leeder
Desculpe, deve haver alguma confusão. Eu reformulei a pergunta acima.
precisa saber é o seguinte
16

Definir PATH antes da linha de comando no meu crontab funcionou para mim:

* * * * * PATH=$PATH:/usr/local/bin:/path/to/some/thing
myrho
fonte
prefiro assim. ou especifique o caminho completo do script.
precisa saber é o seguinte
5
Eu não acho que o caminho vai continuar a crescer, cada vez que seu funcionamento será um novo ambiente, com uma nova cópia do PATH ...
jjcf89
Pode confirmar que @ jjcf89 está correto, PATH é atualizado a cada execução.
Electrovir
14

Adicionar uma definição PATH no crontab do usuário com os valores corretos ajudará ... Enchi a minha apenas:

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

E é suficiente para que todos os meus scripts funcionem ... Inclua qualquer caminho personalizado lá, se necessário.

Treviño
fonte
1
Para um usuário crontab, esta deve ser a resposta correta. Nem todo mundo em um sistema pode editar /etc/crontab. Essa é a resposta mais fácil no nível do usuário. Bom trabalho @ Treviño. Vote se concordar.
Frederickjh
14

Faça com que suas variáveis ​​funcionem para você, isso permitirá o acesso a t

Defina seu PATH em /etc/profile.d/*.sh

Variáveis ​​de ambiente em todo o sistema

Arquivos com a extensão .sh no diretório /etc/profile.d são executados sempre que um shell de logon do bash é inserido (por exemplo, ao fazer login no console ou através do ssh), bem como pelo DisplayManager quando a sessão da área de trabalho é carregada.

Você pode, por exemplo, criar o arquivo /etc/profile.d/myenvvars.sh e definir variáveis ​​como esta:

export JAVA_HOME=/usr/lib/jvm/jdk1.7.0
export PATH=$PATH:$JAVA_HOME/bin

Execute o crontab com a opção de login!

CRONTAB executa script ou comando com variáveis ​​de ambiente

0 9 * * * cd /var/www/vhosts/foo/crons/; bash -l -c 'php -f ./download.php'
0 9 * * * cd /var/www/vhosts/foo/crons/; bash -l -c download.sh
Artistan
fonte
11

Problema

Seu script funciona quando você o executa no console, mas falha no cron.

Causa

Seu crontab não possui as variáveis ​​de caminho corretas (e possivelmente shell)

Solução

Adicione seu shell atual e localize o crontab

Script para fazer isso por você

#!/bin/bash
#
# Date: August 22, 2013
# Author: Steve Stonebraker
# File: add_current_shell_and_path_to_crontab.sh
# Description: Add current user's shell and path to crontab
# Source: http://brakertech.com/add-current-path-to-crontab
# Github: hhttps://github.com/ssstonebraker/braker-scripts/blob/master/working-scripts/add_current_shell_and_path_to_crontab.sh

# function that is called when the script exits (cleans up our tmp.cron file)
function finish { [ -e "tmp.cron" ] && rm tmp.cron; }

#whenver the script exits call the function "finish"
trap finish EXIT

########################################
# pretty printing functions
function print_status { echo -e "\x1B[01;34m[*]\x1B[0m $1"; }
function print_good { echo -e "\x1B[01;32m[*]\x1B[0m $1"; }
function print_error { echo -e "\x1B[01;31m[*]\x1B[0m $1"; }
function print_notification { echo -e "\x1B[01;33m[*]\x1B[0m $1"; }
function printline { 
  hr=-------------------------------------------------------------------------------------------------------------------------------
  printf '%s\n' "${hr:0:${COLUMNS:-$(tput cols)}}"
}
####################################
# print message and exit program
function die { print_error "$1"; exit 1; }

####################################
# user must have at least one job in their crontab
function require_gt1_user_crontab_job {
        crontab -l &> /dev/null
        [ $? -ne 0 ] && die "Script requires you have at least one user crontab job!"
}


####################################
# Add current shell and path to user's crontab
function add_shell_path_to_crontab {
    #print info about what's being added
    print_notification "Current SHELL: ${SHELL}"
    print_notification "Current PATH: ${PATH}"

    #Add current shell and path to crontab
    print_status "Adding current SHELL and PATH to crontab \nold crontab:"

    printline; crontab -l; printline

    #keep old comments but start new crontab file
    crontab -l | grep "^#" > tmp.cron

    #Add our current shell and path to the new crontab file
    echo -e "SHELL=${SHELL}\nPATH=${PATH}\n" >> tmp.cron 

    #Add old crontab entries but ignore comments or any shell or path statements
    crontab -l | grep -v "^#" | grep -v "SHELL" | grep -v "PATH" >> tmp.cron

    #load up the new crontab we just created
    crontab tmp.cron

    #Display new crontab
    print_good "New crontab:"
    printline; crontab -l; printline
}

require_gt1_user_crontab_job
add_shell_path_to_crontab

Fonte

https://github.com/ssstonebraker/braker-scripts/blob/master/working-scripts/add_current_shell_and_path_to_crontab.sh

Saída de amostra

saída de exemplo add_curent_shell_and_path_to_crontab.sh

brakertech
fonte
3

No meu AIX, o cron seleciona suas variáveis ​​ambientais em / etc / environment, ignorando o que está definido no .profile.

Edit: Eu também fiz check-out de algumas caixas Linux de várias idades e estas também parecem ter esse arquivo, portanto, isso provavelmente não é específico do AIX.

Eu verifiquei isso usando a sugestão cron do joemaller e verificando a saída antes e depois da edição da variável PATH em / etc / environment.

Van Amburg
fonte
3

Se você não quiser fazer as mesmas edições em vários lugares, faça o seguinte:

* * * * * . /home/username/.bashrc && yourcommand all of your args

O . espaço e, em seguida, o caminho para .bashrc e o comando && são a mágica para fazer com que seu ambiente mude para o shell bash em execução. Além disso, se você realmente deseja que o shell seja básico, é uma boa idéia ter uma linha no seu crontab:

SHELL=/bin/bash

Espero que ajude alguém!

Wade Chandler
fonte
2

O ambiente padrão para tarefas cron é muito escasso e pode ser muito diferente do ambiente em que você desenvolve seus scripts python. Para um script que pode ser executado no cron, qualquer ambiente do qual você dependa deve ser definido explicitamente. No próprio arquivo cron, inclua caminhos completos para os executáveis ​​python e seus scripts python.

multidão
fonte
2

Sei que isso já foi respondido, mas achei que o dele seria útil para alguns. Eu tive um problema semelhante que resolvi recentemente ( encontrado aqui ) e aqui estão os destaques das etapas que eu segui para responder a essa pergunta:

  1. verifique se você possui as variáveis ​​necessárias em PYTHONPATH (encontradas aqui e aqui e para obter mais informações aqui) dentro do .profile ou .bash_profile para qualquer shell em que você queira testar seu script para garantir que ele funcione.

  2. edite seu crontab para incluir os diretórios necessários para executar seu script em um trabalho cron (encontrado aqui e aqui)

    a) certifique-se de incluir o diretório raiz na variável PATH (.), conforme explicado aqui (basicamente, se você estiver executando um executável com seu comando, ele precisará encontrar o diretório raiz ou o diretório em que o executável está armazenado) e provavelmente estes (/ sbin: / bin: / usr / sbin: / usr / bin)

  3. no seu arquivo crontab, crie um cronjob que altere o diretório para o diretório em que você executou o script com êxito antes (ou seja, Usuários / usuário / Documentos / foo)

    a) Será semelhante ao seguinte:

    * * * * cd /Users/user/Documents/foo; bar -l doSomething -v 
    
derigible
fonte
2

@ Trevino: sua resposta me ajudou a resolver meu problema. No entanto, para um iniciante, tente dar uma abordagem passo a passo.

  1. Obtenha sua instalação atual do java via $ echo $JAVA_HOME
  2. $ crontab -e
  3. * * * * * echo $PATH- isso permite que você entenda qual é o valor PATH que está sendo usado pelo crontab no momento. Execute o crontab e pegue o valor $ PATH usado pelo crontab.
  4. Agora edite o crontab novamente para definir o caminho do java bin desejado: a) crontab -e; b) PATH=<value of $JAVA_HOME>/bin:/usr/bin:/bin(é um caminho de amostra); c) agora, como seu trabalho / script agendado */10 * * * * sh runMyJob.sh &; d) remova echo $PATHdo crontab como não é necessário agora.
Ram Dwivedi
fonte
2

Defina o PATH necessário em seu cron

crontab -e

Editar: Pressione i

PATH=/usr/local/bin:/usr/local/:or_whatever

10 * * * * your_command

Salvar e sair :wq

Yogesh Yadav
fonte
1

A solução mais simples que encontrei se parece com isso:

* * * * * root su -l -c command

Este exemplo chama sucomo usuário root e inicia o shell com o ambiente completo do usuário, incluindo $ PATH, definido como se eles estivessem conectados. Funciona da mesma forma em distros diferentes, é mais confiável do que fornecer. me) e evita caminhos específicos codificados, o que pode ser um problema se você estiver fornecendo um exemplo ou ferramenta de configuração e não souber qual distribuição ou layout de arquivo no sistema do usuário.

Você também pode especificar o nome de usuário depois suse desejar um usuário diferente do root, mas provavelmente deverá deixar o rootparâmetro before sucommand, pois isso garante suprivilégios suficientes para alternar para qualquer usuário especificado.


fonte
-3

Se você usar webmin, estas são as etapas de como definir o PATHvalor:

System
  -> Scheduled Cron Jobs
       -> Create a new environment variable
            -> For user: <Select the user name>
            -> Variable name: PATH
            -> Value: /usr/bin:/bin:<your personal path>
            -> Add environment variable: Before all Cron jobs for user
Peter VARGA
fonte