Neues Konsolenfenster in Python öffnen und nach X sec terminieren

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
scanbot90
User
Beiträge: 11
Registriert: Freitag 1. Juni 2018, 07:40

Hallo zusammen,

Ich suche eine Möglichkeit um in einer Konsolenanwendung ein neues Konsolenfenster zu öffnen, darin ein anderes Programm aufzurufen und dieses nach X Sekunden zu beenden.
-> auf Debian

Leider wurde ich bei meiner Suche nicht fündig.
Ich weiß nur dass ich die Bibliothek subprocess einbinden muss.

Kann mir jemand weiter helfen?
Benutzeravatar
sls
User
Beiträge: 480
Registriert: Mittwoch 13. Mai 2015, 23:52
Wohnort: Country country = new Zealand();

Mit Subprocess kannst du das umsetzen, die Frage ist, ob du wirklich eine andere Shell dazu öffnen musst. Mit Subprocess kann man sowas transparent gestalten.

Helfen können wir dir bestimmt, sobald dein Problem konkreter wird. Dazu ist Code von dir hilfreich, bisher sieht's ja eher so aus als hättest du noch nichts probiert.
When we say computer, we mean the electronic computer.
__deets__
User
Beiträge: 14536
Registriert: Mittwoch 14. Oktober 2015, 14:29

Mobilunity hat geschrieben: Freitag 1. Juni 2018, 09:46 Hallo! Hast du an Stackoverflow angeschaut?
Vllt findest du was hier https://stackoverflow.com/questions/100 ... indow-open
Der TE benutzt Debian.
scanbot90
User
Beiträge: 11
Registriert: Freitag 1. Juni 2018, 07:40

Guten Abend zusammen,

also der bisher vorgeschlagene Link, beschreibt gar nicht mein Problem.

Code: Alles auswählen

import os, threading, subprocess

def terminate_Process():
    if process.poll() is None:
	try:
	    process.terminate()
	except EnvironmentError:
	    pass 
	
def AirDumpWlan1():
    try:
	print "Enable Airdump.." 
	csv_data = "AWA_AirDump_tmp"
	
	#Hier will ich das neue Program starten.. Dies funktioniert auch (es wäre aber schön zu wissen, wie ich dies in einer neuen Shell öffnen könnte)
	process = subprocess.Popen("sudo airodump-ng --cswitch 0 --uptime -w "+ str(csv_data) +" --berlin 10 wlan1", shell=True)
	
	#im folgenden Teil geht es mir nur darum, dass das aufgerufene Programm für 60 Sekunden läuft und danach beendet wird
	#Funktioniert noch nicht!
	timer = threading.Timer(60, terminate_Process)
	timer.start()
	process.wait()
	timer.cancel()
	
    except KeyboardInterrupt:
	print O + "\nAirodump-ng" + R + " (^C) "+ O + "interrupted" + W
	
Kann mir jemand weiter helfen, bzw hat jemand einen anderen Ansatz.
Auf die Funktion terminate_Process() würde ich am liebsten auch verzichten.. Es muss doch einen leichteren Ansatz geben.

Vieln Dank im Voraus
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
Auf die Funktion terminate_Process() würde ich am liebsten auch verzichten.. Es muss doch einen leichteren Ansatz geben.
Also der Ansatz ist IMHO schon relativ einfach...

Muss die andere Anwendung wirklich in einem sichtbaren Konsolenfenster laufen? Wenn ja, warum?

Gruß, noisefloor
scanbot90
User
Beiträge: 11
Registriert: Freitag 1. Juni 2018, 07:40

noisefloor hat geschrieben: Freitag 1. Juni 2018, 18:28 Hallo,
Auf die Funktion terminate_Process() würde ich am liebsten auch verzichten.. Es muss doch einen leichteren Ansatz geben.
Also der Ansatz ist IMHO schon relativ einfach...

Muss die andere Anwendung wirklich in einem sichtbaren Konsolenfenster laufen? Wenn ja, warum?

Gruß, noisefloor
Für den Anfang würde mir reichen, wenn das aufgerufene Unterprogramm für 60 sec läuft, und dann beendet wird (egal ob in der Shell sichtbar oder nicht, oder in einem neuen Shellfenster).
Hauptsache das Unterprogramm wird für 60 sec ausgeführt und dann beendet
__deets__
User
Beiträge: 14536
Registriert: Mittwoch 14. Oktober 2015, 14:29

