Come fare in modo che CRON chiami nei PATH corretti


124

Sto cercando di convincere cron a chiamare i PATH corretti. Quando eseguo uno script Python dalla shell, lo script funziona bene poiché utilizza i PATH impostati in bashrc ma quando uso cron tutti i PATH non vengono utilizzati da bashrc. Esiste un file in cui posso inserire i PATH per cron come bashrc o un modo per chiamare i PATH da bashrc?

Scusa, non penso di averlo formulato correttamente, posso far eseguire lo script corretto (il che significa che il PERCORSO dello script in crontab non è il problema qui), è solo quando quello script è in esecuzione eseguo una build e questo usa il PERCORSI impostati in .bashrc. Quando .bashrceseguo lo script quando ho effettuato l'accesso, i PERCORSI vengono inseriti. Poiché cron non viene eseguito in una shell per dire che non viene eseguito .bashrc. C'è un modo per estrarlo senza dover scrivere un wrapper di script bash?


hanno anche uno sguardo su suggerimento dato qui per sapere come ottenere le impostazioni bashrc al lavoro per cronjobs: stackoverflow.com/q/15557777/1025391
moooeeeep

2
Il comando magico, semplice e corretto per includere il tuo profilo nell'ambiente attuale è source /etc/profile, dovrebbe mangiare .bashrce un sacco di altre cose potenzialmente mancanti per te. Il sourcing esplicito del profilo diventa piuttosto utile se vuoi che alcuni script vengano eseguiti "autonomamente", protegge anche da ambienti strani e quindi ...
exa

1
@exa +100 Questo fa funzionare gli shscript chiamati da crontab. Puoi confermare che aggiorna il percorso aggiungendo un lavoro come * * * * * echo $PATH > ~/crontab_path.txte controllando il file dopo un minuto.
geoteoria

Risposte:


177

Ho usato /etc/crontab. Ho usato vie inserito i PATH di cui avevo bisogno in questo file e l'ho eseguito come root. Il normale crontab sovrascrive i PATH che hai impostato. Un buon tutorial su come farlo .

Il file cron a livello di sistema ha questo aspetto:

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

17
Funziona con crontab -e a livello di utente ed è anche più sicuro.
Robert Brisita,

2
Posso usare bash invece di sh?
qed

1
è strano (per me) che il PATH predefinito impostato in / etc / crontab come mostrato da @chrissygormley, e anche impostato nel mio crontab (Ubuntu), sia diverso dal percorso in / etc / environment, in particolare mette / sbin e / bin prima di / usr / sbin e / usr / bin. Ora l'ho cambiato nel mio / etc / crontab per renderlo uguale all'ambiente utente.
scoobydoo

Non funziona per me. Sto inviando il contenuto di cron a un file. Cron viene eseguito, il file viene creato ma non inserisce alcun contenuto.
Volatil3

2
Sembra che non tutti i percorsi impostati /etc/crontabsiano disponibili per cron durante l'esecuzione come root in Ubuntu 14.04. ( sudo crontab -e)
David Oliver,

50

Molto probabilmente, cron è in esecuzione in un ambiente molto scarso. Controlla le variabili di ambiente che cron sta utilizzando aggiungendo un lavoro fittizio che esegue il dump envin un file come questo:

* * * * * env > env_dump.txt

Confrontalo con l'output di envin una normale sessione di shell.

Puoi anteporre le tue variabili d'ambiente al crontab locale definendole all'inizio del tuo crontab.

Ecco una soluzione rapida per anteporre $PATHal crontab corrente:

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

Il crontab risultante sarà simile alla risposta di chrissygormley, con PATH definito prima delle regole di crontab.


22

Dovresti inserire percorsi completi nel tuo file crontab. Questa è l'opzione più sicura.
Se non vuoi farlo, puoi mettere uno script wrapper attorno ai tuoi programmi e impostare il PERCORSO lì dentro.

