Forum: PC-Programmierung raspberry pi shell-script automatisch ausführen lassen wenn keiner eingeloggt ist


You were forwarded to this site from EmbDev.net. Back to EmbDev.net
von Chandler B. (chandler)


Lesenswert?

Hallo,
ich habe ein kleines shell-script auf einem raspberry pi erstellt.
Wenn ich dieses manuell ausführe (bin über SSH) eingeloggt, funktioniert 
es auch so wie erwartet.

Jetzt möchte ich das ganze aber automatisch alle X stunden ausführen 
lassen. Dabei bin ich nicht eingeloggt.
Was muss ich dafür verwenden?
Kann ich das auch über "cron" machen? Sowie ich das verstanden habe, 
kann man dort automatische Ausführungen für jeden Benutzer einstellen? 
Aber muss ich dann eingeloggt sein, damit das ausgeführt wird?

von Sebastian W. (wangnick)


Lesenswert?

Chandler B. schrieb:
> Kann ich das auch über "cron" machen?

Ja.

Chandler B. schrieb:
> Aber muss ich dann eingeloggt sein, damit das ausgeführt wird?

Nein.

LG, Sebastian

von Rolf M. (rmagnus)


Lesenswert?

Chandler B. schrieb:
> Kann ich das auch über "cron" machen?

Was heißt "auch"? Cron ist eigentlich exakt dafür gemacht.

> Aber muss ich dann eingeloggt sein, damit das ausgeführt wird?

Das ist ganz unabhängig davon, ob du eingeloggt bist.

von Chandler B. (chandler)


Lesenswert?

Hallo,
ganz so wie gedacht funktioniert es bei mir doch noch nicht

crontab -e:
[code]
0 */3   * cd speedtest && sh speedtest.sh
[code]
(zwischen */3 und cd speedtest soll 3x*)
es soll alle 3 Stunden in den Ordner speedtest gewechselt werden und das 
skript speedtest.sh ausgeführt werden

speedtest.sh:
[code]
#!/bin/bash

if ! [ -e speedtest.csv]
then
  speedtest-cli --csv --csv-header >> speedtest.csv
fi

speedtest-cli --csv --secure >> speedtest.csv
[code]

in speedtest.csv sehe ich aber nur den ersten Eintrag. also nicht alle 3 
Stunden. Und der wurde am 25.01. um 14:16 Uhr gemacht (also auch nicht 
volle Stunde)

Wenn ich speedtest.sh selber noch einmal trigger, wird der nächste 
Eintrag unten drangehangen.
Auch wenn ich
crontab -e:
[code]
*/2   * * cd speedtest && sh speedtest.sh
[code]
(zwischen */2 und cd speedtest soll 4x*)
Wird alle 2 Minuten eine Messung in speedtest.csv drangehangen

: Bearbeitet durch User
von Harry L. (mysth)


Lesenswert?

man 5 crontab

von Sebastian W. (wangnick)


Lesenswert?

Also
1
0 */3 * * * cd speedtest && sh speedtest.sh
funktioniert nicht, aber
1
*/2 * * * * cd speedtest && sh speedtest.sh
funktioniert? Seltsam ...

LG, Sebastian

von Chandler B. (chandler)


Lesenswert?

Sebastian W. schrieb:
> funktioniert? Seltsam ...

Ja

so ist es aus crontab herauskopiert (und nicht mehr abgetippt wie oben)
ist aber das selbe (zumindest sehe ich keine unterschied)
1
#0 */3 * * * cd speedtest && sh speedtest.sh
2
*/2 * * * * cd speedtest && sh speedtest.sh
Also die obere zeile ist jetzt auskommentiert, da ich die untere zeile 
zum Testen reingenommen habe

: Bearbeitet durch User
von Sebastian W. (wangnick)


Lesenswert?

Chandler B. schrieb:
> Also die obere zeile ist jetzt auskommentiert, da ich die untere zeile
> zum Testen reingenommen habe

Ich kann mir nur vorstellen, dass beim ersten Test das Zeilenende 
fehlte. Kommentiere mal die zweite Zeile aus. Funktioniert es dann nach 
wie vor nicht?

LG, Sebastian

von Ein T. (ein_typ)


Lesenswert?

Nachdem die Damen und Herren nun ausführlich auf den Cron-Daemon 
hingewiesen haben, möchte ich daran erinnern, daß es auf vielen modernen 
Distributionen heutzutage noch eine andere Möglichkeit gibt: nämlich die 
systemd-Timer.

von Chandler B. (chandler)


Lesenswert?

Sebastian W. schrieb:
> Chandler B. schrieb:
>> Also die obere zeile ist jetzt auskommentiert, da ich die untere zeile
>> zum Testen reingenommen habe
>
> Ich kann mir nur vorstellen, dass beim ersten Test das Zeilenende
> fehlte. Kommentiere mal die zweite Zeile aus. Funktioniert es dann nach
> wie vor nicht?
>
> LG, Sebastian

Hallo,
das ich komme da irgendwie nicht weiter.
1
#run speedtest everyday all 3 hours
2
0 */3 * * * cd speedtest && sh speedtest.sh

Ich habe es wie folgt getestet. Ich habe nur noch diese eine 
Befehlszeile drinnen.
Da bin ich einmal mit dem Kursor nach ganz vorne gegangen und habe die 0 
mit */2 getauscht und */3 mit * (also alle 2 minuten)
-> funktioniert
Dann bin ich wieder mit dem Cursor zu den stellen gegangen und habe das 
*/2 mit der 0 und das erste sternchen dann mit */3 getauscht.
Also zeilenende oder so habe ich gar nichts geändert.
Jetzt habe ich vorhin nachgeschaut und es ist wieder nur die Headerzeile 
drinn.

Gibt es noch eirgeneinen Logbefehl, den ich hinterlegen kann, ob es 
ausgeführt worden ist, oder ob evtl. irgendein Fehler vorliegt?
Aber ganz verstehe ich nicht, warum es nicht funktioniert.
Auch als ich das mit alle 2 Minuten getstet habe, habe ihc mich komplett 
ausgeloggt. Und es hat trotzdem funktioniert.

von Harry L. (mysth)


Lesenswert?

Statt ohne Sinn und Verstand planlos irgendwelche Einstellungen zu 
probieren, könnte man ja einfach mal in die Dokumentation schauen.
Da steht auch detailliert drin, welche Felder welche Bedeutung haben.

https://linux.die.net/man/5/crontab

von Andreas B. (bitverdreher)


Lesenswert?

anstatt einen cd speedtest & vorn dranzuhaengen, wobei nicht klar ist, 
von welchem Verzeichnis aus Du das betrachtest, wuerde ich 
sinnvollerweise stattdessen den Befehl mit vollem Pfad eintragen.

