Dov'è impostato il PATH di cron?


34

Cron non usa il percorso dell'utente di cui è crontab e, invece, ha il suo. Può essere facilmente modificato aggiungendo PATH=/foo/barall'inizio del crontab, e la soluzione alternativa classica è quella di utilizzare sempre percorsi assoluti ai comandi eseguiti da cron, ma dove è definito il PERCORSO predefinito di cron?

Ho creato un crontab con i seguenti contenuti sul mio sistema Arch (cronie 1.5.1-1) e testato anche su una scatola Ubuntu 16.04.3 LTS con gli stessi risultati:

$ crontab -l
* * * * * echo "$PATH" > /home/terdon/fff

Quello stampato:

$ cat fff
/usr/bin:/bin

Ma perché? Il percorso predefinito a livello di sistema è impostato /etc/profile, ma include altre directory:

$ grep PATH= /etc/profile
PATH="/usr/local/sbin:/usr/local/bin:/usr/bin"

Non c'è nient'altro di rilevante in /etc/environmento /etc/profile.d, gli altri file che pensavo potessero essere letti da cron:

$ grep PATH= /etc/profile.d/* /etc/environment
/etc/profile.d/jre.sh:export PATH=${PATH}:/usr/lib/jvm/default/bin
/etc/profile.d/mozilla-common.sh:export MOZ_PLUGIN_PATH="/usr/lib/mozilla/plugins"
/etc/profile.d/perlbin.sh:[ -d /usr/bin/site_perl ] && PATH=$PATH:/usr/bin/site_perl
/etc/profile.d/perlbin.sh:[ -d /usr/lib/perl5/site_perl/bin ] && PATH=$PATH:/usr/lib/perl5/site_perl/bin
/etc/profile.d/perlbin.sh:[ -d /usr/bin/vendor_perl ] && PATH=$PATH:/usr/bin/vendor_perl
/etc/profile.d/perlbin.sh:[ -d /usr/lib/perl5/vendor_perl/bin ] && PATH=$PATH:/usr/lib/perl5/vendor_perl/bin
/etc/profile.d/perlbin.sh:[ -d /usr/bin/core_perl ] && PATH=$PATH:/usr/bin/core_perl

Non c'è nulla di rilevante in nessuno dei file /etc/skel, non sorprende, né viene impostato in alcun /etc/cron*file:

$ grep PATH /etc/cron* /etc/cron*/*
grep: /etc/cron.d: Is a directory
grep: /etc/cron.daily: Is a directory
grep: /etc/cron.hourly: Is a directory
grep: /etc/cron.monthly: Is a directory
grep: /etc/cron.weekly: Is a directory
/etc/cron.d/0hourly:PATH=/sbin:/bin:/usr/sbin:/usr/bin

Quindi, dove viene impostato il PATH predefinito di cron per i crontab dell'utente? È codificato in cronsé? Non legge una sorta di file di configurazione per questo?


3
Non c'è motivo crondi guardare /etc/profileo preoccuparsi di una particolare shell. Una domanda migliore è perché non cronlegge PATHda login.defs(su Linux) o login.conf(su * BSD). Suppongo che alla fine sia un dettaglio di implementazione.
Satō Katsura,

@ SatōKatsura certo, ho menzionato solo /etc/profileperché usa la stessa sintassi ( var=value) di se cronstesso, quindi sarebbe abbastanza facile da fare ed /etc/profileè, per quanto ne sappia , molto diffuso. Ciò che mi ha sorpreso è che non riuscivo a trovarlo impostato da nessuna parte, quindi sembrava che fosse codificato. Come è vero, come ha spiegato Stephen di seguito.
terdon

zsh/etc/profilebash
Alle

2
@BasileStarynkevitch no, non è specifico per bash a tutti ! Al contrario! Mentre ci sono alcune shell che non lo leggono (la famiglia di c-shell AFAIK), zsh non è uno di questi. Vedi la manpage di zsh, se non mi credi. In ogni caso, le shell interattive sono irrilevanti poiché i vari profilefile vengono comunque letti solo dalle shell di login. Questi possono o meno essere interattivi.
terdon