In neueren Python-Verisionen gibt es subprocess.run, das kennt einen Timeout. Und du solltest niemals ein eigenes Terminal-Fenster starten, wenn du Ausgaben darstellen willst, kannst du die vom gestarteten Prozess mittels PIPEs abgreifen, und dann selbst darstellen.
scanbot90
User
Beiträge: 11
Registriert: Freitag 1. Juni 2018, 07:40

__deets__ hat geschrieben: Freitag 1. Juni 2018, 19:40 In neueren Python-Verisionen gibt es subprocess.run, das kennt einen Timeout. Und du solltest niemals ein eigenes Terminal-Fenster starten, wenn du Ausgaben darstellen willst, kannst du die vom gestarteten Prozess mittels PIPEs abgreifen, und dann selbst darstellen.
Habe den Code nun geändert:

Code: Alles auswählen

#
import os, threading, subprocess

def AirDumpWlan1():
    try:
	print "Enable Airdump.." 
	csv_data = "AWA_AirDump_tmp"
	subprocess.run("sudo airodump-ng --cswitch 0 --uptime -w "+ str(csv_data) +" --berlin 10 wlan1", shell=True, timeout=10)
	
    except KeyboardInterrupt:
	print "\nAirodump-ng (^C) interrupted" 
    except subprocess.TimeoutExpired:
        print ("Timeout Expired")
Problem:
Nach 10 sec passiert irgendwas mit der Shell, sodass das Unterprogramm weiter läuft, ich aber die Shell nicht mehr bedienen kann (Strg + C funktioniert auch nicht mehr).
Über den Shell-Befehl "top", sehe ich auch, dass das Unterprogramm (Airodump-ng) weiterhin läuft und nicht beendet wurde.

Wenn ich in

Code: Alles auswählen

subprocess.run("sudo airodump-ng --cswitch 0 --uptime -w "+ str(csv_data) +" --berlin 10 wlan1", shell=False, timeout=10)
shell = False setze, dann kommt diese Fehlermeldung:
with Popen(*popenargs, **kwargs) as process:
File "/usr/lib/python3.6/subprocess.py", line 709, in __init__
restore_signals, start_new_session)
File "/usr/lib/python3.6/subprocess.py", line 1344, in _execute_child
raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: 'sudo airodump-ng --cswitch 0 --uptime -w AWA_AirDump_tmp --berlin 10 wlan1': 'sudo airodump-ng --cswitch 0 --uptime -w AWA_AirDump_tmp --berlin 10 wlan1'
Brauche weiterhin Hilfe :)
__deets__
User
Beiträge: 14536
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du hast ja auch eine Shell dazwischen gespannt. Warum? Bau dein Kommando vernünftig als Liste von Strings auf statt dem zusammen gerödel mit + und str().

subprocess.run(["kommando", "argument"], ...)

aber OHNE shell =True.
scanbot90
User
Beiträge: 11
Registriert: Freitag 1. Juni 2018, 07:40

__deets__ hat geschrieben: Freitag 1. Juni 2018, 21:05 Du hast ja auch eine Shell dazwischen gespannt. Warum? Bau dein Kommando vernünftig als Liste von Strings auf statt dem zusammen gerödel mit + und str().

subprocess.run(["kommando", "argument"], ...)

aber OHNE shell =True.
Das Unterprogramm Airodump-ng wird zwar gestartet (und ist auch sichtbar in der Shell) aber wird auch hier nicht terminiert...

Aktueller Code:

Code: Alles auswählen

import os, threading, subprocess

def AirDumpWlan1():
    try:
	print "Enable Airdump.." 
	csv_data = "AWA_AirDump_tmp"
	#alte Version: 
	#subprocess.run("sudo airodump-ng --cswitch 0 --uptime -w "+ str(csv_data) +" --berlin 10 wlan1", shell=True, timeout=10)
	
	#Neu: Unterprogram wird trotzdem in Shell angezeigt und wird nicht nach 10 sec terminiert
	subprocess.run(["sudo", "airodump-ng", "--cswitch", "0", "--uptime" , "-w", "AWA_AirDump_tmp", "--berlin", "10", "wlan1"], shell=False, timeout=10)
    except KeyboardInterrupt:
	print "\nAirodump-ng (^C) interrupted" 
    except subprocess.TimeoutExpired:
        print ("Timeout Expired")