Harry L. schrieb:
> Statt ohne Sinn und Verstand planlos irgendwelche Einstellungen zu
> probieren, könnte man ja einfach mal in die Dokumentation schauen.

das ausserdem auch noch.

von Chandler B. (chandler)


Lesenswert?

Harry L. schrieb:
> Statt ohne Sinn und Verstand planlos irgendwelche Einstellungen zu
> probieren, könnte man ja einfach mal in die Dokumentation schauen.
> Da steht auch detailliert drin, welche Felder welche Bedeutung haben.
1
    minute
2
    0-59
3
    hour
4
    0-23
5
    day of month
6
    1-31
7
    month
8
    1-12 (or names, see below)
9
    day of week
10
    0-7 (0 or 7 is Sun, or use names) 
11
A field may be an asterisk (*), which always stands for "first-last".

Das steht in der man.
also für mich ist, wenn
1
*/2 * * * *
1
minute: */2 -> alle 2 minuten
2
hour: * -> jede stunde
3
day of month: * -> jeder Tag
4
month: * -> jeder monat
5
day of week: * -> Jeder Wochentag
1
0 */3 * * *
1
minute: 0 -> jede 0te minute
2
hour: */3 -> jede dritte stunde
3
day of month: * -> jeder Tag
4
month: * -> jeder monat
5
day of week: * -> Jeder Wochentag

Bsp. von der Seite
1
# run five minutes after midnight, every day
2
5 0 * * *       $HOME/bin/daily.job >> $HOME/tmp/out 2>&1
nur das ich nicht 5 minuten nach Mitternacht haben möchte, sonder alle 3 
Stunden

: Bearbeitet durch User
von Hmmm (hmmm)


Lesenswert?

Chandler B. schrieb:
1
> #!/bin/bash
2
> 
3
> if ! [ -e speedtest.csv]
4
> then
5
>   speedtest-cli --csv --csv-header >> speedtest.csv
6
> fi
7
> 
8
> speedtest-cli --csv --secure >> speedtest.csv

1. Fehlendes Semikolon am Ende der if-Zeile.

2. Zum Debuggen Deines Problems ist etwas, das sich bei vorhandener 
Datei anders verhält als bei nicht vorhandener, extrem ungünstig. Warum 
fängst Du nicht mit einem simplen "date >> test.txt" an, um erstmal zu 
sehen, ob es wie gewollt gestartet wird?

Chandler B. schrieb:
> cd speedtest

Bei sowas immer absolute Pfade verwenden, erspart Kopfschmerzen.

Chandler B. schrieb:
> Gibt es noch eirgeneinen Logbefehl, den ich hinterlegen kann, ob es
> ausgeführt worden ist, oder ob evtl. irgendein Fehler vorliegt?

Cron kann sogar Mails verschicken, steht alles in den Man-Pages.

von Chandler B. (chandler)


Lesenswert?

Hmmm schrieb:
> 1. Fehlendes Semikolon am Ende der if-Zeile.

laut https://openbook.rheinwerk-verlag.de/linux/linux_kap11_005.html
muss das semikolon nur, wenn das "then" sich in der selben zeile 
befindet

Hmmm schrieb:
> 2. Zum Debuggen Deines Problems ist etwas, das sich bei vorhandener
> Datei anders verhält als bei nicht vorhandener, extrem ungünstig. Warum
> fängst Du nicht mit einem simplen "date >> test.txt" an, um erstmal zu
> sehen, ob es wie gewollt gestartet wird?

Das skript macht ja an für sich das was es soll.
Wenn ich es manuell ausführe, erstellt es eine Datei und erstellt die 
erste messung. Wenn eine Datei schon existiert, wird nur eine weitere 
Messung angehangen.

Wenn ich das skript alle 2 Minuten ausführe funktioniert es genauso.

Das Problem ist (warum auch immer), wenn ich es alle 3 Stunden trigger.

Hmmm schrieb:
> Chandler B. schrieb:
>> cd speedtest
>
> Bei sowas immer absolute Pfade verwenden, erspart Kopfschmerzen.

habe jetzt
1
0 */3 * * * sh speedtest/speedtest.sh

damit wird die csv datei zwar nicht im Ordner speedtest erstellt, aber 
das ist mir erstmal egal, solange es überhaupt mal funktioniert.
Auch hier habe ich es einmal mit alle 2 Minuten getestet. Da 
funktioniert es. Werde ich morgen sehen, ob es geklappt hat.

: Bearbeitet durch User
von Hans (ths23)


Lesenswert?

Ein T. schrieb:
> Nachdem die Damen und Herren nun ausführlich auf den Cron-Daemon
> hingewiesen haben, möchte ich daran erinnern, daß es auf vielen modernen
> Distributionen heutzutage noch eine andere Möglichkeit gibt: nämlich die
> systemd-Timer.
Das hilft dem TO jetzt aber wirklich richtig gut.

@TO

Schreibe es mal so:
1
0 */3 * * *  cd <voll qualifizierter Pfad zu speedtest> && speedtest.sh

Für das Pfadwechselkommando würde ich den vollen Pfad angeben. Wenn 
dieser Pfadwechsel fehl schlägt, also z.B. das Verzeichnis nicht 
vorhanden ist, dann wird der Teil nach && gar nicht ausgeführt.
Das sh vor Deinem Script brauchst Du nicht, denn Du legst in der ersten 
Scriptzeile fest mit welcher Shell Dein Script ausgeführt werden soll. 
Allerdings muß Dein Script Ausführungsrechte haben. Das geht ganz 
einfach im Terminal mit
1
chmod ugo+x speedtest.sh
Ansonsten wenn Du den Pfadwechsel nur ausführst, um in das Verzeichnis 
des Scriptes zu gelangen, dann schreibe vor speedtes.sh einfach den 
vollständigen Pfad zum Script.

von Hmmm (hmmm)


Lesenswert?

Chandler B. schrieb:
> muss das semikolon nur, wenn das "then" sich in der selben zeile
> befindet

Stimmt tatsächlich, Semikolon oder Newline. Bin noch nie auf die Idee 
gekommen, das then in eine separate Zeile zu packen.

Chandler B. schrieb:
> Das skript macht ja an für sich das was es soll.

Das Gesamtkonstrukt tut nicht, was es soll. Also versucht man, den 
Fehler systematisch einzugrenzen, indem man z.B. prüft, ob und wann das 
Script gestartet wird.

Es könnte schliesslich auch sein, dass Dein speedtest-Tool sich unter 
bestimmten Umständen (z.B. kein User eingeloggt) anders verhält.

Chandler B. schrieb:
>> Bei sowas immer absolute Pfade verwenden, erspart Kopfschmerzen.
>
> habe jetzt
> 0 */3   * sh speedtest/speedtest.sh

Auch das ist kein absoluter Pfad.

von Ein T. (ein_typ)


Lesenswert?

