Script will nicht, wie ich

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
nephilim
Beiträge: 39
Registriert: 06.03.2017 18:11:50

Script will nicht, wie ich

Beitrag von nephilim » 06.03.2017 18:16:50

Nabend Gemeinde,

ich tue mich recht schwer mit einem Script und blicke nicht, was ich falsch mache. Ich habe mir das folgende Script geschrieben und es funktioniert auch, wenn ich es manuell laufen lassen.

Script

Code: Alles auswählen

#!/bin/sh
# This script collects basic data and writes them to /etc/pcf/parameter.txt

router=`netstat -r -n | grep "UG" | sed 's/         /:/' | cut -d ":" -f2 | sed 's/ /:/' | cut -d ":" -f1`

echo "# This file will be created while startup procedure\n" > /etc/pcf/parameter.txt

echo "IP_EXT=$(curl http://my.ip.fi)" >> /etc/pcf/parameter.txt
echo "IP_INT=$(ifconfig | grep "inet " | grep -v "127*" | sed 's/^[ \t]*//' | cut -d ":" -f2 | cut -d " " -f1)" >> /etc/pcf/parameter.txt
echo "GATEWAY=$router" >> /etc/pcf/parameter.txt
echo "DNS=$router" >> /etc/pcf/parameter.txt
echo "export {IP_EXT} {IP_INT} {GATEWAY} {DNS}" >> /etc/pcf/parameter.txt

exit 0

Ergebnis (manuell):

Code: Alles auswählen

# This file will be created while startup procedure

IP_EXT=37.***.***.***
IP_INT=192.168.178.30
GATEWAY=192.168.178.1
DNS=192.168.178.1
export {IP_EXT} {IP_INT} {GATEWAY} {DNS}
Sobald ich es aber automatisiert laufen lassen will, ist das Ergebnis dieses:

Code: Alles auswählen

# This file will be created while startup procedure

IP_EXT=
IP_INT=
GATEWAY=
DNS=
export {IP_EXT} {IP_INT} {GATEWAY} {DNS}
Ich habe es versucht als Cronjob

Code: Alles auswählen

@reboot /usr/local/bin/pcf/collect.sh
während des Starts laufen zu lassen und angepasst (skeleton) in /etc/rc5.d. Beides mit dem "Erfolg", wie oben beschrieben, nämlich ohne Werte für meine Variablen.

Was mache ich falsch?

Viele Grüße
//neph
Zuletzt geändert von nephilim am 07.03.2017 19:52:16, insgesamt 1-mal geändert.

rendegast
Beiträge: 15041
Registriert: 27.02.2006 16:50:33
Lizenz eigener Beiträge: MIT Lizenz

Re: Script will nicht, wie ich

Beitrag von rendegast » 06.03.2017 18:23:23

Mal probieren, alle benutzten Programme mit vollem Pfad einzutragen.




echo "# This file will be created while startup procedure\n" > /etc/pcfeecom/parameter.txt
echo "IP_EXT=$(curl http://my.ip.fi)" >> /etc/pcf/parameter.txt
echo "IP_INT=$(ifconfig | grep "inet " | grep -v "127*" | sed 's/^[ \t]*//' | cut -d ":" -f2 | cut -d " " -f1)" >> /etc/pcf/parameter.txt
echo "GATEWAY=$router" >> /etc/pcf/parameter.txt
echo "DNS=$router" >> /etc/pcf/parameter.txt
echo "export {IP_EXT} {IP_INT} {GATEWAY} {DNS}" >> /etc/pcfeecom/parameter.txt
würde ich derart mit einem echo erledigen:

Code: Alles auswählen

echo "# This file will be created while startup procedure

