Forum: PC-Programmierung CRON: curl wird nicht ausgeführt


von RasPi (Gast)


Lesenswert?

Hallo!

Ich habe ein komisches Problem an meinem Raspberry Pi.

Ich habe ins Crontab eingetragen:

@reboot /home/pi/startskript.sh

Der Inhalt des Startskripts:
1
#!/bin/bash
2
3
#Höchstens 80 Sek auf das Netzwerk warten
4
t=0
5
while [ "$(hostname -I)" = "" ]; do
6
  sleep 1
7
  if [ "$t" -gt 80 ];
8
  then
9
    /usr/sbin/shutdown now
10
    exit 1
11
  fi
12
  
13
  t=$((t+1))
14
    
15
done
16
17
#Ntfy Nachricht mit aktueller IP-Adresse inkl. Port
18
/usr/bin/curl -d "http://$(ip route get 8.8.8.8 | awk -F"src " 'NR==1{split($2,a," ");print a[1]}'):5000" ntfy.sh/blabla
19
20
#Hauptprogramm starten
21
cd /home/pi/projekt && ./main
22
23
exit 0

Führe ich das Skript normal aus dem Terminal aus, wird mir per ntfy die 
aktuelle IP-Adresse auf mein Handy gesendet und "main" gestartet.

Starte ich den Pi neu, bekomme ich keine Nachricht auf's Handy, "main" 
wird aber sehrwohl gestartet, das Skript wird also nach dem Hochfahren 
ausgeführt. Wieso funktioniert der curl-Befehl nicht, wenn das Skript 
von CRON gestartet wird??

Was ich schon versucht habe:
- Man liest oft, dass man absolute Pfade nehmen muss -> habe ich getan.
- Habe auch schon versucht den langen komplizierten Befehl durch ein 
"hallo" zu ersetzen -> kein Effekt
- Habe auch versucht die Anführungszeichen zu maskieren mit \"hallo\" -> 
auch dann kommt keine Nachricht am Handy an.

Bitte um Hilfe und danke im Voraus!!

von Εrnst B. (ernst)


Lesenswert?

@reboot wird unter Umständen ausgeführt, bevor das Netzwerk komplett 
hochgefahren ist. Dein "hostname -I" findet auch irgendwelche 
temporären/automatisch vergebenen IPs, sagt also nicht ob schon ein DHCP 
gelaufen ist, und auch Internet verfügbar ist.
Bastel dir ein Logfile mit in das Script, wo du die hostname -I Ausgabe 
reinschreibst. Dann siehst du das.


Besser: mach dir eine systemd-Unit, da kannst du mit 
"After=network-online.target" die Start-Anhängigkeiten vorgeben.


d.H. Datei /etc/systemd/system/meinstartscript.service anlegen:
1
[Unit]
2
Description=Mein Startscript
3
After=network-online.target
4
5
[Service]
6
Type=simple
7
WorkingDirectory=/home/pi
8
### Optional, wenn's nicht als root laufen soll:
9
## User=pi
10
## Group=pi
11
ExecStart=/home/pi/startskript.sh
12
13
[Install]
14
WantedBy=multi-user.target

und dann "sudo systemd enable meinstartscript"

Und bei Bedarf kannst du auch noch ein Logging und ein automatischen 
Restart vorsehen,
1
StandardOutput=journal
2
StandardError=journal
3
Restart=always
4
RestartSec=3s
5
# usw....
in die "Service"-Section


https://www.freedesktop.org/software/systemd/man/systemd.unit.html

: Bearbeitet durch User
von Daniel A. (daniel-a)


Lesenswert?

Man kann in der while Bedingung übrigens auch Befehle rein packen, statt 
`[` aka. `test`.
1
while ! curl --connect-timeout 4 ...
2
do
3
...

Wobei, wofür brauchst du überhaupt diese IP, ist ja nur die lokale. 
Webserver kann man einfach an 0.0.0.0 oder :: binden. Und zum zugriff, 
mach sie statisch oder richte dir DHCP + DNS mit DNS Update (machen die 
meisten Router sowieso), ein. Dann kannst du einfach die feste IP oder 
den DNS Namen nehmen.

Da muss man eigentlich auf nichts warten und nichts spezielles machen.

von Michael D. (nospam2000)


Lesenswert?

RasPi schrieb:
> /usr/bin/curl -d "http://$(ip route get 8.8.8.8 | awk -F"src "
> 'NR==1{split($2,a," ");print a[1]}'):5000" ntfy.sh/blabla

Dein quoting bzw. escaping passt nicht, du musst die inneren quotes 
escapen:
 \"src \"
 \" \"

Gesamt dann so:
/usr/bin/curl -d "http://$(ip route get 8.8.8.8 | awk -F\"src \" 
'NR==1{split($2,a,\" \");print a[1]}'):5000" ntfy.sh/blabla

  Michael

: Bearbeitet durch User
von Daniel A. (daniel-a)


Lesenswert?

Michael D. schrieb:
> Dein quoting bzw. escaping passt nicht, du musst die inneren quotes
> escapen:

Das stimmt nicht. Das in dem $() ist von den Quotes darum nicht 
betroffen, würde ja auch keinen Sinn machen. Zur Demonstration:
1
# Hello World
2
echo "$(printf '%s\n' "Hello World")"
3
4
# "Hello
5
# World"
6
echo "$(printf '%s\n' \"Hello World\")"

Wie man sieht, die "" im ersten Fall tun was sie sollen, aber im zweiten 
Fall, wenn man sie zu escapen versucht, passiert genau das, man hat das 
Zeichen " ohne spezielle Bedeutung, und damit effektiv die 2 Argumente 
'"Hello' und 'World"', da das ja nicht mehr in einem "" string drin ist.

von Michael D. (nospam2000)


Lesenswert?

Daniel A. schrieb:
> Das stimmt nicht. Das in dem $() ist von den Quotes darum nicht
> betroffen

Danke, wieder was gelernt!

 Michael

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.