Hmmm schrieb:
> Chandler B. schrieb:
>
1
>> #!/bin/bash
2
>>
3
>> if ! [ -e speedtest.csv]
4
>> then
5
>>   speedtest-cli --csv --csv-header >> speedtest.csv
6
>> fi
7
>>
8
>> speedtest-cli --csv --secure >> speedtest.csv
9
>
>
> 1. Fehlendes Semikolon am Ende der if-Zeile.

Das wäre schöner, spielt für die Funktion aber keine Rolle.

> Chandler B. schrieb:
>> cd speedtest
>
> Bei sowas immer absolute Pfade verwenden, erspart Kopfschmerzen.

True.

> Chandler B. schrieb:
>> Gibt es noch eirgeneinen Logbefehl, den ich hinterlegen kann, ob es
>> ausgeführt worden ist, oder ob evtl. irgendein Fehler vorliegt?
>
> Cron kann sogar Mails verschicken, steht alles in den Man-Pages.

1. Jedesmal, wenn Cron einen Cronjob ausführt, wird dazu ein Logeintrag 
in der Datei /var/log/syslog erzeugt.

2. Die Crontabs sollte man nicht direkt mit dem Editor bearbeiten, 
sondern mit dem Kommandozeilenbefehl "crontab -e", der auf 
Debian-basierten Systemen per Default den Editor nano(1) oder jenen 
aufruft, der in der Umgebungsvariablen EDITOR konfiguriert ist. Das 
Programm crontab(1) überprüft dabei, ob die vom Editor gespeicherte 
Crontab korrekt formatiert ist (also nicht, ob die darin aufgerufenen 
Programme vorhanden und ausführbar sind), bevor es die Crontab 
installiert. Wenn das Format der vom Editor ausgegebenen Crontab 
inkorrekt ist, erzeugt crontab(1) eine Ausgabe in der Shell und fragt 
dann, ob es den Editierversuch wiederholen soll. Bei der Antwort "y" 
wird wieder der Editor in $EDITOR gestartet, bei der Antwort "n" wird 
crontab(1) die defekte Crontab in einer Datei in /tmp ablegen, den Pfad 
zu dieser Datei ausgegeben und sich danach beenden. crontab(1) findet 
auch keine Permission-Probleme, sondern überprüft ausschließlich das 
Format der neuen Crontab.

3. Wenn das aufgerufende Programm etwas auf STDOUT oder STDERR ausgibt 
und diese beiden Streams nicht umgeleitet werden, oder das Skript einen 
Fehler zurückgibt -- also: der Rückgabewert des Programms ungleich 0 ist 
-- dann erzeugt Cron eine E-Mail an den Besitzer der Crontab (bei der 
systemweiten Crontab natürlich "root" (siehe auch unter 5.)) und 
versucht, sie mit dem installierten Mail Transport Agent (MTA) 
zuzustellen. Wenn das nicht funktioniert, weil kein MTA installiert ist, 
wird ein Logeintrag wie "(CRON) info (No MTA installed, discarding 
output)" in /var/log/syslog erzeugt. Wenn ein MTA installiert ist, dann 
werden die Mails per Default in /var/mail/<username> abgelegt, für die 
systemweite Crontab also in /var/mail/root.

5. In der jeweiligen Crontab selbst kann man auch einen anderen 
(eventuell externen) Empfänger in der Variablen mit der Variablen MAIL 
konfigurieren, zum Beispiel in einer Zeile "MAIL=hab@ich.net". 
Voraussetzung ist natürlich auch hier, daß ein funktionsfähiger MTA 
installiert und zudem dort mindestens ein Smarthost konfiguriert ist.

6. Hmmmms Ratschlag, absolute Pfade zu verwenden, ist absolut 
richtig!!1!

7. Bei mir funktioniert die Crontab-Zeile
1
* */3 * * *    date >> /tmp/datum.txt

übrigens vollkommen problemlos. Mein Verdacht ist, daß der TO 
irgendeinen Tippfehler eingebaut hat. Das sollte sich mit "crontab -e" 
allerdings sehr leicht vermeiden lassen.

8. Wie alle anderen Programme, sollten auch Cronjobs idealerweise mit 
den geringstmöglichen Permissions laufen, also nicht unbedingt als root, 
wenn sie dessen Privilegien nicht brauchen.

HTH!

von Hmmm (hmmm)


Lesenswert?

Ein T. schrieb:
> In der jeweiligen Crontab selbst kann man auch einen anderen
> (eventuell externen) Empfänger in der Variablen mit der Variablen MAIL
> konfigurieren, zum Beispiel in einer Zeile "MAIL=hab@ich.net".

Kleine Korrektur dazu: Nicht MAIL, sondern MAILTO.

von Ein T. (ein_typ)


Lesenswert?

Hans schrieb:
> Ein T. schrieb:
>> Nachdem die Damen und Herren nun ausführlich auf den Cron-Daemon
>> hingewiesen haben, möchte ich daran erinnern, daß es auf vielen modernen
>> Distributionen heutzutage noch eine andere Möglichkeit gibt: nämlich die
>> systemd-Timer.
> Das hilft dem TO jetzt aber wirklich richtig gut.

Da hast Du Recht, die Erinnerung richtete sich aber primär an die 
Mitleser.

> Allerdings muß Dein Script Ausführungsrechte haben. Das geht ganz
> einfach im Terminal mit
>
1
chmod ugo+x speedtest.sh

Nunja, der TO sagt ja, mit anderen Einträgen in den Datums- und 
Zeitfeldern der Crontab würde dasselbe Skript funktionieren. Das würde 
es jedoch nicht, wenn die Dateirechte nicht korrekt gesetzt wären. Es 
bleibt mysteriös. :-)

von Ein T. (ein_typ)


Lesenswert?

Hmmm schrieb:
> Ein T. schrieb:
>> In der jeweiligen Crontab selbst kann man auch einen anderen
>> (eventuell externen) Empfänger in der Variablen mit der Variablen MAIL
>> konfigurieren, zum Beispiel in einer Zeile "MAIL=hab@ich.net".
>
> Kleine Korrektur dazu: Nicht MAIL, sondern MAILTO.

Huch, stimmt, Du hast natürlich Recht!

von Foobar (asdfasd)


Lesenswert?

Wer weiß, was für einen cron er überhaupt hat?  Evtl eine buggy systemd 
extension?

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hans schrieb:
> cd <voll qualifizierter Pfad zu speedtest> && speedtest.sh

Ich würde sogar noch weiter gehen:
1
cd <voll qualifizierter Pfad zu speedtest> && ./speedtest.sh >>/tmp/speedtest.log 2>&1

Beachte: "./" vor speedtest.sh! Das ist wichtig, weil cron das aktuelle 
Arbeitsverzeichnis gar nicht im PATH hat!

Und in speedtest.sh als erstes Kommando:
1
echo Start: `date`

