Alle in meinem Netzwerk befindliche Geräte herunterfahren

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
FrankRahn199
User
Beiträge: 7
Registriert: Samstag 9. Juni 2018, 16:50

Hallo,

ich arbeite mich seit kurzem in Python ein und die Programmiersprache gefällt mir sehr gut.

Ich möchte gerne ein Pythonprogramm erstellen, das alle in meinem Netzwerk befindliche Geräte herunterfährt. (IP Adressenraum: [192,168,0,0],[192,168,255,255]) Wir nutzen nur Windows 7 und 10 jeweils 64 BIT. - Wer drei pupertierende Kinder hat kennt den Grund... ;-) :roll:

Ich habe folgendes Programm erstellt, aber es funktioniert nicht. Wer kann mir helfen oder einen besseren Code schreiben?

Es gibt folgende Fehlermeldung:

ip = raw_input("[[192,168,0,0],[192,168,255,255]]:")
NameError: name 'raw_input' is not defined


Programmentwurf:

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

ip = raw_input("[[192,168,0,0],[192,168,255,255]]:")
nachricht = raw_input("Nachricht: Jetzt ist Schlafenszeit")

s.sendto(nachricht, (ip, 1))
s.close()

if message == "shutdown" :
ser.close()
os.system("shutdown -h now")
sys.exit()
else: print("Gute Nacht")
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Wenn Du im Forum Code postest, bitte in den passenden Tags (»Python«-Knopf über dem Editfeld).

„Funktioniert nicht” ist eine schlechte Fehlerbeschreibung. Was tut genau nicht? Gibt es Fehlermeldungen? Ist das Verhalten (welches) anders, als gewollt (was wird erwartet)?

Irgendwelche Nachrichten auf TCP-Port 1 zu senden, was denkst Du passiert? Es ist sehr unwahscheinlich, dass dort ein Server läuft, oder hast Du auf jedem Rechner ein passendes Gegenstück laufen? »shutdown -h now« wird den Rechner auf dem Du gerade bist, herunterfahren, wenn es erstens ein Linuxrechner ist und Du zweitens root-Rechte hast. Es wird aber keinen Windowsrechner in der Ferne herunterfahren.

Es scheint aber auch ein »shutdown« für Windows zu geben, mit dem man (entsprechende Rechte) auch Nachrichten an einen anderen Rechner schicken und diesen herunterfahren kann. Dazu ist dann auch kein Python nötig, weil es nicht viel mehr ist, als ein Kommandozeilenaufruf.
FrankRahn199
User
Beiträge: 7
Registriert: Samstag 9. Juni 2018, 16:50

Hallo, es gibt folgende Fehlermeldung:

Es gibt folgende Fehlermeldung:

ip = raw_input("[[192,168,0,0],[192,168,255,255]]:")
NameError: name 'raw_input' is not defined

Die Nachricht ist nicht so wichtig, viel wichtiger wäre es, alle Netzwerkgeräte mit dem starten eines Programms herunterzufahren. Da der Router dynamische IP Adressen vergibt ist mein Ansatz, dass alle Geräte im IP Adressenbereich heruntergefahren werden.

Danke für den Tipp, dass der Shutdownbefehl nur den eigenen PC herunterfährt.
Benutzeravatar
sls
User
Beiträge: 480
Registriert: Mittwoch 13. Mai 2015, 23:52
Wohnort: Country country = new Zealand();

Der Ansatz sollte wohl überlegt sein, da du damit unkontrolliert Geräte steuerst, die du vielleicht nicht oder nicht in jenem Moment herunterfahren magst. Der von der gezeigte Adressraum ist ein /16-Netz, die Broadcast-Domäne erstreckt sich also über rund 65 Tausend (!) mögliche IP-Adressen. Bist du dir sicher, dass du ein derart großes Heimnetz hast?

Welche Python-Version verwendest du? raw_input() ist eine Funktion aus Python2 und liest den vom Benutzer auf der Kommandozeile eingegebenen String ein. Da deine Nachricht statisch ist, brauchst du diese Einlesefunktion überhaupt nicht.

Deine Nachricht wird, selbst wenn du sie mit dem gezeigten Code an einen fremden Rechner schicken kannst, zu keiner Zeit dort irgendwo angezeigt. Damit du mit Windows-Clients sprechen kannst, musst du eine entsprechende Bibliothek verwenden, shutdown -h now ist Shell / Linux Syntax.