weitere Vorschläge?
__deets__
User
Beiträge: 14536
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das ist ungewöhnlich. Du könntest statt run Popen & communicate benutzten. Das hat das auch ein timeout Argument. Wenn der timeout kommt, fliegt aber erstmal nur die Exception. Es ist dann dein Job kill aufzurufen. Da solltest du auch statt SIGINT ein SIGTERM oder SIGKILL absetzen.
scanbot90
User
Beiträge: 11
Registriert: Freitag 1. Juni 2018, 07:40

__deets__ hat geschrieben: Freitag 1. Juni 2018, 21:53 Das ist ungewöhnlich. Du könntest statt run Popen & communicate benutzten. Das hat das auch ein timeout Argument. Wenn der timeout kommt, fliegt aber erstmal nur die Exception. Es ist dann dein Job kill aufzurufen. Da solltest du auch statt SIGINT ein SIGTERM oder SIGKILL absetzen.
Für den "Job" bin ich leider nicht qualifiziert :/
Habe bisher keines der genannten Funktionen benutzt und wüsste auch nicht wie ich mein Programm entsprechend ändern muss...

Kannst du das explizit an meinem Code anwenden?
Und vielen Dank im Voraus 😊
__deets__
User
Beiträge: 14536
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ah. Ist mir vorher gar nicht aufgefallen- du benutzt ja sudo. Damit geht das natürlich auch nur mit sudo zu killen.

Damit musst du die PID vom Popen Objekt abgreifen & mit „sudo kill <pid>“ Abschießen.

Und ich schreib das hier auf dem iPhone. Da ist nix mit in deinem Code anwenden.
scanbot90
User
Beiträge: 11
Registriert: Freitag 1. Juni 2018, 07:40

__deets__ hat geschrieben: Freitag 1. Juni 2018, 22:11 Ah. Ist mir vorher gar nicht aufgefallen- du benutzt ja sudo. Damit geht das natürlich auch nur mit sudo zu killen.

Damit musst du die PID vom Popen Objekt abgreifen & mit „sudo kill <pid>“ Abschießen.

Und ich schreib das hier auf dem iPhone. Da ist nix mit in deinem Code anwenden.
das sudo muss da leider stehen, ohne sudo funktioniert das Unterprogramm leider nicht.

Würde mich freuen, wenn du dir ganze nochmal bei guter Laune am PC anschaust :)))

Schönen Abend
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

Wo ist jetzt noch Dein Problem? __deets__ hat doch geschrieben, wie Du Dein Programm beenden kannst, einfach nochmal ein subprocess.run absetzen mit dem sudo-kill-Befehl.
scanbot90
User
Beiträge: 11
Registriert: Freitag 1. Juni 2018, 07:40

Also Leute, ich bekomme es einfach nicht auf die Reihe.

Vllt sollte ich hinzufügen, dass das Programm Airodump-ng (mit sudo ausgeführt) in einer Endlosschleife ist und normalerweise nur mit Strg + C terminiert werden kann.
Ich habe jetzt alle bisherigen Vorschläge aufgegriffen und versucht.. Leider ohne Erfolg! :/

Der aktuelle Code:
... wobei immernoch bei diesem Beispiel mit shell=false die Shell angezeigt wird

Code: Alles auswählen

import os, subprocess

# Console colors
W 	= '\033[0m'	# white (normal)
R 	= '\033[31m'	# red
G       = '\033[32m'	# green
O       = '\033[33m'	# orange

def AirDumpWlan1():
    print (O + "Enable Airdump.." + W)
    csv_data = "AWA_AirDump_tmp"

    #sub_airodump = subprocess.run(["sudo", "airodump-ng", "--cswitch", "0", "--uptime" , "-w", "AWA_AirDump_tmp", "--berlin", "10", "wlan1"],timeout=10)
    #sub_airodump = subprocess.run("sudo airodump-ng --cswitch 0 --uptime -w "+ str(csv_data) +" --berlin 10 wlan1", shell=False, timeout=10)
    sub_airodump = subprocess.Popen(["sudo", "airodump-ng", "--cswitch", "0", "--uptime" , "-w", "AWA_AirDump_tmp", "--berlin", "10", "wlan1"], shell=False)	#Shell wird trotzdem angezeigt
    try:
        sub_airodump.communicate(timeout=5)
        pid_airodump = sub_airodump.pid
        sub_airodump.wait(5)
        subprocess.run(["sudo", "kill", str(pid_airodump)])
        sub_airodump.terminate()
        
    except KeyboardInterrupt:
        print (O + "\nAirodump-ng" + R + " (^C) "+ O + "interrupted" + W)
    except TimeoutError:
        sub_airodump.kill()
        print (R + "Timeout Error" + W)
