Server im Loop

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
droptix
User
Beiträge: 521
Registriert: Donnerstag 13. Oktober 2005, 21:27

Habe mir zum Rumspielen einen simplen SMTP-Server (smtpd Modul) geschrieben. Wenn ich den auf der Konsole starte, kommt das Programm ja in einen Loop und wird quasi nie beendet.

Ich kann den Server eigentlich nur durch Strg+C brutal beenden, wobei der Socket aber in Benutzung bleibt… jedenfalls wird der Server nicht ordnungsgemäß beendet, obwohl es eine close() Methode gibt.

1) Wie kann ich den Socket (unter Debian/Ubuntu) wieder freigeben? Gibt's da einen Konsolenbefehl? Auf die Socket-Option "Re-Use" habe ich keinen Einfluss, da der Socket im asyncore Modul erstellt wird und nicht in meinem Programmcode.

2) Wie kann ich den Server ordnungsgemäß beenden, wenn er sich im Loop befindet?

3) Ich möchte den SMTP-Server als Daemon starten und mir das lästige manuelle Starten nach dem Hochfahren ersparen. Nun habe ich aber das Problem mit dem Loop und brauche außerdem die start, stop und restart Parameter.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Naja, du musst eben die Klasse überschrieben und deine eigene Busy-Loop machen, dann kannst du sie auch abbrechen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

droptix hat geschrieben:1) Wie kann ich den Socket (unter Debian/Ubuntu) wieder freigeben? Gibt's da einen Konsolenbefehl? Auf die Socket-Option "Re-Use" habe ich keinen Einfluss, da der Socket im asyncore Modul erstellt wird und nicht in meinem Programmcode.
der asnyncore.dispatcher und der asynchat.async_chat haben jeweils die Methode set_reuse_addr().

droptix hat geschrieben:2) Wie kann ich den Server ordnungsgemäß beenden, wenn er sich im Loop befindet?
Du kannst den KeyboardInterrupt natuerlich abfangen, um Aufraeumarbeiten zu erledigen. Ausserdem waere das atexit-Modul einen Blick wert.
droptix hat geschrieben:3) Ich möchte den SMTP-Server als Daemon starten und mir das lästige manuelle Starten nach dem Hochfahren ersparen. Nun habe ich aber das Problem mit dem Loop und brauche außerdem die start, stop und restart Parameter.
Normalerweise schreibt man ein (Shell-)Script, welches bei start das Programm startet uns sich die PID in einer Datei mekrt, und welches bei stop und restart die ensprechenden Signale an das Programm schickt. Dein Programm sollte dann natuerlich die entsprechenden Signalhandler implementieren.
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
droptix
User
Beiträge: 521
Registriert: Donnerstag 13. Oktober 2005, 21:27

Hum, interessiert das als Daemon überhaupt, wenn das Skript in der Konsole einen Loop erzeugt, der nie beendet wird?

Ich weiß gar nicht wie das beim Apache ist… unter Windows muss man ja auch immer ein Fenster offen haben, es sei denn Apache läuft als Dienst. Sobald man es schließt, bricht man den Server anscheinend brutal ab.
Rebecca hat geschrieben:der asnyncore.dispatcher und der asynchat.async_chat haben jeweils die Methode set_reuse_addr().
Das wäre einen Versuch wert. Aber gibt es keinen Linux-Befehl, um einen Port wieder freizugeben? So als Notlösung…
Rebecca hat geschrieben:Ausserdem waere das atexit-Modul einen Blick wert.
Ach das geht auch beim brutalen Abbruch mit Ctrl+C?
Rebecca hat geschrieben:Normalerweise schreibt man ein (Shell-)Script, welches bei start das Programm startet uns sich die PID in einer Datei mekrt, und welches bei stop und restart die ensprechenden Signale an das Programm schickt. Dein Programm sollte dann natuerlich die entsprechenden Signalhandler implementieren.
Jo, das hatte ich schonmal erfragt, bin aber daran gescheitert. Habe zwar denke ich das mit den Signal-Handlern in Python verstanden, aber viel weiter hab ich's nicht geschafft.

Gibt's dafür Step-by-Step Tutorials im Netz? Oder kann man sich das bei einem typischen Linux-Dienst abkupfern? Welcher wäre geeignet?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

droptix hat geschrieben:Das wäre einen Versuch wert. Aber gibt es keinen Linux-Befehl, um einen Port wieder freizugeben? So als Notlösung…
Der Kernel gibt Ports selbst wieder frei, nach einigen Minuten.
droptix hat geschrieben:
Rebecca hat geschrieben:Ausserdem waere das atexit-Modul einen Blick wert.
Ach das geht auch beim brutalen Abbruch mit Ctrl+C?
Ja, und Strg+C ist kein brutaler Abbruch sondern schickt einfach nur ein Signal, auf was der Interpreter mit KeyboardInterrupt reagiert. Das nutze ich für meinen Enter-on-Exit-Handler. Also entspricht Strg+C eher dem SIGTERM statt dem SIGKILL.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Mal ein schneller Entwurf:

myserver.py:

Code: Alles auswählen

#!/usr/bin/env python

import time
import signal
import sys

def on_signal(signum, frame):
    print "Terminating..."
    sys.exit(0)

signal.signal(signal.SIGTERM, on_signal)

#So koennte man auch das ctrl-c abfangen:
#signal.signal(signal.SIGINT, on_signal)

while True:
    print "Running..."
    time.sleep(1)
Das startscript:

Code: Alles auswählen

#!/usr/bin/env python

import sys
import subprocess
import signal
import os

def start():
    f = open("PID_FILE", "w")
    pid = subprocess.Popen(["./myserver.py"]).pid
    f.write("%i\n" % pid)
    f.close()


def stop():
    f = open("PID_FILE")
    pid = int(f.read())
    f.read()
    os.kill(pid, signal.SIGTERM)
 

if sys.argv[1] == "start":
    start()
if sys.argv[1] == "stop":
    stop()
if sys.argv[1] == "restart":
    stop()
    start()
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
Antworten