IP_EXT=$(curl http://my.ip.fi)
IP_INT=$(ifconfig | grep "inet " | grep -v "127*" | sed 's/^[ \t]*//' | cut -d ":" -f2 | cut -d " " -f1)
GATEWAY=$router
DNS=$router
export {IP_EXT} {IP_INT} {GATEWAY} {DNS}" > /etc/pcfeecom/parameter.txt
mfg rendegast
-----------------------
Viel Eifer, viel Irrtum; weniger Eifer, weniger Irrtum; kein Eifer, kein Irrtum.
(Lin Yutang "Moment in Peking")

breakthewall
Beiträge: 507
Registriert: 30.12.2016 23:48:51

Re: Script will nicht, wie ich

Beitrag von breakthewall » 06.03.2017 21:52:16

nephilim hat geschrieben:Ich habe es versucht als Cronjob

Code: Alles auswählen

@reboot /usr/local/bin/pcf/collect.sh
während des Starts laufen zu lassen und angepasst (skeleton) in /etc/rc5.d. Beides mit dem "Erfolg", wie oben beschrieben, nämlich ohne Werte für meine Variablen.
Ich denke dein Problem ist hier der Eintrag @reboot in deiner crontab. Denn Cron ist einer der allerersten Dienste die starten, was wirklich sehr früh ist. Und wenn das Shellscript hier schon ausgeführt wird, zu einem Zeitpunkt wo noch gar kein Netzwerk hochgefahren wurde, dann hat das Shellscript auch nichts wovon es Daten sammeln könnte. Da musst das Shellscript schon richtig in die Startreihenfolge einfügen, bspw. via Systemd-Unit, damit es erst startet wenn alle Bedingungen dafür erfüllt sind.

Benutzeravatar
Meillo
Moderator
Beiträge: 8818
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Script will nicht, wie ich

Beitrag von Meillo » 06.03.2017 22:45:15

rendegast hat geschrieben:Mal probieren, alle benutzten Programme mit vollem Pfad einzutragen.
Liegt sicher an ifconfig(8), das ist so ein typischer Kandidat, weil /sbin oft nicht automatisch im Pfad ist.

Alternativ kannst du in deiner interaktiven Shell das ausfuehren:

Code: Alles auswählen

echo $PATH
Und die Ausgabe anstelle der Punkte einfuegen:

Code: Alles auswählen

export PATH="..."
Und die Zeile an den Anfang deines Scriptes setzen. Dann geht's auch mit den relativen Pfaden.
Use ed once in a while!

nephilim
Beiträge: 39
Registriert: 06.03.2017 18:11:50

Re: Script will nicht, wie ich

Beitrag von nephilim » 07.03.2017 06:34:08

Hej zusammen,

schon mal vielen Dank.

Ich möchte nicht mit einem Cronjob arbeiten. Am liebsten wäre mir, wenn ich das Script in /etc/rc5.d laufen lassen könnte.

Ich habe jetzt folgendes probiert:

Code: Alles auswählen

#!/bin/sh
# kFreeBSD do not accept scripts as interpreters, using #!/bin/sh and
sourcing.
if [ true != "$INIT_D_SCRIPT_SOURCED" ] ; then
    set "$0" "$@"; INIT_D_SCRIPT_SOURCED=true . /lib/init/init-d-script
fi

### BEGIN INIT INFO
# Provides:          skeleton
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Example initscript
# Description:       This file should be used to construct scripts to be
#                    placed in /etc/init.d.  This example start a
#                    single forking daemon capable of writing a pid
#                    file.  To get other behavoirs, implemend
#                    do_start(), do_stop() or other functions to
#                    override the defaults in /lib/init/init-d-script.
### END INIT INFO

# Author: pc-f <info@**.com>
#
# Please remove the "Author" lines above and replace them
# with your own name if you copy and modify this script.

export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games"

router=`netstat -r -n | grep "UG" | sed 's/         /:/'| cut -d ":" -f2 | sed 's/ /:/' | cut -d ":" -f1`

echo "# This file will be created while startup procedure\n" > /etc/pcf/parameter.txt
echo "IP_EXT=$(curl http://my.ip.fi)" >> etc/pcf/parameter.txt
echo "IP_INT=$(ifconfig | grep "inet " | grep -v "127*" | sed 's/^[ \t]*//' | cut -d ":" -f2 | cut -d " " -f1)" >>etc/pcf/parameter.txt
echo "GATEWAY=$router" >> etc/pcf/parameter.txt
echo "DNS=$router" >> etc/pcf/parameter.txt
echo "export {IP_EXT} {IP_INT} {GATEWAY} {DNS}" >> /etc/pcf/parameter.txt

exit 0
und das:

Code: Alles auswählen

#!/bin/sh
# kFreeBSD do not accept scripts as interpreters, using #!/bin/sh and
sourcing.
if [ true != "$INIT_D_SCRIPT_SOURCED" ] ; then
    set "$0" "$@"; INIT_D_SCRIPT_SOURCED=true . /lib/init/init-d-script
fi

### BEGIN INIT INFO
# Provides:          skeleton
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Example initscript
# Description:       This file should be used to construct scripts to be
#                    placed in /etc/init.d.  This example start a
#                    single forking daemon capable of writing a pid
#                    file.  To get other behavoirs, implemend
#                    do_start(), do_stop() or other functions to
#                    override the defaults in /lib/init/init-d-script.
### END INIT INFO

# Author: pc-f <info@**.com>
#
# Please remove the "Author" lines above and replace them
# with your own name if you copy and modify this script.

router=`/bin/netstat -r -n | /bin/grep "UG" | /bin/sed 's/         /:/'| /usr/bin/cut -d ":" -f2 | /bin/sed 's/ /:/' | /usr/bin/cut -d ":" -f1`

echo "# This file will be created while startup procedure\n" > /etc/pcf/parameter.txt

echo "IP_EXT=$(/usr/bin/curl http://my.ip.fi)" >> etc/pcf/parameter.txt
echo "IP_INT=$(/sbin/ifconfig | /bin/grep "inet " | /bin/grep -v "127*" | /bin/sed 's/^[ \t]*//' | /usr/bin/cut -d ":" -f2 | /usr/bin/cut -d " " -f1)" >>etc/pcf/parameter.txt
echo "GATEWAY=$router" >> etc/pcf/parameter.txt
echo "DNS=$router" >> etc/pcf/parameter.txt
echo "export {IP_EXT} {IP_INT} {GATEWAY} {DNS}" >> /etc/pcf/parameter.txt

exit 0
Das Ergebnis bleibt leider gleich, eine Datei mit Variablen, aber ohne Werte.

Was kann ich noch versuchen?

LG // neph
Zuletzt geändert von nephilim am 07.03.2017 19:51:42, insgesamt 1-mal geändert.

Benutzeravatar
detix
Beiträge: 1705
Registriert: 07.02.2007 18:51:28
Wohnort: MK

Re: Script will nicht, wie ich

Beitrag von detix » 07.03.2017 10:30:25

Schau zuerst mal hier [1] rein
zum Skript:
Deine „if” -Abfrage scheint immer true zu sein, womit das „set...” (wofür soll das eigentlich gut sein?) auch immer ausgeführt wird.
Den Header würde ich mal so schreiben:

Code: Alles auswählen

### BEGIN INIT INFO
# Provides:          collect
# Required-Start:    $all
# Required-Stop:     $all
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# ...
kleine Anmerkung noch: die Runlevels 2345 sind bei debian identisch.

Die Variable „router” kann man doch bestimmt einfacher zuweisen:

Code: Alles auswählen

router=$(/bin/netstat -r -n | awk '/UG/ {print $2}')
Dann sollte dein Skript in /etc/init.d/ als collect.sh gespeichert werden,
um es anschließend mit „insserv -v collect.sh” (als root) automatisch richtig einzusortieren.
Dieses:

Code: Alles auswählen

echo "IP_INT=$(ifconfig | grep "inet " | grep -v "127*" | sed 's/^[ \t]*//' | cut -d ":" -f2 | cut -d " " -f1)" >>etc/pcf/parameter.txt
ist auch recht merkwürdig, was ist bei 2 Netzwerkkarten?
GATEWAY=$router, DNS=$router ist doch dasselbe!
[1] https://wiki.debian.org/LSBInitScripts
Gruß an alle Debianer, und immer daran denken:
Macht ohne Haftung funktioniert nicht!

nephilim
Beiträge: 39
Registriert: 06.03.2017 18:11:50

Re: Script will nicht, wie ich

Beitrag von nephilim » 07.03.2017 19:50:42

Hej detix

vielen Dank erst einmal. Also mein Script sieht jetzt so aus:

Code: Alles auswählen

#!/bin/sh

### BEGIN INIT INFO
# Provides:          collect
# Required-Start:    $all
# Required-Stop:     $all
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Example initscript
# Description:       This file should be used to construct scripts to be
#                    placed in /etc/init.d.  This example start a
#                    single forking daemon capable of writing a pid
#                    file.  To get other behavoirs, implemend
#                    do_start(), do_stop() or other functions to
#                    override the defaults in /lib/init/init-d-script.
### END INIT INFO

# Author: pc-f <info@***.com>
#
# Please remove the "Author" lines above and replace them
# with your own name if you copy and modify this script.

router=$(/bin/netstat -r -n | awk '/UG/ {print $2}')

echo "# This file will be created while startup procedure\n" > /etc/pcf/parameter.txt
echo "IP_EXT=$(/usr/bin/curl http://my.ip.fi)" >> etc/pcf/parameter.txt
echo "IP_INT=$(/sbin/ifconfig | /bin/grep "inet " | /bin/grep -v "127*" | /bin/sed 's/^[ \t]*//' | /usr/bin/cut -d ":" -f2 | /usr/bin/cut -d " " -f1)" >>etc/pcf/parameter.txt
echo "DNS=$router" >> etc/pcf/parameter.txt
echo "export {IP_EXT} {IP_INT} {GATEWAY} {DNS}" >> /etc/pcf/parameter.txt

exit 0
Leider keine Änderung. Ergebnis:

Code: Alles auswählen

# This file will be created while startup procedure

IP_EXT=
IP_INT=
DNS=
export {IP_EXT} {IP_INT} {GATEWAY} {DNS}
Deine „if” -Abfrage scheint immer true zu sein, womit das „set...” (wofür soll das eigentlich gut sein?) auch immer ausgeführt wird.
Weiß ich nicht. Mir wurde gesagt, halte Dich an "skeleton", wenn es an Init-Scripte geht und habe das schlicht drin gelassen. Bin Anfänger damit.
Dann sollte dein Skript in /etc/init.d/ als collect.sh gespeichert werden,
um es anschließend mit „insserv -v collect.sh” (als root) automatisch richtig einzusortieren.
Genauso gemacht.
router=$(/bin/netstat -r -n | awk '/UG/ {print $2}')
Umgesetzt.

Code: Alles auswählen

 echo "IP_INT=$(ifconfig | grep "inet " | grep -v "127*" | sed 's/^[ \t]*//' | cut -d ":" -f2 | cut -d " " -f1)" >>etc/pcf/parameter.txt 
ist auch recht merkwürdig, was ist bei 2 Netzwerkkarten?
Diese Geräte werden immer nur eine Karte haben. Darauf ist Verlass.

Ich blicke nicht, was ich falsch mache.

LG // Neph

TomL

Re: Script will nicht, wie ich

Beitrag von TomL » 07.03.2017 21:02:16

nephilim hat geschrieben:....und angepasst (skeleton) in /etc/rc5.d. Beides mit dem "Erfolg", wie oben beschrieben, nämlich ohne Werte für meine Variablen.
Was mache ich falsch?
Das ist ganz einfach... Du versuchst ein Problem zu lösen mit "Lösungsansätzen von vorgestern". Runlevels sind quasi jetzt schon tot, und werden nur noch zwangsbeatmet am Leben gehalten. Um das zu verdeutlichen habe ich mal eben ein kurzes TestScript geschrieben und aktiviert.

Code: Alles auswählen

ne /etc/init.d/teststarttime
update-rc.d teststarttime defaults

Code: Alles auswählen

#!/bin/sh
### BEGIN INIT INFO
# Provides:          collect
# Required-Start:    $all
# Required-Stop:     $all
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Example initscript
# Description:       Demo
### END INIT INFO

echo "active/running   Action=$1" | systemd-cat -t "thlu:`basename $0`" -p "info"

# Aktionen
case "$1" in
    start)
        exit 0
        ;;
    stop)
        exit 0
        ;;
    restart)
        exit 0
        ;;