Und am Ende:
1
echo End: `date`

(Achtung das sind Backticks um date)

Zwischen den beiden Zeitausgaben in speedtest.log stehen dann eventuell 
enstandene Fehlermeldungen.

: Bearbeitet durch Moderator
von Hans (ths23)


Lesenswert?

Ein T. schrieb:
>> Allerdings muß Dein Script Ausführungsrechte haben. Das geht ganz
>> einfach im Terminal mit
>>1chmod ugo+x speedtest.sh
>
> Nunja, der TO sagt ja, mit anderen Einträgen in den Datums- und
> Zeitfeldern der Crontab würde dasselbe Skript funktionieren. Das würde
> es jedoch nicht, wenn die Dateirechte nicht korrekt gesetzt wären. Es
> bleibt mysteriös. :-)
Er wird es aber auch da mit sh speedtest.sh eintragen. Das sh am Anfang 
kann man aber getrost weg lassen, wenn das Script Ausfgührungsrechte 
hat.

von Rolf M. (rmagnus)


Lesenswert?

Frank M. schrieb:
> Und in speedtest.sh als erstes Kommando:echo Start: `date`
>
> Und am Ende:echo End: `date`
>
> (Achtung das sind Backticks um date)

Man kann auch $(date) schreiben. Das macht das gleiche.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hans schrieb:
> Das sh am Anfang kann man aber getrost weg lassen, wenn das Script
> Ausfgührungsrechte hat.

Beachte, dass das aktuelle Arbeitsverzeichnis im Allgemeinen nicht im 
Pfad ist. Wenn Du also bei
1
sh mein-script.sh
das "sh" weglassen willst, musst Du (neben der Beachtung der 
Ausführungsrechte) auch den Pfad angeben, also:
1
./mein-script.sh

: Bearbeitet durch Moderator
von Ein T. (ein_typ)


Lesenswert?

Hans schrieb:
> Er wird es aber auch da mit sh speedtest.sh eintragen. Das sh am Anfang
> kann man aber getrost weg lassen, wenn das Script Ausfgührungsrechte
> hat.

Mit dem vorangestellten "sh" kann er sich neben den Ausführrechten auch 
die explizite Pfadangabe "./" sparen, auf die Frank M. (ukw) hingewiesen 
hat. Es wäre dann immer noch etwas unglücklich, daß das Skript selbst 
"/bin/bash" in der Shebangzeile hat, also ein Bash-Skript ist, das dann 
jedoch von Cron mit der Shell "sh" ausgeführt würde. Eine saubere 
Systempflege würde solcherlei Fehlerquellen natürlich vermeiden.

von Rolf M. (rmagnus)


Lesenswert?

Ein T. schrieb:
> Mit dem vorangestellten "sh" kann er sich neben den Ausführrechten auch
> die explizite Pfadangabe "./" sparen, auf die Frank M. (ukw) hingewiesen
> hat. Es wäre dann immer noch etwas unglücklich, daß das Skript selbst
> "/bin/bash" in der Shebangzeile hat, also ein Bash-Skript ist, das dann
> jedoch von Cron mit der Shell "sh" ausgeführt würde.

Man könnte natürlich statt sh auch bash davor schreiben, um dafür zu 
sorgen, dass es auch mit dieser ausgeführt wird.

> Eine saubere Systempflege würde solcherlei Fehlerquellen natürlich
> vermeiden.

Dabei muss man insbesondere bedenken, dass zumindest bei Debian und 
darauf basierenden Systemen die sh in der Regel ein Symlink auf die dash 
ist und nicht auf die bash.

: Bearbeitet durch User
von Ein T. (ein_typ)


Lesenswert?

Rolf M. schrieb:
> Frank M. schrieb:
>> Und am Ende:echo End: `date`
>>
>> (Achtung das sind Backticks um date)
>
> Man kann auch $(date) schreiben. Das macht das gleiche.

Allerdings kann $() korrekt ineinander verschachtelt werden und ist 
meiner persönlichen Meinung nach auch besser lesbar. Das Problem mit den 
Backticks zeigt Frank ja schon: da muß man für unbedarfte Nutzer 
nochmals extra hinzu schreiben, daß das Backticks und keine Singlequotes 
sind, und die besonders unbedarften Benutzer wissen vielleicht auch 
nicht, was Backticks sind.

von Rolf M. (rmagnus)


Lesenswert?

Ein T. schrieb:
>> Man kann auch $(date) schreiben. Das macht das gleiche.
>
> Allerdings kann $() korrekt ineinander verschachtelt werden und ist
> meiner persönlichen Meinung nach auch besser lesbar.

Es gibt auch bei `` die Möglichkeit zu verschachteln durch Escapen, aber 
das macht's auch nicht gerade hübscher.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Ein T. schrieb:
> Allerdings kann $() korrekt ineinander verschachtelt werden und ist
> meiner persönlichen Meinung nach auch besser lesbar.

Stimmt schon, $() ist lesbarer. Ich schreibe oft noch die Backticks, 
weil ich das in den 80ern so gelernt habe. Damals gab es die 
Schreibweise mit $() noch nicht. Die Bourne-Shell kannte diese 
jedenfalls noch nicht.

Meiner Erinnerung nach war $() zunächst eine bash-spezifische 
Erweiterung, wurde dann aber später in den POSIX-Standard mit 
aufgenommen, so dass $() heute eigentlich jede Shell versteht. Man mag 
mich korrigieren, wenn mich meine Erinnerung täuscht. ;-)

: Bearbeitet durch Moderator
von Chandler B. (chandler)


Lesenswert?

Frank M. schrieb:
> Ich würde sogar noch weiter gehen:cd <voll qualifizierter Pfad zu
> speedtest> && ./speedtest.sh >>/tmp/speedtest.log 2>&1
>
> Beachte: "./" vor speedtest.sh! Das ist wichtig, weil cron das aktuelle
> Arbeitsverzeichnis gar nicht im PATH hat!
>
> Und in speedtest.sh als erstes Kommando:echo Start: `date`
>
> Und am Ende:echo End: `date`
>
> (Achtung das sind Backticks um date)
>
> Zwischen den beiden Zeitausgaben in speedtest.log stehen dann eventuell
> enstandene Fehlermeldungen.

Habe es heute Mittag zunächst angepasst
1
#!/bin/bash
2
echo START: `date`
3
if ! [ -e speedtest.csv ]
4
then
5
        echo "file does not exist -> create fie speedtest.csv"
6
        speedtest-cli --csv --csv-header --bytes --secure >> speedtest.csv
7
fi
8
9
speedtest-cli --csv --bytes --secure >> speedtest.csv
10
echo END: `date`

und im cron
1
0 */3 * * * sh /home/speedtest/speedtest.sh >> /home/cron.log 2>&1