`message` wurde nie deklariert und initialisiert. Das mischen von deutscher und englischer Sprache war noch nie eine gute Idee.
When we say computer, we mean the electronic computer.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Genau dafür gibt es DNS-Namen, bzw NETBIOS-Namen bei Windows, die auch bei dynamischer IP-Zuordnung fix sind. Die Rechner heißen dann \\ComputerTom oder \\ComputerJane, was dann auch viel einfacher zu Steuern ist, falls Jane mal eine Extrastunde zum Seminararbeitschreiben bekommt.

Nochmal, falls das untergegangen sein sollte: von Deinem jetzigen Ansatz läßt sich nichts übernehmen. Mach Dich mit Rechnernamen und shutdown.exe von Windows vertraut und versuche es (erstmal) direkt über die Kommandozeile damit.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1012
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Shutdown kann Windows-Rechner auch via Remote herunterfahren. Dafür muss man aber auf den Zielrechnern Rechte haben.
Wie man das einstellen kann, wird unter anderem hier beschrieben: https://www.online-tech-tips.com/comput ... n-command/

Du musst dann, wenn du alles gemacht hast, für jeden zu herunterfahrenden Rechner einen shutdown Befehl absetzen.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Benutzeravatar
Kebap
User
Beiträge: 686
Registriert: Dienstag 15. November 2011, 14:20
Wohnort: Dortmund

FrankRahn199 hat geschrieben: Sonntag 10. Juni 2018, 08:20 Da der Router dynamische IP Adressen vergibt
Das kann man auch deaktivieren. ;)
MorgenGrauen: 1 Welt, 8 Rassen, 13 Gilden, >250 Abenteuer, >5000 Waffen & Rüstungen,
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1012
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Hier mal ein Beispiel mit Tkinter:

Code: Alles auswählen

from tkinter import Tk, Button
from subprocess import call, PIPE
from threading import Thread


def ping(buttons):
    """
    Startet einen Daemon Thread und pingt alle Rechner an.
    """
    thread = Thread(target=_ping, args=[buttons], daemon=True)
    thread.start()


def _ping(buttons):
    """
    Diese Funktion wird als Thread gestartet.
    Es wird jeder Rechner angepingt und die Buttons werden eingefärbt.
    """
    for button, host in buttons:
        # button ist die Referenz zum button
        # host ist der Hostname bzw. die IP Adresse
        command = ['ping', '-c', '1', '-W', '1', host]
        # Ping Befehl ist unter Windows etwas anders
        # Damit das funktioniert, muss er angepasst werden
        if call(command, stdout=PIPE, stderr=PIPE) == 0:
            button.config(bg='green')
        else:
            button.config(bg='red')


def shutdown(host):
    """
    Hier den code ergänzen, um Windows-PCs herunter zu fahren
    Aktuell findet nur eine Ausgabe in der Konsole statt und sonst
    passiert nichts.
    """
    print(f'shutdown -R {host}')


def app(names_or_ips):
    """
    Mit der funktion wird die GUI gestartet und alles weitere konfiguriert.
    """
    root = Tk()
    root.title('Windows Shutdown Tool')
    buttons = []
    # die Liste buttons soll nach dem Durchlauf der Schleife jeweils den
    # Button als Objekt und die IP als string beinhalten
    for row, host in enumerate(names_or_ips):
        button = Button(root, text=host, command=lambda: shutdown(host))
        button.grid(row=row, column=0)
        buttons.append((button, host))
    # row == letzter wert
    row += 1
    Button(root, text='Ping', command=lambda: ping(buttons)).grid(row=row, column=0)
    row += 1 # wieder um einen hochzählen, um in der nächsten Zeile zu landen.
    Button(root, text='Quit', command=root.destroy).grid(row=row, column=0)
    root.after(500, ping, buttons) # nach 500 ms die Hosts anpingen
    root.mainloop()


if __name__ == '__main__':
    # die Hosts können Namen oder IP-Adressen sein.
    hosts = ['192.168.0.1', '192.168.0.2', '192.168.0.3']
    # hier wird die GUI gestartet.
    app(hosts)
Wichtig ist eigentlich nur die Funktion shutdown. Ping muss auch noch angepasst werden. Ich bin kein Window-Nutzer und kenne den Syntax jetzt nicht auswendig.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@DeaD_EyE: GUI-Elemente von einem Thread aus zu manipulieren in dem nicht die GUI-Hauptschleife läuft kann funktionieren, muss aber nicht. Ausserdem könnte das problematisch werden wenn ein Ping hängt, aber trotzdem alle 500 Millisekunden ein neuer Thread gestartet wird, bei dem dann wahrscheinlich der gleiche Ping-Empfänger wieder hängen wird und es immer mehr Threads werden.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
DeaD_EyE
User
Beiträge: 1012
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