esac

exit 1
Es wird tadellos ausgeführt:

Code: Alles auswählen

# journalctl -b | grep teststarttime
Mär 07 20:35:18 thomaspc thlu:teststarttime[1995]: active/running   Action=start

# systemctl status teststarttime
● teststarttime.service - LSB: Example initscript
   Loaded: loaded (/etc/init.d/teststarttime; generated; vendor preset: enabled)
   Active: active (exited) since Tue 2017-03-07 20:35:18 CET; 15min ago
     Docs: man:systemd-sysv-generator(8)
  Process: 1990 ExecStart=/etc/init.d/teststarttime start (code=exited, status=0/SUCCESS)
    Tasks: 0 (limit: 4915)
   CGroup: /system.slice/teststarttime.service

Mär 07 20:35:18 thomaspc systemd[1]: Starting LSB: Example initscript...
Mär 07 20:35:18 thomaspc systemd[1]: Started LSB: Example initscript.
Und nun kann man sich mal anschauen, wann es gestartet wird:

Code: Alles auswählen

systemd-analyze plot >~/bootplot.svg
Und man erkennt, dass es bereits VOR network.target ausgeführt wird und noch mal weitere 4 Sekunden später ist das Netzwerk erst erfolgreich verbunden und eine IP vergeben.

520

Der Lösungsansatz ist imho verkehrt. Richtig wäre es, das Script über eine systemd-service-unit nach erfolgreicher Netzwerkverbindung zu starten.

