Array mit IP-Adressen an Ping-Befehl übergeben (Raspberry Pi 3 B+)

M

m5space

Gast
Hallo zusammen,

ich möchte von meinem Raspberry Pi aus mehrere IP-Adressen per Cronjob anpingen.

Es scheitert jetzt nur noch an zwei Programmzeilen.

Erstens: Wenn eine log-Datei noch nicht existiert, soll diese erstellt werden, hier werden die Kopfspalten nicht vollständig erstellt. Die Kopfspalten sollten eigentlich alle IP-Adressen beinhalten, die ich vorgebe.
Code:
datum;uhrzeit;18.35.2021;19:35:59;success;
18.39.2021;19:39:14;success;
18.47.2021;19:47:47;success;
18.47.2021;19:47:53;success;


Zweitens: Ich möchte ein Array mit IP-Adressen an den Ping-Befehl übergeben, das klappt nicht. Ausgabe:
Code:
pi@Brotdose:~/pingtest $ ./pingtest.zsh
./pingtest.zsh: line 39: 127.0.0.1: syntax error: invalid arithmetic operator (error token is ".0.0.1")
pi@Brotdose:~/pingtest $

Wo kann ich mit Suchen anfangen?

Hier ist das komplette Skript pingtest.zsh:
Code:
#!/bin/bash

#skript-funktion:
#die ping-ausgabe wird nach ´0 received´ jdurchsucht,
#dementsprechend wird ein ping als erfolgt oder fehlerhaft gewertet
#ping-ergebnisse landen in einer csv-datei

#variablen
d=$(date +%d.%M.%Y)
t=$(date +%H:%M:%S)
#anzupingende ip adressen
arr=(127.0.0.1 10.0.0.1 8.8.8.8 8.8.4.4 217.5.100.185 217.5.100.186)

#prüfen ob logdatei existiert, ggf. eine erstellen
if [ -f "/home/pi/pingtest/pingtest.csv" ];
then
    #nichts zu tun
    echo "" >> /dev/null
else
    #logdatei erstellen mitsamt kopfzeile
    echo -n "datum;uhrzeit;" > pingtest.csv
    for i in arr
    do
        echo -n "${arr[i]};" >> pingtest.csv
    done
fi

#datum in logdatei schreiben
echo -n $d >> pingtest.csv
echo -n ';' >> pingtest.csv

#uhrzeit in logdatei schreiben
echo -n $t >> pingtest.csv
echo -n  ';' >> pingtest.csv

#alle ip adressen durchpingen
for n in arr
do
    if echo $(ping -c 1 ${arr[n]}) | grep "0 received" &> /dev/null;
        then
            echo -n "fail;";
        else
            echo -n "success;";
    fi >> pingtest.csv
done

#zeilenende, zeilenumbruch
echo "" >> pingtest.csv

#ende

LG!
 
Zuletzt bearbeitet von einem Moderator:
Dein Skript wird mit bash ausgeführt und dort sind deine for-Schleifen alle kaputt. Du musst "for i in ${arr[@]}" ausführen. Dann kannst du in der Schreife über $i auf den Inhalt des Arrayelements zugreifen.

Beispiel:
Bash:
arr=(a b c d)
for i in ${arr[@]}
do
  echo $i
done

Wenn du das Skript im Debug-Modus ausführst, siehst du auch viel besser was genau passiert:
Code:
bash -x deinskript

Alternativ kannst du auch die erste Zeile (shebang) anpassen:
Code:
#!/bin/bash -x

Edit:
Gregs Wiki ist auch immer gut bei Bash-Fragen:
https://mywiki.wooledge.org

@derFireBird Das täuscht. 😀
 
Zuletzt bearbeitet von einem Moderator:
  • Gefällt mir
Reaktionen: m5space, GTrash81 und madmax2010
Moin,

hab zwar nicht direkt bash-Ahnung und Testmöglichkeit, aber das interessiert mich auch.

Es scheint an deinen for-schleifen zu liegen.
Wenn ich mir das hier https://openbook.rheinwerk-verlag.d...hell_006_009.htm#RxxKap00600904004E2B1F04E1A6 so ansehe, müsstest du die Schleifen nicht einfach mit "for i in arr" sondern mit "for i in ${arr[*]}" einleiten.