Und in der Log konnte ich dann tatsächlich einen Error finden
1
GNU nano 5.4                                                                                                                        cron.log
2
START: Thu 29 Feb 18:00:01 CET 2024
3
file does not exist -> create fie speedtest.csv
4
ERROR: Unable to connect to servers to test latency.
5
END: Thu 29 Feb 18:00:04 CET 2024

Mit diesem Fehler konnte ich weitersuchen und habe öfters gelesen, dass 
es öfters vorkommt, dass die Server immer in der Vollen Stunde und 
Halben Stunde überlastet sind.
Habe meinen cron-Befehl dann auf 8 Minuten nach (alle 3 Stunden) 
gändert.
1
8 */3 * * * sh /home/speedtest/speedtest.sh >> /home/cron.log 2>&1

Werde ich dann morgen sehen, ob es das Problem war.
Aber zumindest weiß ich dann schonmal wo ich nachgucken kann, wenn ein 
Fehler passiert.

: Bearbeitet durch User
von Sheeva P. (sheevaplug)


Lesenswert?

Ein T. schrieb:
>>
1
chmod ugo+x speedtest.sh
1
chmod a+x speedtest.sh

von Norbert (der_norbert)


Lesenswert?

Sheeva P. schrieb:
> Ein T. schrieb:
>>>chmod ugo+x speedtest.sh
> chmod a+x speedtest.sh

Die beiden Vorschläge sind aber mit einem sehr breiten 
Berechtigungspinsel gemalt.

von Sebastian W. (wangnick)


Lesenswert?

Rolf M. schrieb:
> Man könnte natürlich statt sh auch bash davor schreiben, um dafür zu
> sorgen, dass es auch mit dieser ausgeführt wird.

Der crond startet doch sowieso eine Shell für das Parsen und die 
Ausführung der Kommandozeile in Spalte 6. Warum dann nicht das 
speedtest.sh-Skript dort über den Befehl source in dieser Shell 
ausführen, anstatt noch eine weitere innere Shell zu starten? Oder 
übersehe ich etwas?

LG, Sebastian

von Sheeva P. (sheevaplug)


Lesenswert?

Foobar schrieb:
> Wer weiß, was für einen cron er überhaupt hat?  Evtl eine buggy systemd
> extension?

Sicher nicht. systemd hat eigene Möglichkeiten, Jobs periodisch 
auszuführen, nämlich die systemd.timer(5), die im Übrigen viel mehr 
Möglichkeiten bieten als schnöde Cronjobs. Wozu wäre eine "buggy systemd 
extension" dort denn nun bitte noch sinnvoll oder wünschenswert?

Zumal die Ausführungsumgebung bereits vom TO definiert wurde: es handelt 
sich um einen Raspberry Pi, also höchstwahrscheinlich um ein Debian 
GNU/Linux oder ein System, das darauf basiert. Dort ist meist der 
Cron-Daemon von Paul Vixie das Mittel der Wahl.

von Sheeva P. (sheevaplug)


Lesenswert?

Frank M. schrieb:
> Ein T. schrieb:
>> Allerdings kann $() korrekt ineinander verschachtelt werden und ist
>> meiner persönlichen Meinung nach auch besser lesbar.
>
> Stimmt schon, $() ist lesbarer. Ich schreibe oft noch die Backticks,
> weil ich das in den 80ern so gelernt habe.

Same with me, aber das habe ich mir abgewöhnt. :)

> Damals gab es die
> Schreibweise mit $() noch nicht. Die Bourne-Shell kannte diese
> jedenfalls noch nicht.

Absolutely true!

> Meiner Erinnerung nach war $() zunächst eine bash-spezifische
> Erweiterung, wurde dann aber später in den POSIX-Standard mit
> aufgenommen, so dass $() heute eigentlich jede Shell versteht. Man mag
> mich korrigieren, wenn mich meine Erinnerung täuscht. ;-)

True. Meines Wissens können heute die Bourne Again Shell (bash), die 
Debian Almquist Shell (dash), die Korn Shell (ksh) und die Z Shell (zsh) 
das. Andere Shells kenne ich nicht und stelle fest, wie lang ich schon 
nicht mehr mit was anderem als Bash und Dash gearbytet habe. Huch!

von Sheeva P. (sheevaplug)


Lesenswert?

Chandler B. schrieb:
> Habe es heute Mittag zunächst angepasst
>
1
> #!/bin/bash
2
> echo START: `date`
3
> if ! [ -e speedtest.csv ]
4
> then
5
>         echo "file does not exist -> create fie speedtest.csv"
6
>         speedtest-cli --csv --csv-header --bytes --secure >> 
7
> speedtest.csv
8
> fi
9
> 
10
> speedtest-cli --csv --bytes --secure >> speedtest.csv
11
> echo END: `date`
12
>

Bitte sei so lieb und mach hinter alle Zeilen außer "bash", "then" und 
"fi" jeweils ein Semikolon. Das ändert nichts an der Funktion, macht 
Dein Skript aber vermutlich nicht nur aus meiner Perspektive lesbarer.

Zudem würde ich für den Logeintrag der Endzeit auch noch einmal die 
Startzeit ausgeben, um den Zusammenhang zwischen den Logeinträgen 
sichtbar zu machen.

> und im cron
>
1
> 0 */3 * * * sh /home/speedtest/speedtest.sh >> /home/cron.log 2>&1
2
>

Das wäre aus meiner Sicht ein Fehler, und wenn einer meiner Entwickler 
mir so etwas vorlegen würde, hätten wir ein sehr langes und sehr ernstes 
Gespräch.

Dein Skript ist ein Bash-Skript (die Shebang-Zeile lautet "#!/bin/bash", 
aber Du führst es mit "sh" aus. Das "sh" ist aber irgendetwas, das Dein 
System in den Verzeichnissen der Umgebungsvariablen $PATH findet, und 
muss daher keine Bash sein. Wenn Du dann in Deinem Skript Konstrukte 
benutzt, die nur in der Bash verfügbar sind, hast Du ein Problem.

Auch Deine Dateinamenerweiterung halte ich für, sagen wir, schwierig. 
Wenn ich Bash-Skripte schreibe, dann enden sie auf ".bash", wenn ich 
allgemeingültige Shellskripte schreibe, auf ".sh", entsprechend auch 
Skripte für die Korn- und die Z-Shell (".ksh" und ".zsh").

Warum? So ein UNIXoides System besteht aus drölfzig Zilliarden an 
Dateien. Je eindeutiger die benannt sind, desto einfacher ist es, sich 
einzufinden. Dabei geht es hier bisher nicht um technische 
Anforderungen, sondern um humane.

There are two hard things in computer science: cache invalidation, 
off-by-one errors, and naming things. Meine Anmerkungen in diesem Absatz 
betreffen den "naming things"-Teil. :)