Benutzeravatar
detix
Beiträge: 1705
Registriert: 07.02.2007 18:51:28
Wohnort: MK

Re: Script will nicht, wie ich

Beitrag von detix » 07.03.2017 21:15:15

Bitte um eine Lösung mit systemd Thomas,
sonst wäre mein Vorschlag eine kleine while -Schleife um netstat herum zu schreiben.
Noch sind die Skripte in /etc/init.d/ keine Vergangenheit, auch nicht bei stretch.
Gruß an alle Debianer, und immer daran denken:
Macht ohne Haftung funktioniert nicht!

TomL

Re: Script will nicht, wie ich

Beitrag von TomL » 07.03.2017 21:26:44

Code: Alles auswählen

ne /etc/systemd/system/network_wait_online.service
systemctl enable network_wait_online.service

Code: Alles auswählen

[Unit]
Description=thlu:network_wait_online.service:   Waiting for Network or Server to be up
After=network.target

[Service]
Type=oneshot
TimeoutStartSec=95
ExecStart=/usr/local/bin/network_wait_online 10.10.1.2

[Install]
WantedBy=multi-user.target

Code: Alles auswählen

ne /usr/local/bin/network_wait_online

Code: Alles auswählen

#!/bin/bash
#==============================================================================================
# Script-Name :  network_wait_online
# Author      :  TommyLu*gmx.de
# Date        :  27.01.2017
# Version     :  5.0
# Lizenz      :  GNU/GPL
#==============================================================================================

[ -z "$1" ] && Server="8.8.8.8" || Server=$1
echo "active/running   Server=$Server" | systemd-cat -t "thlu:`basename $0`" -p "info"

timeout=85
Diff=0
HomeNetIsConnect=-1

Start=$(date +%s);

while [ true ]; do
    /bin/ping -c1 -W1 -q $Server &>/dev/null
    HomeNetIsConnect=$?

    [ $HomeNetIsConnect -eq 0 ] && break
    /bin/sleep 0.5
    
    End=$(date +%s);
    Diff=$((End-Start)) 
    [[ Diff -gt timeout ]] && break
done

rc=0
if [[ $HomeNetIsConnect -eq 0 ]]; then
    echo "Host $Server is reachable! (RC:$HomeNetIsConnect, after $Diff Seconds wait)" | systemd-cat -t "thlu:`basename $0`" -p "info"
else
    echo "Host $Server is not reachable! (RC:$HomeNetIsConnect, after $Diff Seconds wait)" | systemd-cat -t "thlu:`basename $0`" -p "err"
    rc=1
fi

echo "Successful terminated with exitcode=$rc" | systemd-cat -t "thlu:`basename $0`" -p "info"
exit $rc
Hier wird der Start des eigentlichen Scriptes veranlasst, und zwar definitiv erst dann, wenn das Netzwerk erfolgreich verbunden wurde. Der Vorteil dieser Vorgehensweise ist, dass das auch zuverlässig bei einem PI3 mit langsamer WLAN-Verbindung funktioniert. Ein weiterer Vorteil ist, dass es ein pauschale Lösung ist, die beliebig auch für andere vom Netz abhängige Probleme (Units) genutzt werden kann. Lediglich das kurze Statement after und requires network_wait_online.service in beliebigen Service-Units garantiert das.

Code: Alles auswählen

ne /etc/systemd/system/irgendeinname.service
systemctl enable irgendeinname.servic

Code: Alles auswählen

[Unit]
Description=thlu:irgendeinname.service:   Macht was ich will und was es soll
After=network_wait_online.service
Requires=network_wait_online.service

[Service]
RemainAfterExit=yes
Type=idle
ExecStart=/usr/local/bin/irgendeinname start
ExecStop=/usr/local/bin/irgendeinname stop
ExecReload=/usr/local/bin/irgendeinname start

[Install]
WantedBy=multi-user.target
Das ist aber weissgott nicht der richtige Weg, vorgekautes nur zu schlucken..... :roll:
Zuletzt geändert von TomL am 09.03.2017 20:28:35, insgesamt 1-mal geändert.

TomL

Re: Script will nicht, wie ich

Beitrag von TomL » 07.03.2017 21:43:49

detix hat geschrieben:Noch sind die Skripte in /etc/init.d/ keine Vergangenheit, auch nicht bei stretch.
Ich orientiere mich bei meiner Aussage so ein bisschen an RedHat, die ja fast alleine Urheber der maßgeblichen Innovationen in den letzten Jahren im Linux-Universum (auch bei Debian) sind, die in Fedora keine Init.d-Scripte mehr verwenden und stattdessen sagen:

Zitat:
You are looking for the traditional init scripts in /etc/rc.d/init.d, and they are gone?

Here's an explanation on what's going on:
You are running a systemd-based OS where traditional init scripts have
been replaced by native systemd services files. Service files provide
very similar functionality to init scripts. To make use of service
files simply invoke "systemctl", which will output a list of all
currently running services (and other units). Use "systemctl
list-unit-files" to get a listing of all known unit files, including
stopped, disabled and masked ones. Use "systemctl start
foobar.service" and "systemctl stop foobar.service" to start or stop a
service, respectively. For further details, please refer to systemctl(1)."


Ich bin davon überzeugt, dass es in der Debian-Version nach Stretch keine Init.d-Scripte mehr gibt.... was ich persönlich richtig gut finde. Warum also heute noch darauf setzen?

Benutzeravatar
detix
Beiträge: 1705
Registriert: 07.02.2007 18:51:28
Wohnort: MK

Re: Script will nicht, wie ich

Beitrag von detix » 07.03.2017 21:53:04

Naja, definitiv hab ich noch mindestens 2 Jahre Ruhe bevor ich mich mit so einem kryptischen Zeugs befassen muss.
Da lob ich mir doch die alten einfachen init Skripte, dennoch vielen Dank Thomas,
mal sehn was nephilim dazu schreibt...
Gruß an alle Debianer, und immer daran denken:
Macht ohne Haftung funktioniert nicht!