per esempio

01 01 * * * command

diventa:

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

Inoltre, qualsiasi cosa chiamata da crondovrebbe essere molto attenta ai programmi che esegue e probabilmente impostare la propria scelta per la PATHvariabile.

MODIFICARE:

Se non sai dove si trova il comando che vuoi eseguire which <command>dalla tua shell e ti dirà il percorso.

EDIT2:

Quindi, una volta che il programma è in esecuzione, la prima cosa che dovrebbe fare è impostare PATHe qualsiasi altra variabile richiesta (ad esempio LD_LIBRARY_PATH) sui valori richiesti per l'esecuzione dello script.
Fondamentalmente invece di pensare a come modificare l'ambiente cron per renderlo più adatto al tuo programma / script, fai in modo che il tuo script gestisca l'ambiente che gli è stato dato, impostandone uno appropriato all'avvio.


1
se è nel tuo percorso usa 'quale comando' e ti darà il percorso completo
Paul Whelan

@Douglas Leeder - Quando dici di mettere il percorso completo in cron, intendi metterlo in crontab o in un altro file? Se è così, come faresti se il comando cron è: '01 01 * * * comando '. Grazie
chrissygormley

@chrissygormley - Sì crontab.
Douglas Leeder

Spiacente, deve esserci un po 'di confusione. Ho riformulato la domanda sopra.
Chrissygormley

16

L'impostazione di PATH subito prima della riga di comando nel mio crontab ha funzionato per me:

* * * * * PATH=$PATH:/usr/local/bin:/path/to/some/thing

preferisco in questo modo. o specificare il percorso completo dello script.
zw963

5
Non credo che il percorso continuerà a crescere, ogni volta che verrà eseguito sarà un nuovo ambiente, con una nuova copia di PATH ...
jjcf89

Posso confermare che @ jjcf89 è corretto, PATH è aggiornato ad ogni esecuzione.
electrovir

14

L'aggiunta di una definizione PATH nel crontab dell'utente con i valori corretti aiuterà ... Ho riempito il mio con solo:

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

Ed è sufficiente per far funzionare tutti i miei script ... Includere qualsiasi percorso personalizzato se necessario.


1
Per un utente crontab questa dovrebbe essere la risposta corretta. Non tutti su un sistema possono modificare /etc/crontab. Questa è la risposta più semplice a livello di utente. Buon lavoro @ Treviño. Vota questo se sei d'accordo.
frederickjh

14

Fai in modo che le tue variabili funzionino per te, questo consentirà l'accesso t

