# IP-Adresse von Linux-Router über eigenes Webif ändern



## Html (29. Mai 2010)

Hallo. Ich versuche mal die Problematik zu erläutern. Ich hab einen Router mit einer Linux-FW(OpenWrt), darauf läuft ein Webserver(lighttpd).
Auf diesem Webserver befindet sich mein eigenes Webif. Das Webif besteht aus Bash-CGI-Skripten. So. Nun möchte ich eben über solch ein Bash-CGI-Skript die IP des Routers ändern. Die Sache funktioniert auch im Prinzip. 

Ich habe ein Bash-CGI-Skript mit einem Formular zum Eingeben der neuen IP. Nach dem Absenden wird das Formular an die gleiche Seite gesendet, die IP auf das richtige Format überprüft, die IP geändert und danach muss noch das netzwerkinterface des Routers neu gestartet werden damit die IP auch übernommen wird.
Alles das funktioniert. Doch erzeuge ich nach dem die IP geändert wurde einen meta-refresh mit der neuen IP(Aufruf der Webif mit: http://IP/cgi-bin/*.sh). Ich habe aber nun das Problem das die Seite nach dem ändern der IP nicht mehr vollständig geladen wird, so das der refresh funktioniert. Rein äußerlich wird die Seite nach dem Absenden des Formulars wieder komplett aufgebaut. Der Ladebalken im Firefox bleibt aber in der Mitte stehen. Gebe ich dann in der URL die neue IP ein wird das Webif wieder geladen. Aber dies solle eben nach dem ändern automatisch geschehen.

Ich habe aber den Befehl für das Neustarten des Netzwerkinterfaces schon ganz ans Ende der Seite gesetzt. D.h der komplette Html-Code wurde bis dahin ausgegeben.

Also alles was ich möchte ist, dass nach dem ändern der IP kurz eine Seite erscheint mit z.B der Meldung "Das Netzwerkinterface wird gerade neu gestartet" und dann nach einer Zeit t, die der Router für das Neustarten des Netzwerkinterface braucht, auf die neue IP weitergeleitet wird.

Ich meine, bei diesen Original-FW besteht ja auch die Möglichkeit die IP zu ändern.

Ich möchte nochmals betonen, das es hier nicht um die Befehle geht mir der ich die IP ändere. Die Befehle sind vorhanden und funktionieren.

Ich hoffe das mir jemand helfen kann.


----------



## Html (29. Mai 2010)

Es geht eig lediglich um den Befehl


```
ifup lan
```

Dieser startet das Netzwerkinterface neu und die zuvor eingegebene IP wird übernommen.
Doch obwohl dieser Befehl am Ende des Bash-CGI-Skripts steht, wird die Seite nicht vollständig übertragen.

?


----------



## Html (30. Mai 2010)

Niemand eine Idee?


----------



## port29 (30. Mai 2010)

Also entweder verstehe ich gerade das Problem nicht, oder es ist tatsächlich "zu simpel".
Also dein Problem ist, dass du eine Meldung haben möchtest, dass gerade die IP Adresse geändert wird, bevor dir die "alte" Netzwerkverbindung abschmiert.

Dann mach das doch so, dass bei dir die Eigentliche Änderung in einem eigenständigen Script asynchron abläuft. Da wo bei dir jetzt die IP Adresse geändert wird, schreibst du den asynchronen Start (z.B. mit & am Ende) eines weiteren Scriptes. Und in diesem Script schreibst du noch zusätzlich sleep 5 vor der IP Änderung rein.


----------



## Html (30. Mai 2010)

Hallo. So hatte ich es auch schon versucht, aber es funktioniert leider nicht. 
Das CGI-Skript chip.sh wird nach dem Absenden des Formulars nicht mehr vollständig geladen. Rein äußerlich wurde die Seite wieder neue aufgebaut, aber der Ladebalken bleibt in der Mitte stehen.

chip.sh

```
#!/bin/bash
echo Content-type: text/html
echo ""


#Auswertung Parameterübergabe             
submit=`echo "$QUERY_STRING" | sed -n 's/^.*send=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`
ipaddr=`echo "$QUERY_STRING" | sed -n 's/^.*ipaddr=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`



#Daten lesen?
if [ "$submit" = "true" ] 
then
regex="\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b"
CHECK=$(echo $ipaddr | egrep $regex)
	if [[ "$?" -eq 0 ]]
	then
		err_msg='<li><p id="msg">Die IP-Adresse wurde erfolgreich geändert</p></li>'
		meta_refresh='<meta http-equiv="refresh" content="10; URL=http://'$ipaddr'/cgi-bin/read.sh">'	
	else
		err_msg='<li><p id="err_msg">Die IP-Adresse ist nicht korrekt!</p></li>'
	fi
fi





#Beginn Html
echo '<html>'
echo '<head>'
echo '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">'
echo $meta_refresh
echo '<title></title>'
echo '<link rel="stylesheet" type="text/css" href="style.css">'
echo '</head>'
echo '<body>'
echo '<div id="container">'

#Header
echo '<div id="header">'
echo '</div>'

#Navigationsleiste
echo '<div id="nav">'
echo '<ul>'
echo '<li><a href="read.sh">Daten lesen</a></li>'
echo '<li><a href="chpasswd.sh">Passwort ändern</a></li>'
echo '<li><a href="chip.sh" class="active">Router-IP ändern</a></li>'
echo '</ul>'
echo '</div>'

echo '<div id="wrapper">'
echo '<div id="content">'

#ab hier beginnt der Inhalt

#IP-Formular
echo '<ul id="form">'
echo '<form name="chip" id="chpasswd" action="chip.sh" method="GET" accept-charset="utf-8">'
echo $err_msg

echo '<li><label for="newpasswd">IP-Adresse:</label>'
echo '<input name="ipaddr" type="input" size="15" maxlength="15"></li>'
echo '<input type="hidden" name="send" value="true">'
echo '<li id="submit"><input type="submit" value="IP-Adresse ändern"></li>'
echo '</ul>'
echo '</form>' 

#Ende Inhalt

echo '</div>'
echo '</div>'

echo '<div id="footer">'
echo '</div>'

echo '</body>'
echo '</html>'

if [ "$submit" = "true" ]
	then
	./restart.sh& $ipaddr
fi
```

restart.sh

```
#!/bin/bash

sleep 5
/sbin/uci set network.lan.ipaddr=$1
/sbin/uci commit network
/sbin/ifup lan
```


----------



## port29 (30. Mai 2010)

```
./restart.sh $ipaddr &
```

müsste es heißen


----------



## Html (30. Mai 2010)

Auch damit geht es nicht. 
Nehmen wir mal an der Router hat zunächst die IP 192.168.1.100. 
Ich geben also im Formular die neue IP 192.168.1.101 ein und sende das Formular ab.
Die Seite wird wieder neu aufgebaut, über dem Fomular steht korrekterweise das die IP erfolgreich eingetragen wurde.
Nur im Browser unten steht " Übertrage Daten von 192.168.1.100" und wie schon gesagt der Ladebalken steht in der Mitte.

Irgendwie läuft die Änderung der IP nicht asynchron verzögert ab, so das scheinbar die IP unmittelbar nach Absenden des Formulars geändert wird und der Seitenaufruf greift ja noch auf die alte IP zu so das es dann Probleme gibt.

?


----------



## Html (30. Mai 2010)

Gebe ich die gleiche IP ein die der Router auch aktuell besitzt erkennt man das 
die Seite nach dem Absenden des Formulars auch hier erst fertig aufgebaut wird wenn die 5s im restart.sh abgelaufen sind und dieses Skript fertig ist. Dann verschwindet der Ladebalken und es wird mit dem meta-refresh umgeleitet.


----------



## port29 (31. Mai 2010)

Also das ist ganz interessant. Okay, versuchen wir mal etwas anderes. Das ganze ist ja einfach nur ein Shellscript.  Was passiert, wenn du z.B. die if Abfrage ausbaust und dann einfach an der Konsole die Datei ausführst? Landest du direkt an der Shell und 5 Sekunden später kommt die Änderung oder wartet er, bis die 5 Sek. fertig sind, bis du an der Shell landest?

http://www.perlmonks.org/?node=cgi buffer flush

Die Seite finde ich auch ganz interessant. Da schreiben die irgendwas davon, dass man 


```
$| = 1;
und / oder
$|++
```

Oben in den "Header" einfügen muss. Probiere das evtl. mal aus.


----------



## Html (31. Mai 2010)

Also. Ich habe die if-abfrage ausgebaut und folgendes ans ende von chip.sh geschriebn:


```
./restart.sh 192.168.1.100 &
```

Das Skript restart.sh wie oben. Danach hab ich mich auf der Bash eingeloggt und chip.sh aufgerufen.
Auf der Shell sehe ich dann die Html-Ausgabe. Direkt danach erscheint eine neue Eingabe-Zeile der Bash.

Lasse ich das "&" beim Aufruf von restart.sh weg, wird zunächst auch der html-code ausgegeben, jedoch erscheint erst nach ca. 5s eine neue Eingabe-Zeile der Bash.


?


----------



## deepthroat (31. Mai 2010)

Hi.





port29 hat gesagt.:


> http://www.perlmonks.org/?node=cgi buffer flush
> 
> Die Seite finde ich auch ganz interessant. Da schreiben die irgendwas davon, dass man
> 
> ...


Ähem, das ist aber Perl. 

@Html: Schließe mal die Standard Ein-/Ausgabeströme am Ende vom Skript

```
exec <&- >&-
```
Und du könntest auch disown für den restart.sh Job aufrufen.

Gruß


----------



## Html (3. Juni 2010)

Also die Standard Ein-/Ausgabeströme habe ich geschlossen. Keine Veränderung.
"Disown" steht mir nicht zur Verfügung, dafür habe ich es mit "nohup" probiert:


```
if [ "$submit" = "true" ]
	then
	
	nohup ./restart.sh &ipaddr &
fi
```

Allerdings auch damit wird die Seite nicht wieder vollständig geladen.
Ich weiß nicht woran es noch liegen könnte!?


----------



## deepthroat (3. Juni 2010)

Html hat gesagt.:


> "Disown" steht mir nicht zur Verfügung


Dann hast du wohl nicht wirklich eine bash?


Html hat gesagt.:


> ```
> nohup ./restart.sh &ipaddr &
> ```


So kann das aber nichts werden. Das hatte dir port29 aber auch bereits gesagt - du führst damit die beiden Befehle "nohup ./restart.sh" und "ipaddr" im Hintergrund aus (zumindest bei letzerem bleibt es beim Versuch).

Oder tippst du das etwa jedesmal ab und hast dich verschrieben?


Html hat gesagt.:


> Allerdings auch damit wird die Seite nicht wieder vollständig geladen.
> Ich weiß nicht woran es noch liegen könnte!?


Evtl. wartet der lighty bis wirklich der letzte Kindprozess des gestarteten CGI Prozesses beendet ist.

Versuche mal die die Eingabe/Ausgabe des restart.sh Skripts auf /dev/null umzuleiten.

Gruß


----------



## Html (3. Juni 2010)

Wie bereits eingangs erwähnt ist das ganze OpenWrt. 
Die Bash ist def. vorhanden. (GNU Bash 3.2.0). Diese wurde als Paket mitinstalliert.

Ist "disown" vllt eine Option beim kompilieren der Bash?
Eben sowas wie "net-redirections". Dies musste ich auch zuvor im Makefile erst explizit angeben.

Also was ich vor hatte mit nohup, ist das skript restart.sh dem die Variable $ipaddr mitübergeben wird vom Elternprozess, sprich hier vom CGI-Skript, abgekapselt wird, damit die Seite vollständig geladen wird.
Müsste es vllt so heißen


```
nohup (./restart.sh &ipaddr) & > /dev/Null
```


----------



## deepthroat (4. Juni 2010)

Html hat gesagt.:


> Wie bereits eingangs erwähnt ist das ganze OpenWrt.
> Die Bash ist def. vorhanden. (GNU Bash 3.2.0). Diese wurde als Paket mitinstalliert.
> 
> Ist "disown" vllt eine Option beim kompilieren der Bash?
> ...


Du verwechselst immer noch & mit $.

Das & ist ein Kommando-Trennzeichen (so wie ein Semikolon), es darf nur am Ende eines Kommandos auftauchen weil damit das Kommando abgeschlossen wird.

```
nohup &> /dev/null </dev/null ./restart.sh &
```
Gruß


----------



## Html (4. Juni 2010)

Super, danke. Es funktioniert!


----------