TomL

Re: Script will nicht, wie ich

Beitrag von TomL » 07.03.2017 22:52:00

detix hat geschrieben:Naja, definitiv hab ich noch mindestens 2 Jahre Ruhe bevor ich mich mit so einem kryptischen Zeugs befassen muss.
Es ist eher genau das Gegenteil von "kryptisch". Statt haufenweise Runlevel-Links zu generieren um ein Start-Script zu starten, welches dann das eigentliche Binary bzw. den Job startet, ist NUR noch eine einzige kleine Service-Unit notwendig, um den Job direkt zu starten. Das ich hier 2 Lösungen präsentiere ist dem Umstand geschuldet, auf die Besonderheiten des Netzwerks zu achten. Aber das erschlägt dann auch sofort noch z.B. Remote-Mounts oder beliebige andere Netzwerk-Interaktionen, die nach dem Systemstart ebenfalls alle auf ein etabliertes Netzwerk warten müssen.

Und mal ganz am Rande nebenbei bemerkt... die runlevel-Links sind m.E. jetzt schon tot, weil systemd jetzt schon service-units generiert. Das heisst, die kommen sowieso nicht mehr zur Ausführung und dienen nur noch dem Auto-Gen als Grundlage für die generierte Unit. Und vor dem Hintergrund mache ich das doch lieber von vornherein selber und habe dann die Kontrolle darüber direkt in eigener Hand.

nephilim
Beiträge: 39
Registriert: 06.03.2017 18:11:50

Re: Script will nicht, wie ich

Beitrag von nephilim » 08.03.2017 19:24:21

Nabend zusammen,

vielen Dank für diese neue Richtung. :-)

Ich bin noch nicht lange dabei und fuchse mich in Linux erst ein. Ich bin schon ein alter Sack und mir fällt neues zu lernen reichlich schwer. Daher werde ich mich an dem Vorschlag von Thomas versuchen. Wenn das eh das nächste ist was kommt, lerne ich lieber gleich das.

Ich versuche mal zusammenzufassen, was ich glaube bisher verstanden zu haben: Mein Script läuft, aber bereits zu einer Zeit, wo die Funktionen noch nicht verarbeitet werden können, weil die Grundlagen dafür noch nicht gegeben sind, sprich das Netzwerk noch nicht etabliert ist. systemd schafft Abhilfe, weil ich hier bspw. warten kann, bis das Netzwerk komplett etabliert ist (After=network.target) und erst dann mein Script angestoßen wird. Ist das soweit richtig?

Nun zu ganz praktischen Fragen.

Code: Alles auswählen

ne /etc/systemd/system/network_wait_online.service
Was bedeutet das ne? Meine Konsole meckert das an (bash: ne: command not found).

Code: Alles auswählen

ExecStart=/usr/local/bin/network_wait_online 10.10.1.2
Ist das eine IP am Ende und ist die zwingend oder läuft das Script in /usr/local/bin auch ohne diese?

@Thomas: Darf ich mich, wenn ich mich daran versuche, per PN an Dich wenden, um ggf weitere Fragen zu stellen?

Vielen Dank schon mal an alle...

LG // neph

TomL

Re: Script will nicht, wie ich

Beitrag von TomL » 08.03.2017 20:03:16

nephilim hat geschrieben:Ich bin schon ein alter Sack und mir fällt neues zu lernen reichlich schwer. Daher werde ich mich an dem Vorschlag von Thomas versuchen. Wenn das eh das nächste ist was kommt, lerne ich lieber gleich das.
Nun ja... der Anteil an alten Säcken hier im Forum ist m.E. vergleichsweise hoch :lol: also, Du bist nicht allein. Und es ist nicht das nächste, was kommt, sondern das, was bereits mit Jessie vor 2 Jahren eingeführt wurde.
nephilim hat geschrieben:Ich versuche mal zusammenzufassen, was ich glaube bisher verstanden zu haben: Mein Script läuft, aber bereits zu einer Zeit, wo die Funktionen noch nicht verarbeitet werden können, weil die Grundlagen dafür noch nicht gegeben sind, sprich das Netzwerk noch nicht etabliert ist.
Richtig!
nephilim hat geschrieben:systemd schafft Abhilfe, weil ich hier bspw. warten kann, bis das Netzwerk komplett etabliert ist (After=network.target) und erst dann mein Script angestoßen wird. Ist das soweit richtig?
Ja, richtig. systemd ist aufgrund möglichst paralleler Starts von Diensten und Jobs einerseits für Dein Problem verantwortlich, aber es bietet auch Mechanismen, diese Probleme zu lösen.
nephilim hat geschrieben:Was bedeutet das ne? Meine Konsole meckert das an (bash: ne: command not found).
Debianne ist ein wunderbarer kleiner Editor, den ich begeistert nutze und der den bei mir seit langer Zeit ungeliebten "nano" abgelöst hat. Du kannst die Dateien allerdings mit jedem beliebigen Editor erstellen, nur nicht gerade mit Winword, LO-Writer oder einem anderen Editor, der nicht pure Textfiles erzeugt. Standardmäßig ist auf Deinem Rechner vermutlich "nano" installiert.
nephilim hat geschrieben:

Code: Alles auswählen