Dann habe ich ein zweites Problem mit Deinem Ansatz, nämlich das 
Schreiben in /home. Sowas würde ein erfahrener Sysop einfach nicht 
machen, sorry. Es gibt für so etwas das Verzeichnis /var/log, und rate, 
wofür das da ist? Haargenau: für _var_iable _log_Daten.

> Und in der Log konnte ich dann tatsächlich einen Error finden
>
1
> ERROR: Unable to connect to servers to test latency.
2
>

Ach, sieh an. :)

>
1
> 8 */3 * * * sh /home/speedtest/speedtest.sh >> /home/cron.log 2>&1
2
>
>
> Werde ich dann morgen sehen, ob es das Problem war.
> Aber zumindest weiß ich dann schonmal wo ich nachgucken kann, wenn ein
> Fehler passiert.

Lessons learned: Unter Linux sind Logdateien wichtig und enthalten 
wertvolle Informationen, was passiert (ist).

Hast Du schon eine Idee für die Analyse und Visualisierung Deiner Logs?

von Sheeva P. (sheevaplug)


Lesenswert?

Sebastian W. schrieb:
> Der crond startet doch sowieso eine Shell für das Parsen und die
> Ausführung der Kommandozeile in Spalte 6. Warum dann nicht das
> speedtest.sh-Skript dort über den Befehl source in dieser Shell
> ausführen, anstatt noch eine weitere innere Shell zu starten? Oder
> übersehe ich etwas?

"source" ist ein Bashism und obendrein dazu gedacht, Umgebungsvariablen 
in der laufenden Shell zu setzen. Wegen der potentiellen Seiteneffekte 
sollte man das nicht ohne Not benutzen!

von Rolf M. (rmagnus)


Lesenswert?

Sheeva P. schrieb:
> Bitte sei so lieb und mach hinter alle Zeilen außer "bash", "then" und
> "fi" jeweils ein Semikolon. Das ändert nichts an der Funktion, macht
> Dein Skript aber vermutlich nicht nur aus meiner Perspektive lesbarer.

Hmm, für mich nicht. Sie würden mich eher irritieren, und ich würde mich 
fragen, warum da überall unnötige Semikolons sind. Ich kenne das von 
Shellskripten eher nicht, dass da jede Zeile mit einem Semikolon 
abgeschlossen wäre.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Rolf M. schrieb:
> Hmm, für mich nicht.

Sehe ich genauso. Die zusätzlichen Semikolons sind hyperfluid und tragen 
meiner Meinung auch nicht zur Lesbarkeit bei.

von Norbert (der_norbert)


Lesenswert?

Ein Semikolon trennt.
Ein Newline trennt.
Ein Semikolon Newline trennt trennt.
1
if [ 1 -eq 1 ]; then echo 1; fi
ist so gut wie:
1
if [ 1 -eq 1 ]; then
2
  echo 1
3
fi

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Chandler B. schrieb:
> Und in der Log konnte ich dann tatsächlich einen Error finden

Nur zur Info: Als Du noch nicht den Standard-Fehler-Ausgabekanal 
(stderr) in cron.log umgeleitet hast, hätte cron Dir eine Mail schicken 
müssen.

Grund: Immer wenn der zu startende Job etwas auf dem 
Standard-Ausgabekanal (stdout) oder Standard-Fehler-Ausgabekanal 
(stderr) ausgibt, schickt der cron eine lokale Mail mit dem Inhalt. 
Durch die neue Umleitung in cron.log unterlässt er das jetzt.

Wenn Du in der Shell also mal "mail" eingibst, sollten Dir Dutzende von 
Mails von Deinen vorhergehenden Versuchen entgegenwinken :-)

Voraussetzung ist natürlich, dass auf dem System zumindest ein minimales 
Mail-Paket installiert ist.

: Bearbeitet durch Moderator
von Chandler B. (chandler)


Lesenswert?

Sheeva P. schrieb:
> Auch Deine Dateinamenerweiterung halte ich für, sagen wir, schwierig.
> Wenn ich Bash-Skripte schreibe, dann enden sie auf ".bash", wenn ich
> allgemeingültige Shellskripte schreibe, auf ".sh", entsprechend auch
> Skripte für die Korn- und die Z-Shell (".ksh" und ".zsh").

leider weiß ich nicht, was genau der unterschied zwischen .bash und .sh 
ist.
Was wäre denn jetzt hier richtig?
* Das „Shebang“ entfernen?
* Die Datei .bash nennen und mit bash aufrufen?

Sheeva P. schrieb:
> Dann habe ich ein zweites Problem mit Deinem Ansatz, nämlich das
> Schreiben in /home. Sowas würde ein erfahrener Sysop einfach nicht
> machen, sorry. Es gibt für so etwas das Verzeichnis /var/log, und rate,
> wofür das da ist? Haargenau: für _var_iable _log_Daten.

Ok, da ich aber nicht so oft auf dem rasperry pi bin, hatte ich es 
direkt ins home gemacht, damit ich das sofort sehe und weiß das da was 
ist.
Aber ja, es gibt bestimmt einen besseren Ort (in diesem fall /var/log) 
dafür.

Sheeva P. schrieb:
> Hast Du schon eine Idee für die Analyse und Visualisierung Deiner Logs?

Das werde ich wahrscheinlich mit Python machen.

Frank M. schrieb:
> Wenn Du in der Shell also mal "mail" eingibst, sollten Dir Dutzende von
> Mails von Deinen vorhergehenden Versuchen entgegenwinken :-)
>
> Voraussetzung ist natürlich, dass auf dem System zumindest ein minimales
> Mail-Paket installiert ist.

Wie bekomme ich das denn heraus? Also wenn ich keine "richtige" 
E-Mailadresse hinterlegt habe, gäbe es dann etwas internes?
Wenn ich mit Putty auf dem raspberry pi bin und "mail" eingebe, bekomme 
ich den fehler
-bash: mail: command not found

Ein T. schrieb:
> Nunja, der TO sagt ja, mit anderen Einträgen in den Datums- und
> Zeitfeldern der Crontab würde dasselbe Skript funktionieren. Das würde
> es jedoch nicht, wenn die Dateirechte nicht korrekt gesetzt wären. Es
> bleibt mysteriös. :-)

Das Problem war wahrscheilich die 0 bei den Minuten.
Jetzt wo ich dort 8 Eingetragen habe, funktioniert es ohne Probleme 
(bisher). Also alle 8 minuten nach, alle 3 Stunden.

So kann ich es jetzt erstmal laufen lassen.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Chandler B. schrieb:
> Also wenn ich keine "richtige" E-Mailadresse hinterlegt habe, gäbe es
> dann etwas internes?

Ja, der cron schickt den Output nach user@localhost.

> Wenn ich mit Putty auf dem raspberry pi bin und "mail" eingebe, bekomme
> ich den fehler
> -bash: mail: command not found