Der echo-Befehl für die CSV und der Ping müsste dann ja mit $i bzw. $n als Variable gehen, da dort dann die IP-Adresse drinstehen müsste?!
Ansonsten müsstest du mit ${#arr[*]} die Anzahl der Elemente an die for-Schleife übergeben (wenn ich das richtig sehe), dann müsste so wie du denkst die aktuelle Zählnummer in "i" bzw. "n" stehen, welche dann wieder zum Aufruf des entsprechenden Elements im Array verwendet werden kann so wie du es jetzt versuchst (nur dass ich eben denke, dass in i/n eben keine Zahl drin steht?!)

EDIT: ??? war schneller und scheint auch mehr Ahnung wie ich zu haben ;-) da scheint das ja der richtige Weg zu sein.
 
Dankeschööön.

Was mir noch Sorge bereitet: Kann man einen if-Zweig leer lassen? Wenn ich keinen Befehl reinschreibe kommt bei mir eine Fehlermeldung.

Ausführung OK:
Code:
then
    #nichts zu tun
    echo "" >> /dev/null
else

Ausführung mit Fehler abgebrochen:
Code:
then
    #nichts zu tun
else

EDIT: Noch was. Mein Cronjob auf dem Raspberry PI 3B+ startet nicht. Ideen?

crontab -l:
Code:
pi@Brotdose:~/pingtest $ crontab -l
* * * * * /home/pi/pingtest/pingtest.zsh
pi@Brotdose:~/pingtest $

----------

Hier die funktionsfähigen Dateien:

pingtest.zsh:
Code:
#!/bin/bash

#skript-funktion:
#die ping-ausgabe wird nach ´0 received´ durchsucht,
#dementsprechend wird ein ping als erfolgt oder fehlerhaft gewertet
#ping-ergebnisse landen in einer csv-datei

#variablen
d=$(date +%d.%m.%Y)
t=$(date +%H:%M:%S)
filename=pingtest.csv

#anzupingende ip adressen
arr=(127.0.0.1 10.0.0.1 8.8.8.8 8.8.4.4 217.5.100.185 217.5.100.186)

#prüfen ob logdatei existiert, ggf. eine erstellen
if [ -f "/home/pi/pingtest/$filename" ];
then
    #nichts zu tun
    echo "" >> /dev/null
else
    #logdatei erstellen mitsamt kopfzeile
    echo -n "date d.m.Y;time CET 24h;" > $filename
    for i in ${arr[@]}
    do
        #ip-adressen in die spaltenheader writen
        echo -n "$i" >> $filename
        echo -n ";" >> $filename
    done
    #zeilenende, zeilenumbruch
    echo "" >> $filename
fi

#datum in logdatei schreiben
echo -n $d >> $filename
echo -n ';' >> $filename

#uhrzeit in logdatei schreiben
echo -n $t >> $filename
echo -n  ';' >> $filename

#alle ip adressen durchpingen
for n in ${arr[@]}
do
    if echo $(ping -c 1 $n) | grep "0 received" &> /dev/null;
        then
            echo -n "fail;";
        else
            echo -n "success;";
    fi >> $filename
done

#zeilenende, zeilenumbruch
echo "" >> $filename

#ende

pingtest.csv:
Code:
date d.m.Y;time CET 24h;127.0.0.1;10.0.0.1;8.8.8.8;8.8.4.4;217.5.100.185;217.5.100.186;
19.07.2021;10:47:27;success;success;success;success;success;success;
19.07.2021;10:48:14;success;success;success;success;success;success;
19.07.2021;10:48:35;success;success;success;success;success;success;
 
Zuletzt bearbeitet von einem Moderator:
Hm, naja, bei if ist das then obligatorisch und das else optional. Ein einfaches ! bringt da eigentlich die Lösung.

Bash:
if [ ! -f "/home/pi/pingtest/$filename" ];
then
    #logdatei erstellen mitsamt kopfzeile
    echo -n "date d.m.Y;time CET 24h;" > $filename
    for i in ${arr[@]}
    do
        #ip-adressen in die spaltenheader writen
        echo -n "$i" >> $filename
        echo -n ";" >> $filename
    done
    #zeilenende, zeilenumbruch
    echo "" >> $filename
fi
 
  • Gefällt mir
Reaktionen: m5space
derFireBird schrieb:
Ein einfaches ! bringt da eigentlich die Lösung.

Sänk Ju. Mit dem Ausrufezeichen habe ich ebenfalls schon herumexperimentiert aber außer Fehlermeldungen nichts zustandebekommen. Danke.
 
m5space schrieb:
Mein Cronjob auf dem Raspberry PI 3B+ startet nicht. Ideen?
Ist das Skript ausführbar?

Schau' dir mal die Ausgabe von ...
Code:
ls -l /home/pi/pingtest/pingtest.zsh
... an. Wenn die Zeile nicht in etwa so „.rwxr-xr-x ...“ anfängt (das x ist wichtig), dann musst du es noch als ausführbar markieren:
Code:
chmod +x /home/pi/pingtest/pingtest.zsh
 