ExecStart=/usr/local/bin/network_wait_online 10.10.1.2
Ist das eine IP am Ende und ist die zwingend oder läuft das Script in /usr/local/bin auch ohne diese?
Ja, das ist die IP meines Servers. Du musst da natürlich die passende IP Deines Netzwerkes einsetzen, z.B. Router, Server, NAS... eben worauf Du wartest. Oder Du lässt es leer, dann wartet das Script auf Erreichbarkeit der IP 8.8.8.8, um festzustellen, ob der Zugriff aufs Internet möglich ist.
nephilim hat geschrieben:Darf ich mich, wenn ich mich daran versuche, per PN an Dich wenden, um ggf weitere Fragen zu stellen?
Nein! Debian und dieses Forum leben auch von der Unterstützung bei Problemen, die einige erfahrene Stammuser bereit sind zu geben, wenn neu-beginnende User eben solche für sie unlösbare Probleme haben. Und niemand sonst, außer Dir, hat etwas von "geheimen" Antworten per PN zu einem öffentlichen Thema. Wenn ich hier im Forum etwas beantworte, kann es sein, dass jemand anderes, der diesen Thread hier später liest, diese Frage gar nicht mehr stellen muss, weil passend zum Thema gleich Frage und Antwort zusammen zu finden sind. Und außerdem (das ist das wichtigste), wenn ich per PN Blödsinn erzähle, bleibt das eine "dumme Wahrheit", weil niemand der es besser weiss, mich korrigieren konnte. Also, frag lieber hier, irgend jemand wird antworten.

nephilim
Beiträge: 39
Registriert: 06.03.2017 18:11:50

Re: Script will nicht, wie ich

Beitrag von nephilim » 09.03.2017 06:24:20

Danke Thomas, das verstehe ich.

OK, hier ist, was ich getan habe, um das Vorgeschlagene zu testen.

Ein ganz frisches Debian 8 auf die Karte gezogen, den RPi3 bestückt und update & upgrade gemacht. Dann habe ich die Datei /usr/local/bin/pcf/collect.sh erstellt, mit folgendem Inhalt gefüllt und für ugo ausführbar gemacht:

Code: Alles auswählen

#!/bin/sh
# This script collects basic data and writes them to /etc/pcf/parameter.txt

router=$(netstat -r -n | awk '/UG/ {print $2}')

echo "# This file will be created while startup procedure\n" > /etc/pcf/parameter.txt

echo "IP_EXT=$(curl http://my.ip.fi)" >> /etc/pcf/parameter.txt
echo "IP_INT=$(ifconfig | grep "inet " | grep -v "127*" | sed 's/^[ \t]*//' | cut -d ":" -f2 | cut -d " " -f1)" >> /etc/pcf/parameter.txt
echo "DNS=$router" >> /etc/pcf/parameter.txt
echo "export {IP_EXT} {IP_INT} {DNS}" >> /etc/pcf/parameter.txt

exit 0
Nun habe ich meine Service-Unit erstellt und aktiviert:

Code: Alles auswählen

pi@raspberrypi:~ $ sudo nano /etc/systemd/system/collect.service
pi@raspberrypi:~ $ sudo systemctl enable /etc/systemd/system/collect.service
Created symlink from /etc/systemd/system/multi-user.target.wants/collect.service to /etc/systemd/system/collect.service.
pi@raspberrypi:~ $ sudo systemctl is-enabled collect.service
enabled
pi@raspberrypi:~ $
Und das ist der Inhalt von collect.service:

Code: Alles auswählen

[Unit]
Description=neph:collect.service:   Collects data once the network is up and running
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
TimeoutStartSec=95
ExecStart=/usr/local/bin/pcf/collect.sh

[Install]
WantedBy=multi-user.target
Ich verwende After=network-online.target & Wants=network-online.target weil ich das hier gelesen habe:
Alternatively, you can change your service that needs the network to be up, to include After=network-online.target and Wants=network-online.target.
Hier mein Ergebnis in /etc/pcf/parameter.txt:

Code: Alles auswählen

# This file will be created while startup procedure

IP_EXT=
IP_INT=
DNS=
export {IP_EXT} {IP_INT} {DNS}
Die Werte fehlen immer noch. Woran kann das liegen? Habe ich was wesentliches vergessen?

LG // neph

TomL

Re: Script will nicht, wie ich

Beitrag von TomL » 09.03.2017 10:27:53

nephilim hat geschrieben:Ich verwende After=network-online.target & Wants=network-online.target weil ich das hier gelesen habe:
:D Das finde ich ja mal richtig klasse. Jemand, der eine vorherige Antwort dergestalt weiterverwendet, um sich darüber weitergehend zu informieren, sich eigene Gedanken macht, selber aufgrund von Anregungen recheriert und versucht auf Verstehen basierend konstruktiv zu eigenen Lösungen zu kommen :THX:

Aber leider gerätst Du hier in eine Falle, die Du als Newbie unmöglich selber erkennen kannst. Zunächst mal liegt hier eine Verwechselung vor. Dein Link beschreibt die besondere Service-Unit 'systemd-networkd-wait-online.service'. Diese Unit funktioniert nach meinem Kenntnisstand aber nur, wenn Du das Netzwerk über 'systemd-networkd & systemd-resolved' startest und handhabst. Das ist aber bei einer frischen Debian-Installation so nicht gegeben. Stattdessen wird das Netzwerk traditionell über '/etc/init.d/networking' & '/etc/network/interfaces' & diverse runlevel-Links gestartet. Faktisch bedeutet das, dass diese Units vor diesem Hintergrund eben nicht funktionieren.

Der zweite Irrtum bezieht sich auf das, was Du tatsächlich in die Unit eingetragen hast, und zwar "After=network-online.target & Wants=network-online.target". Diese Einträge funktionieren zwar auch in dem traditionellen sysvinit-Modus, aber sie tun nicht das, was sie vom Namen vorgeben zu tun und auch nicht das, was Du erwartest.
Die Unit 'network-online.target' ist eine aktive Unit, die weitere Service-Starts verzögert, bis das Netzwerk ausreichend etabliert ist. Die Besonderheit liegt hier beim Begriff "ausreichend".... was bedeutet das? Nun, ganz einfach, es bedeutet keine abschließend gültige Zustandsdefinition, sondern nur das, was für bestimmte Aufgaben als ausreichend definiert wird. Es gibt also verschiedene Zustände von "ausreichend", je nach point of view.
Ausreichend für
- die Treiber ist, wenn der Kernel die Hardware erkannt hat
- die Netzwerkprotokolle ist, wenn der Treiber funktionsfähig ist und ein Networkmanager gestartet werden könnte
- den Networkmanager ist, wenn die NICs geöffnet werden können
- den DHCP-Client ist, wenn der Network-Manager die NICs geöffnet hat und nun eine IP bezogen werden kann
- für den User ist, wenn das Netz (Gateway ->Server und Internet) erreichbar ist