Hab jetzt alles mögliche versucht um das Subprocess zu beenden.. aber nichts funktioniert.
Dementsprechend stehen jetzt oben im Code paar verschiedene Methoden drinnen, um den Process zu terminieren..

Außerdem hab ich auf https://docs.python.org/3/library/subprocess.html nachgelesen:
Popen.pid
The process ID of the child process.
Note that if you set the shell argument to True, this is the process ID of the spawned shell.
... das bedeutet doch, dass ich ja doch die Shell True setzten muss, damit ich die PID auslesen kann. Oder nicht?

Es funktioniert immernoch nicht...
Brauche weitere Hilfe
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

Du hast und brauchst keine Shell, denn mit Shell ist ein Programm gemeint, das das Ausführen von anderen Programmen erlaubt, also /bin/sh, /bin/ksh, /bin/bash, /bin/dash. Was Du siehst ist die Ausgabe auf einem Terminal. Das machen alle Programme, wenn man die Ausgabe nicht irgendwohin umleitet. Dein `kill` beendet nur den sudo-Befehl, nicht aber das Programm, das von sudo ausgeführt wird. Dazu mußt Du also den Kindprozess finden.

Code: Alles auswählen

subprocess.run(["sudo", "pkill", "-P", str(pid_airodump)])
scanbot90
User
Beiträge: 11
Registriert: Freitag 1. Juni 2018, 07:40

Sirius3 hat geschrieben: Sonntag 3. Juni 2018, 09:45 Du hast und brauchst keine Shell, denn mit Shell ist ein Programm gemeint, das das Ausführen von anderen Programmen erlaubt, also /bin/sh, /bin/ksh, /bin/bash, /bin/dash. Was Du siehst ist die Ausgabe auf einem Terminal. Das machen alle Programme, wenn man die Ausgabe nicht irgendwohin umleitet. Dein `kill` beendet nur den sudo-Befehl, nicht aber das Programm, das von sudo ausgeführt wird. Dazu mußt Du also den Kindprozess finden.

Code: Alles auswählen

subprocess.run(["sudo", "pkill", "-P", str(pid_airodump)])
Das Programm läuft trotzdem weiter..
Also ich habe bisher jeden Vorschlag versucht umzusetzten, aber nichts hilft -.-

aktueller Code mit lauter Terminationsmöglichkeiten.. wobei keine hilft:

Code: Alles auswählen

import os, subprocess
# Console colors
W 	= '\033[0m'	# white (normal)
R 	= '\033[31m'	# red
G       = '\033[32m'	# green
O       = '\033[33m'	# orange

    def AirDumpWlan1():
    print (O + "Enable Airdump.." + W)
    csv_data = "AWA_AirDump_tmp"

    #sub_airodump = subprocess.run(["sudo", "airodump-ng", "--cswitch", "0", "--uptime" , "-w", "AWA_AirDump_tmp", "--berlin", "10", "wlan1"],timeout=10)
    #sub_airodump = subprocess.run("sudo airodump-ng --cswitch 0 --uptime -w "+ str(csv_data) +" --berlin 10 wlan1", shell=False, timeout=10)
    sub_airodump = subprocess.Popen(["sudo", "airodump-ng", "--cswitch", "0", "--uptime" , "-w", "AWA_AirDump_tmp", "--berlin", "10", "wlan1"], shell=False)
    try:
        sub_airodump.communicate(timeout=5)
        pid_airodump = sub_airodump.pid
        sub_airodump.wait(5)
        subprocess.run(["sudo", "pkill", "-P",str(pid_airodump)])
        #sub_airodump.terminate()
        
    except KeyboardInterrupt:
        print (O + "\nAirodump-ng" + R + " (^C) "+ O + "interrupted" + W)
    except TimeoutError:
        sub_airodump.kill()
        subprocess.run(["sudo", "pkill", "-P",str(pid_airodump)])
        print (R + "Timeout Error" + W)
        
__deets__
User
Beiträge: 14536
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du kannst die PID nicht so holen, wie du das glaubst. Der Code steht in communicate bis das entweder vorbei ist, womit du nix killen musst. ODER er schmeißt den Timeout, aber DANN kam er ja nie an der Zeile vorbei, in der du die PID auslesen willst. Was soll er da also killen?

Du musst die PID also vor dem communicate schon haben. Eigentlich sollte das auch einen Fehler geworfen haben. Denn er kennt pid ja gar nicht.
scanbot90
User
Beiträge: 11
Registriert: Freitag 1. Juni 2018, 07:40

