DNS geht nicht

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
p90
User
Beiträge: 198
Registriert: Donnerstag 22. Juli 2010, 17:30

Hi,

habe einen kleinen Socket Client geschrieben der auch funktioniert.
Daraufhin habe ich ihn als Dienst in Systemd eingestellt und wurde bei nächsten
Systemstart mit dieser Nachricht begrüßt:
Feb 28 00:52:08 pinkiepi DoorSounds[141]: [Errno -2] Name or service not known

Das ganze sieht so aus:

Code: Alles auswählen

def get_sock():
        #ugly but we have very shitty wlan....
        sock_err = 1
        while sock_err:
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                sock.settimeout(TIMEOUT)
                try:
                        sock_err = sock.connect_ex((HOSTNAME, PORT))
                except Exception, a:
                        err(a)
        else:
                return sock


if __name__ == "__main__":
        previous_state = None
        while True:
                try:
                        err("Connecting Socket")
                        sock = get_sock()
                        err("Socket Connected")
                        err("Waiting for state change")
                        while True:
                                try:
                                        tmp=sock.recv(BUFFER)[-1]
                                        state = int(tmp)
                                except (socket.timeout, ValueError):
                                        continue
                                if not previous_state == state:
                                        err("State change")
                                        switch_state(state)
                                        previous_state = state
                except Exception:
                        err("Socket lost")
        else:
                sock.close()
                #:)
Meine Vermutung ist, dass das Skipt vor einem laufenden DNS Server gestartet wird. Nun würde man ja meinen, dass es trotzdem irgendwann mal DNS bekommen würde, bekommt es aber nie.
Wie bekomme ich hier DNS rein?
Bis später

p91
BlackJack

@p90: Hat wahrscheinlich nichts mit dem Problem zu tun, aber Du hast anscheinend ``else`` bei Schleifen nicht verstanden. Solange in der Schleife kein ``break`` vorkommt, ist ein ``else``-Zweig komplett sinnfrei, denn dann wird der Code darin in *jedem* Fall ausgeführt (solange er nicht von einer Ausnahme ”übersprungen” wird).
p90
User
Beiträge: 198
Registriert: Donnerstag 22. Juli 2010, 17:30

Hi,

eigentlich war das ein Scherz an meinen Kollegen weil man ja jeden Socket wieder closen sollte. Deshalb der Smily.
Leider habe ich mir das etwas zerhackt. Vorher hatte ich den socket einmal eingestellt und dann nur eine Connection Funktion gehabt.
Als der Fehler auftrat dachte ich, dass dies genau das Problem sein könnte und habe es etwas verdummt bis es jetzt nur noch eine große while True Schleife ist.
BlackJack

@p90: Aus der Antwort kann ich jetzt nicht wirklich rauslesen ob Du den Einwand verstanden hast. Ich habe nichts gegen den Code in den ``else``-Zweigen gesagt, sondern dass er auch einfach ohne ``else`` hinter der jeweiligen Schleife stehen könnte. Das ``else`` macht den Quelltext nur unnötig komplexer und verwirrt Leute die ``else`` bei Schleifen nicht gewohnt sind. Die schauen dann in der Dokumentation nach was das semantisch bedeutet, und sind immer noch verwirrt weil sie (zu recht) nicht verstehen was das soll.
p90
User
Beiträge: 198
Registriert: Donnerstag 22. Juli 2010, 17:30

Hi,

du meinst, der Else Block wird nur ausgeführt wenn die Bedingung der Schleife mit False evaluiert.
Mir ist auch klar, dass er immer Ausgeführt wird weil ich kein break drin habe und ich somit das else
auch weglassen könnte.
Persönlich finde ich es aber übersichtlicher den in das else zu packen da ich dann direkt eine logische Verbindung zwischen den Blöcken habe. Aber wurscht. Bin mit meinem Problem noch nicht weiter.
Keine Idee warum das DNS nicht geht?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Das Problem ist dass du bei der Schleife eine falsche Semantik hast .. ueber die man einfach stolpern kann, sollte man darin doch noch ein `break` brauchen. Noch dazu willlst du eigentlich ein `try .. finally`.

Zum DNS: Kann es sein, dass das du die Abhaengigkeiten falsch angegeben hast und das Netzwerk noch nicht eingerichtet ist?
p90
User
Beiträge: 198
Registriert: Donnerstag 22. Juli 2010, 17:30

@cofi

Es kann durchaus sein, dass das Skript gestartet wird bevor das Netzwerk oben ist. Das es dann failed ist klar.
Aber wenn das Netzwerk dann hochkommt sollte die While Schleife doch dafür sorgen, dass es dann geht oder?
BlackJack

@p90: Welche ``while``-Schleife? Wo glaubst Du denn das diese Fehlermeldung her kommt? Welche Zeile im Programm gibt die aus?

Falls Du jetzt Zeile 10 antworten wolltest, beschreib mal wann diese Zeile *jemals* erreicht werden sollte?
p90
User
Beiträge: 198
Registriert: Donnerstag 22. Juli 2010, 17:30