Also, die Aussagekraft von "network-online.target" ist abhängig von dem, der dieses Target anzieht.... und das entscheidet der selber. Das könnte also bedeuten:
- Der Start Networkmanager ist veranlasst (Service-Manager)
- Der Start Networkmanager war erfolgreich (Fork exited = 0) (Service-Manager)
- Der Networkmanager wurde erfolgreich gestartet und ist bereit (NWM)
- Das Netzwerk-Interface wurde erfogreich geöffnet (NWM)
- eine DHCP-Adresse wurde angefordert (DHCP)
- eine IP-Adresse ist vergeben (DHCP)
- eine IP-Adresse ist vergeben (NWM)

Darüber hinaus
- beliebige eigene Services können dieses Target nach eigenem Ermessen zu jeder Zeit anziehen

Insofern ist das für Deine Zwecke unbrauchbar. So, und an der Stelle kann man nur hoffen, dass jemand eingreift, wenn ich hier falsches oder unvollständiges erzählt habe. :roll: Wenn Du das genauer wissen möchtest, such einfach mal nach "tcp/ip-referenzmodell". Da siehst Du die Ebenen, die ggf. als "ausreichend" jeweils für den Nachfolger denkbar wären. Wobei das natürlich für unsere Probleme jetzt so auch nicht ganz der Wahrheit entspricht, für uns greifen eher die "späteren" Ebenen, aber egal... was bleibt ist, der Zustand dieses Targets ist nicht vernünftig verwertbar. Und noch weniger auf einem PI, weil es gerade mit dem PI3 auch die Möglichkeit eines eher sehr langsamen Verbindungsaufbaus via internem WLAN-NIC gibt.

PS
Ich denke, diese Antwort macht deutlich, warum man Frage & Antwort nicht per PN abhandeln sollte.
Zuletzt geändert von TomL am 09.03.2017 14:20:15, insgesamt 3-mal geändert.

nephilim
Beiträge: 39
Registriert: 06.03.2017 18:11:50

Re: Script will nicht, wie ich

Beitrag von nephilim » 09.03.2017 10:59:26

Wow, dass nenne ich umfassend. Danke dafür. :)

Ich bin jetzt unsicher. Bedeutet das, ich kann das, was ich vorhabe vergessen, weil nicht realisierbar? Ich weiß das gerade nicht einzuschätzen.

WLAN kann ich vernachlässigen. Der Einsatz später ist nur per LAN definiert. Ich brauche nur eth0.

Wie kann ich denn trotz der Umstände realisieren, was ich da brauche?

LG // neph

TomL

Re: Script will nicht, wie ich

Beitrag von TomL » 09.03.2017 11:04:32

nephilim hat geschrieben:Ich bin jetzt unsicher. Bedeutet das, ich kann das, was ich vorhabe vergessen, weil nicht realisierbar? Ich weiß das gerade nicht einzuschätzen.
Doch, das ist natürlich realisierbar. Die Lösung hatte ich ja schon weiter oben skizziert.... ein explizites Delay, welches auf die definitive Erreichbarkeit einer bestimmten Netzwerkressource wartet, ohne den Boot oder das System oder den Start anderer Services an sich zu blockieren.

Und dann in die Unit collect.service statt after&wants die Einträge übernehmen, wie ich sie oben vorgeschlagen habe, und zwar Warten auf die zweite Unit fürs "Warten aufs Netzwerk". Das wird auf Anhieb funktionieren. Ich würde das auch getrennt/nacheinander umsetzen, insbesondere dabei auch die Log-Einträge durchführen, damit du das jeweils auf Erfolg kontrollieren kannst. Es bringt nix, Dein Scrip zu starten, solange nicht im Log durch diese Wait-Unit drinsteht, dass sie erfolgreich auf das Netzwerk gewartet hat. Und wenn Dein Script danach gestartet wird, muss es erfolgreich sein - sofern keine Fehler drin sind.

nephilim
Beiträge: 39
Registriert: 06.03.2017 18:11:50

Re: Script will nicht, wie ich

Beitrag von nephilim » 09.03.2017 19:52:51

Hoho, ich war so blöd. Ich habe allen Ernstes Deinen Vorschlag oben nicht als funktionierende Lösung wahrgenommen. Hat bissl gedauert, bis es klick gemacht hat.

Dank Deiner Hilfe Thomas, funktioniert es jetzt. :D

Vielen herzlichen Dank für eine richtig angenehme Forum-Erfahrung. Ich habe viel dazugelernt.

LG // neph

nephilim
Beiträge: 39
Registriert: 06.03.2017 18:11:50

Re: Script will nicht, wie ich

Beitrag von nephilim » 11.03.2017 11:57:45

Dieser Eintrag ist optional, aber die Lösung, für die ich mich jetzt entschieden habe. Daher möchte ich sie nachreichen.

Ich habe die Netzwerkverwaltung auf systemd-networkd umgestellt.

Dann habe ich die folgende Service-Unit erstellt. Sie sorgt dafür, dass gewartet wird, bis alle das Netzwerk etabliert wurde und startet dann mein Script; in diesem Beispiel collect.sh.

Service-Unit /etc/systemd/system/<name_deiner_wahl>.service (bei mir: collect.service):

Code: Alles auswählen

[Unit]
Description=neph:collect.service:   Collects data once the network is up and running
After=network.target

[Service]
RemainAfterExit=yes
Type=idle
ExecStart=/usr/local/bin/pcf/collect.sh

[Install]
WantedBy=multi-user.target
Damit After=network.target bei mir funktioniert, musste in meinem Setup noch der folgende "Verzögerungs"-Service aktiviert werden:

Code: Alles auswählen

