So bringen Sie CRON dazu, die richtigen Pfade einzugeben

124

Ich versuche, Cron dazu zu bringen, die richtigen Pfade einzugeben. Wenn ich ein Python-Skript über die Shell ausführe, läuft das Skript einwandfrei, da es die in bashrc festgelegten PATHs verwendet. Wenn ich jedoch cron verwende, werden nicht alle PATHs über bashrc verwendet. Gibt es eine Datei, in die ich die PATHs für cron wie bashrc eingeben kann, oder eine Möglichkeit, die PATHs von bashrc aus aufzurufen?

Es tut mir leid, ich glaube nicht, dass ich das richtig formuliert habe. Ich kann das richtige Skript ausführen (was bedeutet, dass der Pfad zum Skript in crontab hier nicht das Problem ist). Nur wenn dieses Skript ausgeführt wird, führe ich einen Build aus und dies verwendet das Pfade setzen ein .bashrc. Wenn ich das Skript beim .bashrcAnmelden ausführe , werden die Pfade eingezogen. Da cron nicht in einer Shell ausgeführt wird, wird es nicht eingezogen .bashrc. Gibt es eine Möglichkeit, dies zu erreichen, ohne einen Bash-Script-Wrapper schreiben zu müssen?

chrissygormley
quelle
Schauen Sie sich auch den hier gegebenen Vorschlag an, wie die bashrc-Einstellungen für Cronjobs funktionieren
moooeeeep
2
Der magische, einfache und korrekte Befehl, Ihr Profil in die aktuelle Umgebung aufzunehmen, lautet source /etc/profile: Es sollte essen .bashrcund viele andere potenziell fehlende Dinge für Sie. Explizites Profil-Sourcing wird sehr nützlich, wenn einige Skripte "eigenständig" ausgeführt werden sollen. Es schützt auch vor seltsamen Umgebungen und so ...
exa
1
@exa +100 Damit shfunktionieren von crontab aufgerufene Skripte. Sie können bestätigen, dass der Pfad aktualisiert wird, indem Sie einen Job wie hinzufügen * * * * * echo $PATH > ~/crontab_path.txtund die Datei nach einer Minute überprüfen.
Geotheory

Antworten:

177

Ich habe benutzt /etc/crontab. Ich vihabe die benötigten Pfade verwendet und in diese Datei eingegeben und sie als root ausgeführt. Die normale Crontab überschreibt die von Ihnen eingerichteten Pfade. Ein gutes Tutorial dazu .

Die systemweite Cron-Datei sieht folgendermaßen aus:

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
quelle
17
Dies funktioniert mit crontab -e auf Benutzerebene und ist auch auf diese Weise sicherer.
Robert Brisita
2
Kann ich bash anstelle von sh verwenden?
Qed
1
Es ist seltsam (für mich), dass der Standardpfad, der in / etc / crontab festgelegt ist, wie von @chrissygormley gezeigt, und auch in meinem (Ubuntu) crontab festgelegt ist, sich vom Pfad in / etc / environment unterscheidet, insbesondere in / sbin und / bin vor / usr / sbin und / usr / bin. Ich habe dies jetzt in meiner / etc / crontab geändert, damit es mit der Benutzerumgebung identisch ist.
Scoobydoo
Funktioniert nicht für mich. Ich gebe Cron-Inhalte in eine Datei aus. Cron wird ausgeführt, eine Datei wird erstellt, es werden jedoch keine Inhalte eingefügt.
Volatil3
2
Es scheint, dass nicht alle eingestellten Pfade /etc/crontabfür cron verfügbar sind, wenn sie als Root in Ubuntu 14.04 ausgeführt werden. ( sudo crontab -e)
David Oliver
50

Cron läuft höchstwahrscheinlich in einer sehr spärlichen Umgebung. Überprüfen Sie die Umgebungsvariablen, die cron verwendet, indem Sie einen Dummy-Job anhängen, der envan eine Datei wie diese ausgegeben wird :

* * * * * env > env_dump.txt

Vergleichen Sie das mit der Ausgabe von envin einer normalen Shell-Sitzung.

Sie können der lokalen Crontab Ihre eigenen Umgebungsvariablen voranstellen, indem Sie sie oben auf Ihrer Crontab definieren.

Hier ist eine schnelle Lösung, $PATHum der aktuellen Crontab voranzukommen:

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

Die resultierende Crontab ähnelt der Antwort von Chrissygormley, wobei PATH vor den Crontab-Regeln definiert wurde.

Joemaller
quelle
22

Sie sollten vollständige Pfade in Ihre setzen crontab. Das ist die sicherste Option.
Wenn Sie dies nicht möchten, können Sie ein Wrapper-Skript um Ihre Programme legen und dort den Pfad festlegen.

z.B

01 01 * * * command

wird:

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

Auch alles, was von aufgerufen wird, cronsollte sehr vorsichtig mit den Programmen sein, die es ausführt, und wahrscheinlich seine eigene Wahl für die PATHVariable festlegen .

BEARBEITEN:

Wenn Sie nicht wissen, wo sich der Befehl befindet, den Sie which <command>von Ihrer Shell ausführen möchten, wird Ihnen der Pfad angezeigt.

EDIT2:

Sobald Ihr Programm ausgeführt wird, sollte es zunächst PATHalle anderen erforderlichen Variablen (z. B. LD_LIBRARY_PATH) auf die Werte setzen, die für die Ausführung des Skripts erforderlich sind.
Anstatt zu überlegen, wie Sie die Cron-Umgebung ändern können, um sie für Ihr Programm / Skript besser geeignet zu machen, sollten Sie Ihr Skript mit der gegebenen Umgebung umgehen lassen, indem Sie beim Start eine geeignete festlegen.

Douglas Leeder
quelle
1
Wenn es in Ihrem Pfad ist, verwenden Sie 'welchen Befehl' und es gibt Ihnen den vollständigen Pfad
Paul Whelan
@Douglas Leeder - Wenn Sie sagen, dass Sie den vollständigen Pfad in cron einfügen, meinen Sie damit, dass Sie ihn in crontab oder eine andere Datei einfügen? Wenn ja, wie würden Sie vorgehen, wenn der Befehl cron lautet: '01 01 * * * Befehl '. Danke
chrissygormley
@chrissygormley - Ja crontab.
Douglas Leeder
Entschuldigung, es muss Verwirrung geben. Ich habe die Frage oben umformuliert.
Chrissygormley
16

Das Einstellen von PATH direkt vor der Befehlszeile in meiner Crontab hat für mich funktioniert:

* * * * * PATH=$PATH:/usr/local/bin:/path/to/some/thing
Myrho
quelle
lieber so. oder geben Sie den vollständigen Pfad des Skripts an.
zw963
5
Ich denke nicht, dass der Pfad weiter wachsen wird, jedes Mal, wenn sein Lauf eine neue Umgebung sein wird, mit einer neuen Kopie von PATH ...
jjcf89
Kann bestätigen, dass @ jjcf89 korrekt ist, PATH ist bei jedem Lauf frisch.
Electrovir
14

Das Hinzufügen einer PATH-Definition zum Benutzer crontab mit korrekten Werten hilft ... Ich habe meine mit nur gefüllt:

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

Und es reicht aus, um alle meine Skripte zum Laufen zu bringen ... Fügen Sie dort bei Bedarf einen benutzerdefinierten Pfad hinzu.

Treviño
quelle
1
Für einen Benutzer crontab sollte dies die richtige Antwort sein. Nicht jeder in einem System kann bearbeiten /etc/crontab. Dies ist die einfachste Antwort auf Benutzerebene. Gute Arbeit @ Treviño. Stimmen Sie ab, wenn Sie damit einverstanden sind.
Frederickickjh
14

Lassen Sie Ihre Variablen für Sie arbeiten, dies ermöglicht den Zugriff auf t