@OP: Das angesprochene threading von __blackjack__ bezieht sich auf Race-Conditions. Also wenn zwei oder mehr Threads gegeneinander kämpfen. Der eine Thread kann z.B. eine Variable zuweisen, während der andere Thread noch einen alten Wert ausgelesen hat mit diesem weiter arbeitet und dann ggf. wieder eine Zuweisung macht. Spätestens da hat man ein Chaos und es ist sehr schwer nachzuvollziehen, wenn der Code komplexer wird. Das ist einer der Gründe, wieso es so schwierig ist Threading richtig zu implementieren.

Ping bleibt nicht hängen, sofern man einen Timeout angibt. Ich wies auch nochmal drauf hin, dass der Syntax unter Windows etwas anders ist.
Dort wird es aber auch einen Parameter für den timeout geben.
Wenn man sich nicht auf das Betriebssystem verlassen will/kann, könnte man eine Implementierung in Python nehmen.
Da hat man aber das Problem, dass man erhöhte Rechte benötigt. Unter Linux ist das so und unter Windows schätze ich mal auch.
Das wäre ziemlich doof das Programm mit Adminstrator-Rechten auszuführen.

Zum Threading:
Wenn ping nur einmal ausgeführt wird, gibt es auch nur einen Thread, der den Call macht. Also nur eine Zuweisun. Um zu verhindern, dass zur Laufzeit des Threads kein weiterer gestartet werden kann.
Ja, man könnte das sogar so toll machen, dass man den Thread vorzeitig beenden kann.

Hier mal eine erweiterte Version:

Code: Alles auswählen

from tkinter import Tk, Button
from subprocess import call, PIPE
from threading import Thread, Event


PING_EVENT = Event()


def ping(buttons):
    """
    Startet einen Daemon Thread und pingt alle Rechner an.
    """
    if not PING_EVENT.is_set():
        PING_EVENT.set()
        thread = Thread(target=_ping, args=[buttons], daemon=True)
        thread.start()
    else:
        print('Ping is currently executed.')


def _ping(buttons):
    """
    Diese Funktion wird als Thread gestartet.
    Es wird jeder Rechner angepingt und die Buttons werden eingefärbt.
    """
    for button, host in buttons:
        # button ist die Referenz zum button
        # host ist der Hostname bzw. die IP Adresse
        command = ['ping', '-c', '1', '-W', '1', host]
        # Ping Befehl ist unter Windows etwas anders
        # Damit das funktioniert, muss er angepasst werden
        if call(command, stdout=PIPE, stderr=PIPE) == 0:
            button.config(bg='green')
        else:
            button.config(bg='red')
    PING_EVENT.clear()


def shutdown(host):
    """
    Hier den code ergänzen, um Windows-PCs herunter zu fahren
    Aktuell findet nur eine Ausgabe in der Konsole statt und sonst
    passiert nichts.
    """
    print(f'shutdown -R {host}')


def app(names_or_ips):
    """
    Mit der funktion wird die GUI gestartet und alles weitere konfiguriert.
    """
    root = Tk()
    root.title('Windows Shutdown Tool')
    buttons = []
    # die Liste buttons soll nach dem Durchlauf der Schleife jeweils den
    # Button als Objekt und die IP als string beinhalten
    for row, host in enumerate(names_or_ips):
        button = Button(root, text=host, command=lambda: shutdown(host))
        button.grid(row=row, column=0)
        buttons.append((button, host))
    # row == letzter wert
    row += 1
    Button(root, text='Ping', command=lambda: ping(buttons)).grid(row=row, column=0)
    row += 1 # wieder um einen hochzählen, um in der nächsten Zeile zu landen.
    Button(root, text='Quit', command=root.destroy).grid(row=row, column=0)
    root.after(500, ping, buttons) # nach 500 ms die Hosts anpingen
    root.mainloop()


if __name__ == '__main__':
    # die Hosts können Namen oder IP-Adressen sein.
    hosts = ['192.168.0.1', '192.168.0.2', '192.168.0.3']
    # hier wird die GUI gestartet.
    app(hosts)


Falls du eine bessere Lösung kennst, dann poste sie einfach als Code. Darüber diskutieren kann man, wenn du ein Snippet gepostet hast.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@DeaD_EyE: ich verstehe den Sinn nicht, warum Du ping mit after aufrufst. button.config darf nur vom Hauptthread aus geändert werden. PING_EVENT ist eine globale Variable, und keine Konstante und auch gar nicht nötig, weil man sich einfach den gestarteten Thread merken könnte und beim Aufruf prüfen, ob er noch alive ist.