Ich wollte tatsächlich Zeile 10 schreiben.
Und wie der Code ausgeführt wird?
Zeile 15 evaluiert True,
Zeile 17 evaluiert True und beginnt somit eine Schleife
Zeile 20 calls get_sock()
Zeile 4 evaluiert True da 1
Und somit sind wir in einem Codeblock ohne Conditions und nur einem Try-Except-Block.
Meintest du vlt. Zeile 35? Die wird wirklich nicht ausgeführt.

Hier mal ein zweites Program, diesmal etwas schöner damit wir uns nicht über hässlichen Code sondern über die Frage warum ein Python programm das gestartet wird wenn es noch kein DNS gibt auch später kein DNS hat:

Code: Alles auswählen

if __name__ == "__main__":
        previous_state = None
        while True:
                try:
                        sock = None
                        while sock is None:
                                err("Connecting Socket")
                                try:
                                        sock = socket.create_connection((HOSTNAME, PORT), TIMEOUT)
                                except (socket.timeout, socket.error, socket.herror, socket.gaierror), msg:
                                        err(msg)
                        err("connected")
                        while True:
                                try:
                                        state = int(sock.recv(4096)[-1])
                                except (socket.timeout, ValueError):
                                        continue
                                if not previous_state == state:
                                        switch_state(state)
                                        previous_state = state
                except (socket.timeout, socket.error, socket.herror, socket.gaierror):
                        err("Connection lost")
                        continue
Die Ausgabe hier ist ein ewiges:
Mar 01 14:58:09 pinkiepi DoorSounds[140]: [Errno -2] Name or service not known
Mar 01 14:58:09 pinkiepi DoorSounds[140]: Connecting Socket
Mar 01 14:58:09 pinkiepi DoorSounds[140]: [Errno -2] Name or service not known
Mar 01 14:58:09 pinkiepi DoorSounds[140]: Connecting Socket
Mar 01 14:58:09 pinkiepi DoorSounds[140]: [Errno -2] Name or service not known
Mar 01 14:58:09 pinkiepi DoorSounds[140]: Connecting Socket
Mar 01 14:58:09 pinkiepi DoorSounds[140]: [Errno -2] Name or service not known
Mar 01 14:58:09 pinkiepi DoorSounds[140]: Connecting Socket
Mar 01 14:58:09 pinkiepi DoorSounds[140]: [Errno -2] Name or service not known

Starte ich das Script dann manuel geht es sofort. Verstehe halt nur nicht warum?
Es sollte doch egal sein wann das Skript gestarted wurde, oder?
BlackJack

@p90: Aber Zeile 10 wird nie ausgeführt. Dazu müsste es eine Ausnahme geben. Und in der Zeile im ``try``/``except``-Block kann keine Socke-bezogene Ausnahme ausgelöst werden, also wo sollte die her kommen? Darum frage ich mich halt immer noch wo die Ausnahme im Log her kommt. Oder ob Du vielleicht den falschen Quelltext gezeigt hast.

Wie lange schaust Du Dir das Log denn so an? Und vielleicht wäre es eine gute Idee mal eine kleine Verzögerung in die Schleife einzubauen und nicht so schnell wie's irgend geht immer neue Verbindungsversuche zu machen.
p90
User
Beiträge: 198
Registriert: Donnerstag 22. Juli 2010, 17:30

Zeile 10 wird ausgeführt gerade weil da eine Exception passiert.
Mal aus der Spec:
socket.connect_ex(address)

Like connect(address), but return an error indicator instead of raising an exception for errors returned by the C-level connect() call (other problems, such as “host not found,” can still raise exceptions). The error indicator is 0 if the operation succeeded, otherwise the value of the errno variable. This is useful to support, for example, asynchronous connects.

Deswegen fange ich da auch genaz generisch alle Exceptions ab weil ich nicht rausfinden konnte welche Exception den nun alle passieren können.

Hab mittlerweile auch ein 1s sleep drin ändert aber auch nichts.

Zum Thema log dauer:
Zum Teil mehrere Stunden lang. Also Netzwerk ist bereits oben, alles geht, nur mein Skript nicht.
Restarte ich es dann geht es sofort.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Ja, genau _die_ Dokumentation beschreibt, warum da nie eine Exception auftreten kann:
socket.connect_ex(address)

Like connect(address), but return an error indicator instead of raising an exception for errors...
p90
User
Beiträge: 198
Registriert: Donnerstag 22. Juli 2010, 17:30

cofi hat geschrieben:Ja, genau _die_ Dokumentation beschreibt, warum da nie eine Exception auftreten kann:
socket.connect_ex(address)

Like connect(address), but return an error indicator instead of raising an exception for errors...
Einen Satz weiter lesen:
"(other problems, such as “host not found,” can still raise exceptions)"

Hatte das auch zuerst überlesen und nachdem mir da die erste Exception passiert war nen Try-except Block drum gebaut.

[EDIT]

Okay, ich glaube ich habs.
Anscheinend liegt das Problem darin, dass die unter Python liegenen libc calls resolv.conf cashen wodurch Python nicht mitbekommt, dass es
nun den Hostname doch resolven könnte.
Hier hab ich Code gefunden der das Problem löst:
http://bugs.sugarlabs.org/attachment/ti ... k.py.patch

Für weitere Anmerkungen bin ich sehr Dankbar den das sieht echt Hässlich aus.
Antworten