Definieren Sie Ihren PFAD in /etc/profile.d/*.sh

Systemweite Umgebungsvariablen

Dateien mit der Erweiterung .sh im Verzeichnis /etc/profile.d werden ausgeführt, wenn eine Bash-Anmeldeshell eingegeben wird (z. B. beim Anmelden von der Konsole oder über ssh) sowie vom DisplayManager, wenn die Desktop-Sitzung geladen wird.

Sie können beispielsweise die Datei /etc/profile.d/myenvvars.sh erstellen und folgende Variablen festlegen:

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

Führen Sie crontab mit Login-Option aus!

CRONTAB führt ein Skript oder einen Befehl mit Umgebungsvariablen aus

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
quelle
11

Problem

Ihr Skript funktioniert, wenn Sie es über die Konsole ausführen, schlägt jedoch in cron fehl.

Ursache

Ihre Crontab hat nicht die richtigen Pfadvariablen (und möglicherweise die Shell)

Lösung

Fügen Sie Ihre aktuelle Shell hinzu und verfolgen Sie die Crontab

Skript, um es für Sie zu tun

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

Quelle

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

Beispielausgabe

Beispielausgabe add_curent_shell_and_path_to_crontab.sh

Brakertech
quelle
3

Auf meinem AIX nimmt cron seine Umgebungsvariablen aus / etc / environment auf und ignoriert dabei, was im .profile festgelegt ist.

Bearbeiten: Ich habe auch ein paar Linux-Boxen unterschiedlichen Alters ausgecheckt und diese scheinen auch diese Datei zu haben, daher ist dies wahrscheinlich nicht AIX-spezifisch.

Ich habe dies mit dem Cron-Vorschlag von Joemaller überprüft und die Ausgabe vor und nach dem Bearbeiten der PATH-Variablen in / etc / environment überprüft.

Van Amburg
quelle
3

Wenn Sie nicht an verschiedenen Stellen dieselben Änderungen vornehmen müssen, gehen Sie ungefähr so ​​vor:

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

Das . Leerzeichen und dann der Pfad zu .bashrc und der Befehl && sind die Magie, um Ihre Umgebungsänderungen in die laufende Bash-Shell zu integrieren. Auch wenn Sie wirklich wollen, dass die Shell Bash ist, ist es eine gute Idee, eine Linie in Ihrer Crontab zu haben:

SHELL=/bin/bash

Hoffe es hilft jemandem!

Wade Chandler
quelle
2

Die Standardumgebung für Cron-Jobs ist sehr spärlich und unterscheidet sich möglicherweise stark von der Umgebung, in der Sie Ihre Python-Skripte entwickeln. Für ein Skript, das möglicherweise in Cron ausgeführt wird, sollte jede Umgebung, von der Sie abhängig sind, explizit festgelegt werden. Fügen Sie in die Cron-Datei selbst vollständige Pfade zu ausführbaren Python-Dateien und zu Ihren Python-Skripten ein.

Mob
quelle
2

Ich weiß, dass dies bereits beantwortet wurde, aber ich dachte, dass seine für einige nützlich sein würde. Ich hatte ein ähnliches Problem, das ich kürzlich gelöst habe ( hier zu finden ). Hier sind die Höhepunkte der Schritte, die ich zur Beantwortung dieser Frage unternommen habe:

  1. Stellen Sie sicher, dass Sie die Variablen, die Sie in PYTHONPATH (hier und hier und für weitere Informationen hier) benötigen, in der .profile oder .bash_profile für jede Shell haben, in der Sie Ihr Skript testen möchten, um sicherzustellen, dass es funktioniert.

  2. Bearbeiten Sie Ihre Crontab so, dass sie die Verzeichnisse enthält, die zum Ausführen Ihres Skripts in einem Cron-Job erforderlich sind (hier und hier zu finden).

    a) Stellen Sie sicher, dass Sie das Stammverzeichnis in die PATH-Variable (.) aufnehmen, wie hier erläutert (wenn Sie eine ausführbare Datei mit Ihrem Befehl ausführen, muss sie in der Lage sein, root oder das Verzeichnis zu finden, in dem die ausführbare Datei gespeichert ist) und wahrscheinlich diese (/ sbin: / bin: / usr / sbin: / usr / bin)

  3. Erstellen Sie in Ihrer crontab-Datei einen Cronjob, der das Verzeichnis in das Verzeichnis ändert, in dem Sie das Skript zuvor erfolgreich ausgeführt haben (z. B. Benutzer / Benutzer / Dokumente / foo).

    a) Dies sieht folgendermaßen aus:

    * * * * cd /Users/user/Documents/foo; bar -l doSomething -v 
    
abzugsfähig
quelle
2

@ Trevino: Ihre Antwort hat mir geholfen, mein Problem zu lösen. Für Anfänger jedoch versuchen, einen schrittweisen Ansatz zu geben.

  1. Holen Sie sich Ihre aktuelle Installation von Java über $ echo $JAVA_HOME
  2. $ crontab -e
  3. * * * * * echo $PATH- Auf diese Weise können Sie verstehen, welchen PATH-Wert derzeit von crontab verwendet wird. Führen Sie crontab aus und holen Sie sich den von crontab verwendeten Wert $ PATH.
  4. Bearbeiten Sie nun crontab erneut, um den gewünschten Java-Bin-Pfad festzulegen: a) crontab -e; b) PATH=<value of $JAVA_HOME>/bin:/usr/bin:/bin(es ist ein Probenpfad); c) jetzt Ihren geplanten Job / Skript wie */10 * * * * sh runMyJob.sh &; d) Entfernen Sie es echo $PATHvon Crontab, da es jetzt nicht benötigt wird.
Ram Dwivedi
quelle
2

Stellen Sie den gewünschten Pfad in Ihrem Cron ein

crontab -e

Bearbeiten: Drücken Sie i

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

10 * * * * your_command

Speichern und schließen :wq

Yogesh Yadav
quelle
1

Die einfachste Problemumgehung, die ich gefunden habe, sieht folgendermaßen aus:

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

Dieses Beispiel wird suals Root-Benutzer aufgerufen und startet die Shell mit der vollständigen Umgebung des Benutzers, einschließlich $ PATH, die so eingestellt ist, als ob sie angemeldet wären. Es funktioniert in verschiedenen Distributionen gleich und ist zuverlässiger als die Beschaffung von .bashrc (was nicht funktioniert hat) me) und vermeidet das Hardcodieren bestimmter Pfade, was ein Problem sein kann, wenn Sie ein Beispiel oder ein Setup-Tool bereitstellen und nicht wissen, welche Distribution oder welches Dateilayout auf dem System des Benutzers vorhanden ist.

Sie können den Benutzernamen auch nach angeben, suwenn Sie einen anderen Benutzer als root möchten. Sie sollten den rootParameter jedoch wahrscheinlich vor dem suBefehl belassen, da dies sicherstellt, dass Sie suüber ausreichende Berechtigungen verfügen, um zu einem von Ihnen angegebenen Benutzer zu wechseln.


quelle
-3

Wenn Sie webmindann verwenden, sind dies die Schritte zum Festlegen des PATHWerts:

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
quelle