Hallo zusammen,
ich komme solangsam der Sache näher.. aber leider gibt es noch ein paar Schwierigkeiten.

Aktueller Code:

Code: Alles auswählen

import os
import time
from subprocess import Popen, call, PIPE
from signal import SIGINT, SIGTERM
from sys import stdout  # Flushing

W 	= '\033[0m'	# white (normal)
R 	= '\033[31m'	# red
G       = '\033[32m'	# green
O       = '\033[33m'	# orange
B       = '\033[34m'	# blue
P       = '\033[35m'	# purple
C       = '\033[36m'	# cyan
GR      = '\033[37m'	# gray

# /dev/null, send output from programs so they don't print to screen.
DN = open(os.devnull, 'w')

def send_interrupt(process):
    """
        Sends interrupt signal to process's PID.
    """
    try:
        os.kill(process.pid, SIGINT)
        # os.kill(process.pid, SIGTERM)
    except OSError:
        pass  # process cannot be killed
    except TypeError:
        pass  # pid is incorrect type
    except UnboundLocalError:
        pass  # 'process' is not defined
    except AttributeError:
        pass  # Trying to kill "None"
        
def AirDumpWlan1():
    print (O + "Enable Airdump.." + W)
    csv_data = "AWA_AirDump_tmp"
    countdown = 10.0
    scan = True
    timer = 0
    sub_airodump = Popen(["sudo", "airodump-ng", "--uptime" , "-w", "AWA_AirDump_tmp", "--berlin", "10", "wlan1"], stdout=DN, stderr=DN)
    time_started = time.time()
    time.sleep(0.5)
    print (GR + ' [+] ' + G + 'initializing scan' + W + ' (' + G + 'wlan1' + W + '), finishing scan in ' + G + str(countdown) + W + ' seconds')
    while scan:
        timer = time.time() - time_started
        print (G + str(timer) + W)
        #Check ob Timer größer als 10.0
        if float(timer) >= float(countdown):
            send_interrupt(sub_airodump)
            try:
                os.kill(sub_airodump.pid, SIGTERM)
            except KeyboardInterrupt:
                print (O + "\nAirodump-ng" + R + " (^C) "+ O + "interrupted" + W)
            except OSError:
                pass
            except UnboundLocalError:
                pass
                
            #Hier lass ich mir extra die PID ausgeben    
            print (str(sub_airodump.pid))
            scan = False
            time.sleep(0.5)
            break
Also das Python-Script öffnet ganz normal den Unterprozess Airodump (endlich nicht mehr in der Shell).
Nach 10 sec soll das Programm terminiert werden, ABER die abgegriffene PID ist immer eine Nummer kleiner als gewünscht.

Hier das Ende der Ausgabe aus dem Python-Script:

Code: Alles auswählen

...
...
9.99996614456
9.9999730587
9.99998116493
9.99998903275
9.99999713898
10.0000050068
7081					#Das ist die PID die mein Python-Skript abgreift
odin@SCNBT90:~/Schreibtisch/AirDump$
Und hier was mir Top anzeigt:

Code: Alles auswählen

odin@SCNBT90:~/Schreibtisch/AirDump$ top | grep airodump
 7082 root      20   0  102172   7004   2928 S   1,7   0,2   0:00.05 airodump-ng                        
 7082 root      20   0  102172   7004   2928 S   0,3   0,2   0:00.06 airodump-ng                        
 7099 root      20   0   24612   1868   1616 D   0,3   0,0   0:00.01 airodump-ng                        
 7082 root      20   0  102172   7004   2928 S   0,3   0,2   0:00.07 airodump-ng                        
 7099 root      20   0   24612   1868   1616 S   0,3   0,0   0:00.02 airodump-ng
Scheinbar wird Airodump-ng 2-Mal geöffnet.. weil es zeigt mir ja 2 Prozesse an -.-
Weis leider nicht wie das entsteht bzw wie ich dem entgegenwirken kann.
Wenn ich Airodump-ng normal in der Shell starte, zeigt mir Top auch nur einen Prozess an...

Habe mich an dem Python-Skript Wifite orientiert (https://github.com/derv82/wifite/blob/master/wifite.py).
Leider sind meine Pythonkenntnisse noch im Ausbau

Sieht jemand einen Fehler, bzw. wie ich die richtige PID erhalte (ohne es um 1 inkrementieren zu müssen)?
Und wie ich den zweiten Unterprozess vermeiden kann, bzw auch abgreifen kann? (in dem Bsp. mit PID=7099)
Antworten