Ja, ausführbar wäre es eigentlich schon. Dies habe ich bereits kurz nach der Skripterstellung mit chmod erledigt. Crondienst habe ich mit sudo service cron restart auch schon neu gestartet ohne Erfolg.

Ich glaube, mein Cronservice ist kaputt. Ich habe eine zusätzliche Zeile eingefügt, aber auch diese wird nicht abgearbeitet. Es wird keine Datei "nix" angelegt.

EDIT: Oh! Doch. Die Datei nix wird angelegt im Homeverzeichnis. Zeile 2 klappt also, Zeile 1 nicht.

Code:
pi@Brotdose:~/pingtest $ crontab -l
* * * * * /home/pi/pingtest/pingtest.zsh
* * * * * touch nix

pi@Brotdose:~/pingtest $

Nochmal EDIT: Ich habe im falschen Verzeichnis nachgesehen, die pingtest.csv wird nicht im Verzeichnis /pingtest angelegt sondern im /home/pi. Der cron service funktioniert also ;)

Hier also nochmals das korrigierte und funktionierende Skript:

pingtest.zsh

Code:
#!/bin/bash

#skript-funktion:
#die ping-ausgabe wird nach ´0 received´ durchsucht,
#dementsprechend wird ein ping als erfolgt oder fehlerhaft gewertet
#ping-ergebnisse landen in einer csv-datei

#variablen
d=$(date +%d.%m.%Y)                #datum
t=$(date +%H:%M:%S)                #uhrzeit
f="/home/pi/pingtest/pingtest.csv" #ort und name der logdatei

#anzupingende ip adressen
arr=(127.0.0.1 10.0.0.1 8.8.8.8 8.8.4.4 217.5.100.185 217.5.100.186 195.50.140.114 195.50.140.252 217.237.150.188 217.237.150.33 83.169.185.161 83.169.185.225 83.169.186.161 83.169.184.33 83.169.184.97)

#prüfen ob logdatei existiert, wenn nicht, eine erstellen
if [ ! -f "$f" ];
then
    #logdatei erstellen mitsamt kopfzeile
    echo -n "date d.m.Y;time CET 24h;" > $f
    for i in ${arr[@]}
    do
        #ip-adressen in die spaltenheader writen
        echo -n "$i" >> $f
        echo -n ";" >> $f
    done
    #zeilenende, zeilenumbruch
    echo "" >> $f
fi

#datum in logdatei schreiben
echo -n $d >> $f
echo -n ';' >> $f

#uhrzeit in logdatei schreiben
echo -n $t >> $f
echo -n  ';' >> $f

#alle ip adressen durchpingen
for n in ${arr[@]}
do
    if echo $(ping -c 1 $n) | grep "0 received" &> /dev/null;
        then
            echo -n "fail;";
        else
            echo -n "success;";
    fi >> $f
done

#zeilenende, zeilenumbruch
echo "" >> $f

#ende
 