Dann ist auch kein Mailpaket drauf und der cron konnte Dir dann auch 
nicht den Output per Mail schicken. Genau wie ich schon sagte:

Frank M. schrieb:
> Voraussetzung ist natürlich, dass auf dem System zumindest ein minimales
> Mail-Paket installiert ist.

Aber egal: Ich selbst finde die Lösung mit den Log-Dateien sowieso 
praktischer.

: Bearbeitet durch Moderator
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Chandler B. schrieb:
> Aber ja, es gibt bestimmt einen besseren Ort (in diesem fall /var/log)
> dafür.

Ich persönlich hatte ja eine Logdatei unter /tmp vorgeschlagen - aber 
nur deswegen, weil Du uns nicht verraten hast, unter welcher User-ID 
Dein cron-Job überhaupt läuft. /tmp macht da keine Probleme, unter 
/var/log kann kein normaler User etwas anlegen.

Aber da Du ja dann tatsächlich als Logdatei /home/cron.log gewählt hast, 
wo ein normal sterblicher User auch nix schreiben kann, vermute ich mal, 
dass der Job als User root läuft. Dann hättest Du natürlich 
Schreibberechtigung unter /var/log.

von Hmmm (hmmm)


Lesenswert?

Frank M. schrieb:
> Aber da Du ja dann tatsächlich als Logdatei /home/cron.log gewählt hast,
> wo ein normal sterblicher User auch nix schreiben kann, vermute ich mal,
> dass der Job als User root läuft. Dann hättest Du natürlich
> Schreibberechtigung unter /var/log.

Ich werfe mal logger(1) in den Raum, um es sauber zu lösen.

von Ein T. (ein_typ)


Lesenswert?

Chandler B. schrieb:
> leider weiß ich nicht, was genau der unterschied zwischen .bash und .sh
> ist.
> Was wäre denn jetzt hier richtig?
> * Das „Shebang“ entfernen?
> * Die Datei .bash nennen und mit bash aufrufen?

Die Shebang-Zeile zu entfernen, ist sicherlich keine gute Idee. Aber 
fangen wir ungewöhnlicherweise mit dem Anfang an...

Auf vielen Linux-Systemen ist /bin/sh ein symbolischer Link auf 
/bin/bash, also wird ein Aufruf von "sh", wie Du ihn in Deiner Crontab 
verwendest, die Bash aufrufen. Auf Debian-basierten Systemen ist das 
allerdings nicht so, dort ist /bin/sh ein Symlink auf /bin/dash, die 
Debian Almquist Shell, die leider in einigen Bereichen nicht mit der 
Bash kompatibel ist. Dafür ist sie etwas performanter und benötigt 
weniger Systemressourcen, deswegen haben die Leute bei Debian das so 
gemacht.

Du hingegen rufst mit Deiner Shebang-Zeile die Bash auf. Wenn jemand wie 
ich dieses Skript bearbeitet und diese Shebang-Zeile sieht, gehe ich 
davon aus, daß die Bash benutzt wird und ich daher auch 
Bash-Besonderheiten (Bashisms) benutzen kann, also die Möglichkeiten, 
welche zwar die Bash bietet, und die andere Shells womöglich aber nicht 
bieten. Solange ich keine Bashisms nutze, ist es kein Problem, das 
Skript mit "sh", also "/bin/sh" aufzurufen. Aber da Deine Shebang-Zeile 
ausssagt, daß zur Ausführung die Bash benutzt wird, heißt das für mich, 
daß ich Bashisms benutzen darf. Und die fallen mir dann sofort auf die 
Füße, wenn das Skript nicht von der Bash ausgeführt wird.

Also kannst Du entweder Deine Shebang-Zeile durch "#!/bin/sh" ersetzen 
und dadurch signalisieren, daß das Skript keine Bashisms nutzen darf, 
oder die Shebang-Zeile so lassen, wie sie ist, und den Aufruf Deines 
Skripts mit "sh" in der Crontab durch "bash" oder noch besser 
"/bin/bash" ersetzen und das Skript dann eindeutig mit der Bash 
aufrufen.

von Rolf M. (rmagnus)


Lesenswert?

Um's nochmal kurz un knapp zu machen: (Ich nehme mal an, auf deinem 
Raspi läuft ein debian-basiertes System)
1
./speedtest.sh
-> Skript läuft in der bash, weil der Shebang das so vorgibt. Die 
Dateinamens-Endung '.sh' ist dann etwas irritierend, aber für die 
Ausführung des Skripts nicht relevant.
1
sh speedtest.sh
-> Skript läuft in der dash, weil du es explizit mit sh gestartet hast, 
das auf die dash verweist. Das passt zwar zur Dateinamens-Endung '.sh', 
aber nicht zu deinem Shebang, das eigentlich die bash will.
1
bash speedtest.sh
-> Skript läuft mit der bash, weil du es explizit damit gestartet hast.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Rolf M. schrieb:
> Die
> Dateinamens-Endung '.sh' ist dann etwas irritierend, aber für die
> Ausführung des Skripts nicht relevant.
> ... Das passt zwar zur Dateinamens-Endung '.sh',
> aber nicht zu deinem Shebang, das eigentlich die bash will.

Warum so kompliziert?

Warum muss die Endung zu der Shell passen, mit der man es ausführt? 
Meiner Meinung nach muss die Endung lediglich zu der Shell passen, mit 
der man es ausführen kann.

Oder mit anderen Worten:

Solange das Script keine bashisms enthält, verdient es auch die Endung 
".sh", denn es ist vollkommen irrelevant, mit welcher 
(Posix-kompatiblen) Shell man es tatsächlich ausführt.

Wenn's nur mit dash liefe, würde ich .dash wählen, wenn es nur mit bash 
liefe, würde ich .bash wählen. Wenn's mit allen liefe, dann ist .sh 
gerechtfertigt. Die Endung ".sh" ist sogar hilfreich, denn sie zeigt an, 
dass das Script kompatibel ist.

von Michi S. (mista_s)


Lesenswert?

Chandler B. schrieb:
> dass die Server immer in der Vollen Stunde und
> Halben Stunde überlastet sind.

> Werde ich dann morgen sehen, ob es das Problem war.

Na das ist ja 'ne fiese Erklärung.

Erinnere mich jetzt aber daran, in grauer Vorzeit - als richtige PCs 
noch viel, viel lahmer waren als ein RasPi heute - gab es den Tip 
cron-jobs die man ein mal täglich oder stündlich laufen haben wollte, 
besser nicht auf Mitternacht bzw. volle Stunden zu setzen, weil da die 
Systeme oft eh schon genug zu tun hatten.


Sheeva P. schrieb:
> "source" ist ein Bashism und