Definisci il tuo PERCORSO in /etc/profile.d/*.sh

Variabili di ambiente a livello di sistema

I file con estensione .sh nella directory /etc/profile.d vengono eseguiti ogni volta che viene inserita una shell di login bash (ad es. Quando si accede dalla console o tramite ssh), nonché dal DisplayManager quando viene caricata la sessione desktop.

Ad esempio, puoi creare il file /etc/profile.d/myenvvars.sh e impostare variabili in questo modo:

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

Esegui crontab con l'opzione di accesso!

CRONTAB esegue lo script o il comando con le variabili d'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

11

Problema

Il tuo script funziona quando lo esegui dalla console ma fallisce in cron.

Causa

Il tuo crontab non ha le variabili del percorso corretto (e forse la shell)

Soluzione

Aggiungi la tua shell corrente e traccia il crontab

Script per farlo per te

#!/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

Output di esempio

output di esempio add_curent_shell_and_path_to_crontab.sh


3

Sul mio AIX cron raccoglie le sue variabili ambientali da / etc / environment ignorando ciò che è impostato nel .profile.

Modifica: ho anche controllato un paio di scatole Linux di varie età e anche queste sembrano avere questo file, quindi questo probabilmente non è specifico di AIX.

L'ho verificato usando il suggerimento cron di joemaller e controllando l'output prima e dopo aver modificato la variabile PATH in / etc / environment.


3

Se non vuoi dover apportare le stesse modifiche in vari punti, fai più o meno questo:

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

Il . spazio e quindi il percorso per .bashrc e il comando && sono la magia lì per portare le modifiche all'ambiente nella shell bash in esecuzione. Inoltre, se vuoi davvero che la shell sia bash, è una buona idea avere una riga nel tuo crontab:

SHELL=/bin/bash

Spero che aiuti qualcuno!


2

L'ambiente predefinito per i cron job è molto scarso e potrebbe essere molto diverso dall'ambiente in cui si sviluppano gli script python. Per uno script che potrebbe essere eseguito in cron, qualsiasi ambiente da cui si dipende deve essere impostato esplicitamente. Nello stesso file cron, includi i percorsi completi agli eseguibili Python e agli script Python.


2

So che è già stata data una risposta, ma ho pensato che il suo sarebbe stato utile ad alcuni. Ho avuto un problema simile che ho risolto di recente ( trovato qui ) ed ecco i punti salienti dei passaggi che ho seguito per rispondere a questa domanda:

  1. assicurati di avere le variabili di cui hai bisogno in PYTHONPATH (trovate qui e qui e per maggiori informazioni qui) all'interno di .profile o .bash_profile per qualsiasi shell in cui desideri testare il tuo script per assicurarti che funzioni.

  2. modifica il tuo crontab per includere le directory necessarie per eseguire il tuo script in un cron job (trovato qui e qui)

    a) assicurati di includere la directory root nella variabile PATH (.) come spiegato qui (in pratica se stai eseguendo un eseguibile con il tuo comando deve essere in grado di trovare root o la directory in cui è memorizzato l'eseguibile) e probabilmente questi (/ sbin: bin /: / usr / sbin: / usr / bin)

  3. nel tuo file crontab, crea un cronjob che cambierà la directory nella directory in cui hai eseguito con successo lo script in precedenza (cioè Users / user / Documents / foo)

    a) Questo sarà simile al seguente:

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

2

@Trevino: la tua risposta mi ha aiutato a risolvere il mio problema. Tuttavia, per un principiante, cercando di dare un approccio graduale.

  1. Ottieni la tua attuale installazione di java tramite $ echo $JAVA_HOME
  2. $ crontab -e
  3. * * * * * echo $PATH- questo ti consente di capire qual è il valore PATH attualmente utilizzato da crontab. Esegui crontab e prendi il valore $ PATH usato da crontab.
  4. Ora modifica nuovamente crontab per impostare il percorso del bin java desiderato: a) crontab -e; b) PATH=<value of $JAVA_HOME>/bin:/usr/bin:/bin(è un percorso di esempio); c) ora il tuo lavoro / script pianificato come */10 * * * * sh runMyJob.sh &; d) rimuovi echo $PATHda crontab perché non è necessario ora.

2

Imposta il PERCORSO richiesto nel tuo cron

crontab -e

Modifica: premere i

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

10 * * * * your_command

Salva ed esci :wq


1

La soluzione più semplice che ho trovato è simile a questa:

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

Questo esempio invoca sucome utente root e avvia la shell con l'ambiente completo dell'utente, incluso $ PATH, impostato come se fosse loggato. Funziona allo stesso modo su diverse distribuzioni, è più affidabile del sourcing .bashrc (che non ha funzionato per me) ed evita di codificare percorsi specifici che possono essere un problema se si fornisce un esempio o uno strumento di configurazione e non si sa quale distribuzione o layout di file sul sistema dell'utente.

Puoi anche specificare il nome utente dopo suse desideri un utente diverso da root, ma probabilmente dovresti lasciare il rootparametro prima del sucomando poiché questo garantisce suprivilegi sufficienti per passare a qualsiasi utente specificato.


-3

Se usi, webminquesti sono i passaggi per impostare il PATHvalore:

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.