Zuletzt bearbeitet von einem Moderator:
Spontan würde ich sagen, den Pfad findest du am Besten so raus:
Bash:
my_location=${BASH_SOURCE%/*}
Die Variable $f kannst du also so definieren:
Bash:
f="${BASH_SOURCE%/*}/pingtest.csv"

Wenn du mehr über den roten Teil in "${variable%/*}" wissen möchtest, dann ist "parameter expansion" das richtige Stichwort. 😉
 
Das klappt noch nicht so ganz, BASH_SOURCE zeigt mir als Pfad lediglich einen Punkt.

PS: Wie verknüpfe ich Strings? Mit "_" oder "+" will es nicht klappen.

Code:
Code:
#!/bin/bash

echo "pwd: " _ $(pwd)
echo "BASH_SOURCE: " _ ${BASH_SOURCE%/*}
l=${BASH_SOURCE%/*}
echo $l

Ausgabe:
Code:
pi@Brotdose:~/location $ ./showme.sh
pwd:  _ /home/pi/location
BASH_SOURCE:  _ .
.
pi@Brotdose:~/location $
 
Zuletzt bearbeitet von einem Moderator:
m5space schrieb:
Das klappt noch nicht so ganz, BASH_SOURCE zeigt mir als Pfad lediglich einen Punkt.
Das ist doch richtig, wenn das Skript im selben Verzeichnis liegt.

m5space schrieb:
PS: Wie verknüpfe ich Strings? Mit "_" oder "+" will es nicht klappen.
So
Code:
echo "pwd: $(pwd)"
Oder so
Code:
echo "pwd:" $(pwd)
Oder auch so
Code:
echo "pwd: "$(pwd)
 
??? schrieb:
Das ist doch richtig, wenn das Skript im selben Verzeichnis liegt.
Ich hätte mir da eigentlich ein "/home/pi/pingtest" erhofft und nicht ein ".".

Mit pwd klappt's jedenfalls schonmal nicht, da speichert das Skript die csv-Datei immer im Home-Ordner, aber da soll sie ja nicht hin, sondern in dasselbe Verzeichnis, in dem auch das zsh-Skript liegt.

So nicht:
Code:
l=$(pwd)            #l=location, aktueller pfad
f="/pingtest.csv"   #f=file,     name der logdatei

#prüfen ob logdatei existiert, wenn nicht, eine erstellen
if [ ! -f "$l$f" ];
 
m5space schrieb:
Mit pwd klappt's jedenfalls schonmal nicht, da speichert das Skript die csv-Datei immer im Home-Ordner, aber da soll sie ja nicht hin, sondern in dasselbe Verzeichnis, in dem auch das zsh-Skript liegt.
Die Lösung dafür hatte ich dir schon gezeigt. 😉
Bash:
f="${BASH_SOURCE%/*}/pingtest.csv"

Probier's doch einfach mal aus. Wenn du das Skript aus einem anderen Pfad aus aufrufst, wird der Inhalt der Variable $BASH_SOURCE korrekt angepasst. Ich wüsste nicht, warum man da mit pwd hantieren muss, denn das aktuelle Verzeichnis hat doch nicht unbedingt etwas mit dem Verzeichnis zu tun, in dem das Skript liegt.
 
Zuletzt bearbeitet von einem Moderator:
??? schrieb:
Die Lösung dafür hatte ich dir schon gezeigt. 😉
Ja das weiß ich ;) Nachdem aber da nur ein Punkt ausgespuckt wird, habe ich das wieder verworfen. Sinn der Sache wäre halt, dass ich das Skript in ein x-beliebiges Verzeichnis platzieren kann und eben genau dort auch die csv-Datei erstellt wird. Werden soll. Klappt aber weder mit pwd noch mit BASH_SOURCE.
 
m5space schrieb:
Sinn der Sache wäre halt, dass ich das Skript in ein x-beliebiges Verzeichnis platzieren kann und eben genau dort auch die csv-Datei erstellt wird.
Aber genau das passiert doch, wenn du $f benutzt und die Variable so initialisierst, wie ich schrieb. Sorry, ich kann dir nicht folgen.
 
Ich hab da wohl irgend etwas vermurkst.

Jetzt klappt es.

pingtest.zsh:

Code:
#!/bin/bash

#skript-funktion:
#die ping-ausgabe wird nach ´0 received´ durchsucht,
#dementsprechend wird ein ping als erfolgt oder fehlerhaft gewertet
#ping-ergebnisse landen in einer csv-datei

#variablen
d=$(date +%d.%m.%Y)                #d=date, datum
t=$(date +%H:%M:%S)                #t=time, uhrzeit
f="${BASH_SOURCE%/*}/pingtest.csv" #f=file, speicherort und dateiname

#anzupingende ip adressen
arr=(127.0.0.1 10.0.0.1 8.8.8.8 8.8.4.4 217.5.100.185 217.5.100.186 195.50.140.114 195.50.140.252 217.237.150.188 217.237.150.33 83.169.185.161 83.169.185.225 83.169.186.161 83.169.184.33 83.169.184.97)

#prüfen ob logdatei existiert, wenn nicht, eine erstellen
if [ ! -f "$f" ];
then
    #logdatei erstellen mitsamt kopfzeile
    echo -n "date d.m.Y;time CET 24h;" > $f
    for i in ${arr[@]}
    do
        #ip-adressen in die spaltenheader writen
        echo -n "$i" >> $f
        echo -n ";" >> $f
    done
    #zeilenende, zeilenumbruch
    echo "" >> $f
fi

#datum in logdatei schreiben
echo -n $d >> $f
echo -n ';' >> $f

#uhrzeit in logdatei schreiben
echo -n $t >> $f
echo -n  ';' >> $f

#alle ip adressen durchpingen
for n in ${arr[@]}
do
    if echo $(ping -c 1 $n) | grep "0 received" &> /dev/null;
        then
            echo -n "fail;";
        else
            echo -n "success;";
    fi >> $f
done

#zeilenende, zeilenumbruch
echo "" >> $f

#ende

Kurz getestet:

Anhang anzeigen 1103684
 
Zurück
Oben