systemctl enable systemd-networkd-wait-online.service
Hier geht es zur Quelle zum Nachlesen.

Nochmal danke an alle Mitwirkenden..

LG // neph

TomL

Re: Script will nicht, wie ich

Beitrag von TomL » 11.03.2017 14:20:27

nephilim hat geschrieben:Damit After=network.target bei mir funktioniert, musste in meinem Setup noch der folgende "Verzögerungs"-Service aktiviert werden:

Code: Alles auswählen

systemctl enable systemd-networkd-wait-online.service
Hier geht es zur Quelle zum Nachlesen.
Das funktioniert mit Einschränkungen richtig prima. Ich habe das früher auch verwendet. Allerdings zeigt es Dir nur an, dass das Netzwerk verbunden ist und Du eine gültige IP in diesem Netzwerk hast. Leider ist aber keine Information darüber enthalten, ob beispielsweise eine bestimmte Ressource in diesem Netzwerk erreichbar ist oder ob z.B. das Internet erreichbar ist.

Eine bestimmte Ressource könnte ein Fileserver im LAN sein, der sich vielleicht verabschiedet hat. Wenn auf dem Client jedoch bestimmte Jobs genau diesen Fileserver brauchen, für simple Remote-Mounts zu Samba- oder NFS-Shares, für Backups, Homedirs, egal was, reicht leider systemd-networkd-wait-online.service nicht, um die Verfügbarkeit dieses Servers zu gewährlisten. Ebenso kann zwar das LAN laufen, aber der Zugriff aufs WAN ist weg, weil der ISP gerade Schluckauf hat oder ein Bagger die Leitung gekappt hat. Auch das handhabt der Service nicht. Das bedeutet, man muss für bestimmte Jobs zusätzlich ein Fallback-Szenario entwerfen, weil sie ja trotzdem gestartet werden. Deswegen habe ich das wieder ausgeplant und starte bestimmte Jobs nur, wenn auch die gewünschte Ressource verfügbar ist. Genau diese Schwäche sollte meine network_wait_online.service-Alternative beheben. Und ich wollte natürlich keine 2 Delays, das ist natürlich auch Quatsch.

Man muss einfach abwägen, ob es für die eigenen Aufgaben reicht oder nicht oder welche Version für die eigenen Vorhaben besser geeignet ist.

breakthewall
Beiträge: 507
Registriert: 30.12.2016 23:48:51

Re: Script will nicht, wie ich

Beitrag von breakthewall » 13.03.2017 00:54:32

nephilim hat geschrieben:

Code: Alles auswählen

#! /bin/sh
# This script collects basic data and writes them to /etc/pcf/parameter.txt

LOG="/etc/pcf/parameter.txt"

COLLECT() {
echo "IP_EXT=$(ip route | awk '/src / {print $9}')"
echo "IP_INT=$(ip route | tail -1 | awk '{print $1}')"
echo "DNS=$(awk '{print $2}' /etc/resolv.conf | sed '2q;d')"
echo "GATEWAY=$(ip route | awk '/default/ {print $3}')"
export DNS IP_EXT IP_INT GATEWAY
}

COLLECT > "$LOG"

exit 0
Ich habe dein Shellscript mal etwas effizienter gestaltet und fehlerbereinigt. Zum einen hast recht umständliche Wege genutzt um jene Datensätze zu sammeln. Zum anderen ist es unvorteilhaft vielfache Umleitungen auf eine Datei laufen zu lassen, wenn man das wie hier als Funktion, oder via Kommandogruppierung { command; command; } > File, auf einmal zusammenfassen kann. Deine export Zeile im Shellscript war auch nicht korrekt und gewissermaßen wirkungslos, sodass hier ausschließlich echo nur die Variablennamen samt Curly-Brackets ausgegeben hat, ohne das überhaupt irgendetwas exportiert wurde. Wenn man etwas exportiert, dann will man ja letztlich Daten weiterverarbeiten, und wenn offenbar nicht auffällt, dass das gar nicht funktioniert, dann wirkt der Export an sich wieder überflüssig.

nephilim
Beiträge: 39
Registriert: 06.03.2017 18:11:50

Re: Script will nicht, wie ich

Beitrag von nephilim » 13.03.2017 10:55:23

Jetzt bin ich total durcheinander. Vorgestern habe ich ja noch hier die Option beschrieben, für die ich mich entschieden hatte.

Heute funktioniert die nicht mehr. Wie kann denn sowas sein? Und vor allem, wie komme ich dahinter, was da schiefläuft?

Hier die ServiceUnit:

Code: Alles auswählen

[Unit]
Description=neph:collect.service:   Collects data once the network is up and running
After=network.target

[Service]
RemainAfterExit=yes
Type=idle
ExecStart=/usr/local/bin/pcf/collect.sh

[Install]
WantedBy=multi-user.target
LG // ein verwunderter neph

TomL

Re: Script will nicht, wie ich

Beitrag von TomL » 13.03.2017 11:52:18

nephilim hat geschrieben:Jetzt bin ich total durcheinander. Vorgestern habe ich ja noch hier die Option beschrieben, für die ich mich entschieden hatte.
Wie ich im Vorposting schon sagte... das funktioniert mit Einschränkungen richtig prima. Wegen der Einschränkungen habe ich diese Lösung allerdings dort wieder verworfen, wo konkrete Abhängigkeiten bestehen und nutze stattdessen meine Unit plus Script.

Schau Dir Status und die Log-Einträge an, ob Du was findest:

Code: Alles auswählen

systemctl status systemd-networkd systemd-networkd-wait-online.service

journalctl -b -u systemd-networkd-wait-online.service
journalctl -b -u systemd-networkd 
journalctl -p err
journalctl -p warning
Schau Dir die Ausgabe mit einem Picture-Viewer an.... Startzeit und Dauer und Reihenfolge ist dabei interessant

Code: Alles auswählen

systemd-analyze plot >~/bootplot.svg

Antworten