Da der OP aber überhaupt nicht nach einer GUI gefragt hat, frage ich mich, warum Du seinen Thread kaperst.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1012
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Meine Beiträge bitte löschen, ihr habt die meine Zustimmung.
Ich werde mich nicht mehr beteiligen. Ihr macht das schon.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
FrankRahn199
User
Beiträge: 7
Registriert: Samstag 9. Juni 2018, 16:50

DeaD_EyE hat geschrieben: Mittwoch 13. Juni 2018, 09:41 Meine Beiträge bitte löschen, ihr habt die meine Zustimmung.
Ich werde mich nicht mehr beteiligen. Ihr macht das schon.
Hallo DeaD_EyE,

vielen Dank, dass du dir die Mühe gemacht hast Code zu entwickeln und zu posten. Du hast mir sehr geholfen und die nächsten Tage werde ich das testen. Wie wäre der Cod ohne Tinken? z.B. es ist 23 Uhr unter der Woche und die Pupertiere denken gar nicht daran, dass morgen um 5.45 Uhr der Wecker klingelt? Ich hätte gerne einen kurzen Pythoncode, kurz und knackig ohne GUI (das zwingt mich auch mich näher mit dem Code zu befassen.

Vielen lieben Dank für deine sehr umfangreiche Hilfe.
Frank
Benutzeravatar
DeaD_EyE
User
Beiträge: 1012
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Keine Ursache.
Ich dachte mir, dass es ggf. einfacher ist eine GUI zu verwenden, auch wenn das gar nicht die Frage war.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
FrankRahn199
User
Beiträge: 7
Registriert: Samstag 9. Juni 2018, 16:50

Hallo DeaD_EyE, vielen Dank für deine Hilfe. Bitte schicke mir den Code ohne Tinker per Nachricht. Dann unterbleiben auch die Kommentare. Ich wäre dir für deine Hilfe sehr dankbar. --> Mail: frankrahn1@gmx.net

Danke und LG Frank
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Kann ich an die E-Mail auch per Paypal größere Summen Geld überweisen? Der transparente Versuch sich Code durch gegeneinander ausspielen der User hier zu ergaunern ist ja schon in vollem Gange. Da geht noch was!

Deine Dankbarkeit hat durch testen und Nachfragen zum schon geposteten Code ja auch schon deutlich Form angenommen! Das zeigt das ganze Ausmaß der versprochen Beschäftigung mit der kostenlos erbrachten Leistung anderer. Das lässt hoffen!

Bei manchen Leuten fällt mir echt nix mehr ein :evil:
Benutzeravatar
DeaD_EyE
User
Beiträge: 1012
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Jegliche Kommentare verkneife ich mir mal.

Quelle: https://www.online-tech-tips.com/comput ... n-command/
Kommando zum Herunterfahren: shutdown /m \\computername /s /f

Mit subprocess.call kannst du shutdown aufrufen.

Code: Alles auswählen

import subprocess


def shutdown(computername):
    command = ['shutdown', '/m', '\\\\' + computername, '/s', '/f']
    subprocess.call(command)
Der Befehl Shutdown sollte auch ohne Pfadangabe funktionieren.

Funktion aufrufen:

Code: Alles auswählen

shutdown('computername')
Sofern der Name des Zielrechners aufgelöst werden kann und die Berechtigung dafür freigegeben ist, sollte der Rechner herunterfahren.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Wobei das zu einem ”Python”-Skript zu führen scheint das eigentlich kaum bis gar kein Python braucht und genau so gut oder eben besser als PowerShell- oder Batch-Skript umgesetzt werden könnte.
Komplett ungetestet:

Code: Alles auswählen

$computers = ("\\watson", "\\colossus")
$computers | foreach { Stop-Computer -computer $_ -Force }
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
FrankRahn199
User
Beiträge: 7
Registriert: Samstag 9. Juni 2018, 16:50

Danke für den Code. Ich teste ihn.

__blackjack__ hat geschrieben: Mittwoch 20. Juni 2018, 08:58 Wobei das zu einem ”Python”-Skript zu führen scheint das eigentlich kaum bis gar kein Python braucht und genau so gut oder eben besser als PowerShell- oder Batch-Skript umgesetzt werden könnte.
Komplett ungetestet:

Code: Alles auswählen

$computers = ("\\watson", "\\colossus")
$computers | foreach { Stop-Computer -computer $_ -Force }
Antworten