Jetzt wollte ich schon widersprechen, aber das stimmt für ja für source 
tatsächlich, den (in der Praxis ohnehin fast ausschließlich 
geschriebenen) . gibt es aber mindestens seit der Bourne-Shell.

> obendrein dazu gedacht, Umgebungsvariablen
> in der laufenden Shell zu setzen.

Das hingegen kann man so nicht stehen lassen, jedenfalls nicht im 
Zusammenhang mit shell-Skripten. In solchen dient es eigentlich vor 
allem als include-Statement.

von Rolf M. (rmagnus)


Lesenswert?

Frank M. schrieb:
> Warum muss die Endung zu der Shell passen, mit der man es ausführt?

Die Endung ist doch dafür da, dass man weiß, mit welcher Shell es 
ausgeführt werden soll, wobei sh dann für "irgendeine POSIX-konforme 
Shell" steht.

> Solange das Script keine bashisms enthält, verdient es auch die Endung
> ".sh", denn es ist vollkommen irrelevant, mit welcher
> (Posix-kompatiblen) Shell man es tatsächlich ausführt.

Dann sollte das Shebang allerdings auch nicht #!/bin/bash lauten, was es 
hier aber tut.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Rolf M. schrieb:
> Dann sollte das Shebang allerdings auch nicht #!/bin/bash lauten, was es
> hier aber tut.

Das siehe ich nicht so eng. Die Endung zeigt an, womit es laufen kann, 
das Shebang zeigt an, womit es hier konkret laufen soll. Schließlich 
ist /bin/sh in den meisten Fällen sowieso ein Symlink auf irgendeine 
konkrete Shell.

von Norbert (der_norbert)


Lesenswert?

Mich würde mal interessieren, woher dieser sonderbare Wunsch kommt, ein 
Shell-Script extra mit  /bin/{bash,dash,sh} laufen zu lassen.

Mir hat bis jetzt immer ein zuvor angewandtes:
chmod u=rx,go= filename
gereicht.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Norbert schrieb:
> Mich würde mal interessieren, woher dieser sonderbare Wunsch kommt, ein
> Shell-Script extra mit  /bin/{bash,dash,sh} laufen zu lassen.

Ich benutze das Konstrukt nur, um ein Script mit -x zu starten, damit 
ich sehe, was es tut. Okay, ich könnte auch das Script editieren und ein 
"set -x" reinsetzen (und nachher wieder rausnehmen), aber für eine 
Ad-Hoc-Action ist das einfacher:
1
sh -x filename.sh

> Mir hat bis jetzt immer ein zuvor angewandtes:
> chmod u=rx,go= filename
> gereicht.

Jepp, mache ich in der Regel auch so. Manchmal lasse ich auch die Endung 
".sh" weg, weil mir dann egal ist, ob die ausführbare Datei ein Script 
oder ein ELF-Executable ist. Von welchem Typ die Datei letztendlich ist, 
bekommt, man ja mit "file" raus:
1
file filename

von Rolf M. (rmagnus)


Lesenswert?

Frank M. schrieb:
> Rolf M. schrieb:
>> Dann sollte das Shebang allerdings auch nicht #!/bin/bash lauten, was es
>> hier aber tut.
>
> Das siehe ich nicht so eng.

Das sehe ich "enger" als die Endung, denn die ist nur informativer 
Natur, während das Shebang tatsächlich Einfluss auf das Verhalten des 
Systems hat.

> Die Endung zeigt an, womit es laufen kann, das Shebang zeigt an, womit es
> hier konkret laufen soll.

Warum soll das Skript mit was anderen laufen als dem, wofür es 
geschrieben ist? Welchen Vorteil soll das bringen? Entweder schreibe ich 
es für die Bash, dann will ich auch, dass es mit der Bash ausgeführt 
wird, oder ich schreiben es so, dass es egal ist, dann ist es eben auch 
egal.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Rolf M. schrieb:

> Das sehe ich "enger" als die Endung, denn die ist nur informativer
> Natur, während das Shebang tatsächlich Einfluss auf das Verhalten des
> Systems hat.

Nochmal zum Verständnis:

Wenn ich ein kompatibles Shell-Script mit der Endung ".sh" speichere, 
dann hat das Shebang überhaupt keinen "Einfluss auf das Verhalten des 
Systems". Schreibe /bin/sh, /bind/bash, /bin/dash oder /bin/ksh rein, es 
ändert nichts. Das Verhalten ist immer gleich.

Genau das meinte ich und nichts anderes.

Andersherum wird ein Schuh daraus:

Inkompatible Shell-Scripts würde ich niemals mit der Endung ".sh" 
versehen. Wenn ich bashisms nutzen würde, dann wäre bei mir die Endung 
.bash und das Shebang selbstverständlich /bin/bash.

P.S.

Meine Shell-Scripts schreibe ich so, dass sie in jeder Posix-kompatiblen 
Shell laufen. ICh nutze grundsätzlich keine bashisms oder andere 
Shell-Spezifika.

: Bearbeitet durch Moderator
von Rolf M. (rmagnus)


Lesenswert?

Frank M. schrieb:
> Rolf M. schrieb:
>
>> Das sehe ich "enger" als die Endung, denn die ist nur informativer
>> Natur, während das Shebang tatsächlich Einfluss auf das Verhalten des
>> Systems hat.
>
> Nochmal zum Verständnis:
>
> Wenn ich ein kompatibles Shell-Script mit der Endung ".sh" speichere,
> dann hat das Shebang überhaupt keinen "Einfluss auf das Verhalten des
> Systems". Schreibe /bin/sh, /bind/bash, /bin/dash oder /bin/ksh rein, es
> ändert nichts. Das Verhalten ist immer gleich.
> Genau das meinte ich und nichts anderes.

Nein, wenn du das Skript in der Art "./meinskript" aufrufst, wird die 
Shell verwendet, die im Shebang steht, ganz unabhängig von der Endung. 
Wenn du es POSIX-konform gestaltet hast, gibt es keinen Grund, über das 
Shebang dann die bash zu erzwingen. Und wenn du da stattdessen was 
angibst, was keine POSIX-konforme Shell ist, dann funktioniert dein 
Skript ggf. auch gar nicht. Das Shebang hat also sehr wohl einen 
Einfluss, ganz im Gegensatz zur Endung.
Und das ist es, was ich meinte.

> Andersherum wird ein Schuh daraus:
>
> Inkompatible Shell-Scripts würde ich niemals mit der Endung ".sh"
> versehen. Wenn ich bashisms nutzen würde, dann wäre bei mir die Endung
> .bash und das Shebang selbstverständlich /bin/bash.

Ja, so sehe ich das auch. Und wenn ich keine bashisms nutze, verweist 
das Shebang selbstverständlich nicht auf /bin/bash, denn sonst hätte 
ich das Skript ja völlig umsonst POSIX-konform geschrieben und hätte 
auch gleich Bashisms nutzen können.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.