1
A volte l'esecuzione stringssu un programma può aiutare a trovare anche questi valori codificati.
jrw32982 supporta Monica il

Risposte:


47

È codificato nel codice sorgente (quel collegamento punta all'attuale Debian cron- data la varietà di cronimplementazioni, è difficile sceglierne una, ma altre implementazioni sono probabilmente simili):

#ifndef _PATH_DEFPATH
# define _PATH_DEFPATH "/usr/bin:/bin"
#endif

#ifndef _PATH_DEFPATH_ROOT
# define _PATH_DEFPATH_ROOT "/usr/sbin:/usr/bin:/sbin:/bin"
#endif

cronnon legge i percorsi predefiniti da un file di configurazione; Immagino che il ragionamento sia che supporta la specifica di percorsi già in uso PATH=in qualsiasi cronjob, quindi non è necessario essere in grado di specificare un valore predefinito altrove. (L'impostazione predefinita codificata viene utilizzata se nient'altro specifica un percorso in una voce di lavoro .)


Nota che, nonostante l'esistenza di _PATH_DEFPATH_ROOTdefine, ho confermato (usando un cron job di echo $PATH > /testfile) dopo aver modificato il crontab di root usando crontab -esu Debian Stretch che usa anche il crontab di root _PATH_DEFPATH, cioè "/ usr / bin: / bin", no _PATH_DEFPATH_ROOT . Ciò è confermato anche dal secondo link al codice sorgente in questa risposta (in cui _PATH_DEFPATH_ROOTnon viene utilizzato). Non mi è chiaro se questa definizione orfana sia un bug.
njahnke

8

L'aggiunta alla risposta di Stephen Kitt, c'è un file di configurazione che imposta PATHper cron su Ubuntu, e cron ignora che PATHusare quello di default hard-coded (o PATHS Impostare nelle crontab stessi). Il file è /etc/environment. Nota cronconfigurazione PAM:

$ cat /etc/pam.d/cron
...   
# Read environment variables from pam_env's default files, /etc/environment
# and /etc/security/pam_env.conf.
session       required   pam_env.so

# In addition, read system locale information
session       required   pam_env.so envfile=/etc/default/locale
...

Questo è facilmente verificabile. Aggiungi una variabile /etc/environment, diciamo foo=bar, env > /tmp/fooeseguilo come cronjob e guarda come foo=barappare nell'output.


Ma perché? Il percorso predefinito a livello di sistema è impostato in / etc / profile, ma include altre directory:

$ grep PATH= /etc/profile
PATH="/usr/local/sbin:/usr/local/bin:/usr/bin"

Questo è vero in Arch Linux, ma in Ubuntu PATHè impostata la base /etc/environment. File /etc/profile.desistenti su un esistente PATHe puoi accedervi in ~/.pam_environment. Ho presentato un bug sul comportamento di Arch .

Sfortunatamente, /etc/pam.d/cronnon include la lettura di ~/.pam_environment. Stranamente, /etc/pam.d/atd fa comprendere quel file:

$ cat /etc/pam.d/atd
#
# The PAM configuration file for the at daemon
#

@include common-auth
@include common-account
session    required   pam_loginuid.so
@include common-session-noninteractive
session    required   pam_limits.so
session    required   pam_env.so user_readenv=1

... ma i comandi eseguiti atapparentemente ereditano l'ambiente disponibile durante la creazione del atlavoro (ad esempio, env -i /usr/bin/at ...sembra che esegua lavori con un ambiente molto pulito).

La modifica /etc/pam.d/crondi avere user_readenv=1sembra non causare problemi e le variabili in hanno ~/.pam_environmentiniziato a presentarsi bene (tranne PATH, ovviamente).


Tutto sommato, l'impostazione delle variabili di ambiente per cron sembra essere un casino. Il posto migliore sembra essere nelle specifiche del lavoro stesso, anche solo perché non si sa quali variabili d'ambiente ereditate cron potrebbe decidere di ignorare (senza leggere l'origine).


Per quanto riguarda i atlavori, se si scarica un atlavoro, si vedrà che imposta esplicitamente l'ambiente affinché corrisponda all'ambiente al momento della creazione del lavoro.
Stephen Kitt,
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.