Standard-Shell für Cron-Problem

8

Ich habe einige Befehle, sie arbeiten unter Bash, aber nicht als Cronjob. Um zu sehen, was das Problem verursacht, speichere ich die Ausgabe in einer Datei, hier mein Beispiel:

51  *  *   *   *    source ~/.rvm/scripts/rvm >> stack.log 2>&1

Der Inhalt der Protokolldatei lautet:

/bin/sh: 1: source: not found

Das heißt, Cron verwendet shInsead von bash. Ich habe versucht, es zu ändern in /etc/crontab:

SHELL=/bin/bash

Das funktioniert aber nicht. Ich habe in die /etc/passwdund hier sehe ich, dass der Dämon shals Standard-Shell verwendet. Beide rootund pihaben bashals Standard-Shell.

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
pi:x:1000:1000:,,,:/home/pi:/bin/bash

Was soll ich tun, um die Standard-Shell für cron zu ändern? Ich würde nicht /bin/bashfür den Daemon-Benutzer /etc/passwdeinstellen in ... imho das ist keine gute Idee.

bearbeiten :

ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Mar 30  2012 /bin/sh -> dash

hier der Inhalt der /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
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

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

# m h dom mon dow user  command
17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly
25 6    * * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6    * * 7   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6    1 * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
#
Cupakob
quelle
1
Warum willst du sourcein crons Umgebung? Einfach das laufen zu lassen ~/.rvm/scripts/rvmfunktioniert nicht? Und Sie können Probleme mit der Verwendung von ~ in Nicht-Bash-Umgebungen haben.
Makrojames

Antworten:

4

Die verwendete Shell ist dash; Eine POSIX-kompatible Shell, die viel kleiner und stabiler als ist bash.

Man könnte argumentieren, dass Sie cronJobs schreiben sollten , um POSIX-kompatibel zu sein. Alternativ können Sie versuchen, Ihre Logik in ein Skript zu kapseln und den Shebang voranzustellen

#!/usr/bin/env bash
Alex Chamberlain
quelle
2
Warum #! / usr / bin / env bash und nicht #! / bin / bash? Was ist der Unterschied?
Cupakob
1
IMHO nicht viel. Genau genommen kann es bashan anderer Stelle aufbewahrt werden. Wer das machen würde, weiß ich nicht!
Alex Chamberlain
Ich habe es auch versucht ... Ich habe ein Wrapper-Bash-Skript, das meinen Befehl aufruft, aber das funktioniert auch nicht. Aber ich wandere, warum die Änderungen in der / etc / crontab den Swich nicht dazu bringen, zu schlagen.
Cupakob
@cupakob Kannst du /etc/crontabbitte dein gesamtes einfügen ?
Alex Chamberlain
1
Ich denke, das Problem ist sourceein eingebautes, was keinen Sinn macht, alleine zu laufen.
Alex Chamberlain
4

Die meisten dieser Fälle (in denen das Skript in der Shell, aber nicht in Cron funktioniert) sind auf Umgebungsvariablen zurückzuführen, die sich im Skript unterscheiden. In vielen Fällen sind die Probleme PATHvariabel. Sie können vollständige Pfade zu allen ausführbaren Dateien verwenden, die Sie im Skript ausführen, oder PATHin der ersten Zeile Ihres Skripts ändern .

Um solche Probleme zu verfolgen, können Sie zunächst Umgebungsvariablen sichern, die für Ihr Skript verfügbar sind, indem Sie den folgenden envBefehl verwenden: / usr / bin / env> /tmp/env.txt

Krzysztof Adamski
quelle
Ich habe keine Umgebungsvariablen in meinem Skript ... und / bin / env existiert nicht.
Cupakob
2
Nein, Sie haben immer einige Umgebungsvariablen in jeder Shell. Ein Beispiel ist PATHdas bereits erwähnte. Versuchen Sie es /usr/bin/envstattdessen. Oder verwenden Sie which env, um zu überprüfen, welchen Pfad Sie vollständig verwenden envmüssen.
Krzysztof Adamski
3

Sind Sie sicher, dass sourcingIhr Skript genau das cronist, was Sie tun möchten und, was noch wichtiger ist, notwendig ist? Ich denke, dass es fast immer eine schlechte Idee ist.

cronVersuchen Sie außerdem, beim Bearbeiten (sowie bei anderen Tools, die möglicherweise von anderen Benutzern und / oder anderen Shells gestartet werden können) Schritt für Schritt vorzugehen. Zum Beispiel können Sie Ihre Umgebung folgendermaßen testen:

42  *  *   *   *    bash -c "echo home---$HOME---"   >> /tmp/cron-temp.log 2>&1
42  *  *   *   *    bash -c "echo shell---$SHELL---" >> /tmp/cron-temp.log 2>&1

oder auch:

42  *  *   *   *    bash -c "export"                 >> /tmp/cron-temp.log 2>&1

So können Sie Beweise für Ihre Umgebung usw. haben.

Um Ihre Frage zu beantworten, würde ich die Shell für nicht ändern cron. Ich würde es einfach aufrufen bashund dann bashIhre Skripte aufrufen lassen .

Avio
quelle
Die $ SHELL war immer noch 'sh', obwohl ich sie in der / etc / crontab
cupakob
1
Ja, es ist auch die Standardeinstellung in meinem cron. Wie gesagt, ich würde es nicht ändern. Sie einfach Ihr Skript aufrufen durch bashmit bash -c "yourscript"und alles sollte in Ordnung sein (nicht Ihr Skript beziehen, werden Sie wahrscheinlich brauchen sie nicht!)
Avio
Ja, das wird funktionieren, aber ich möchte wissen, warum die Standard-Shell nicht geändert wurde.
Cupakob
3

Also ... ich habe zwei Lösungen für mein Problem:

  1. Wrapper-Skript über den Bash-Befehl, den ich gerade als Cronjob aufrufe. Das Problem hier - für jeden Cronjob brauche ich einen Wrapper, und das ist nicht die beste Lösung für mich.

  2. Ich habe versucht, ein Ruby-Skript als Cronjob zu bezeichnen. Das funktioniert nicht, also dachte ich, ich muss 'rvm use 1.9.3' aufrufen und dafür muss ich zuerst 'source ~ / .rvm / scripts / rvm' aufrufen. Und hier war mein Fehler. In meiner Bash-Instanz habe ich einen Pfad zu Rubin, aber nicht als Cron. Nachdem ich das behoben habe, funktioniert alles gut und ich kann meine Ruby-Skripte als Cronjob ausführen.

Alex Chamberlain hat mir sehr geholfen und mir die wichtigsten Hinweise gegeben. Vielen Dank für die Hilfe !!!

Cupakob
quelle