Die obige Antwort erklärt es richtig, aber nicht direkt genug. Lass uns den ps
Befehl verwenden, um zu sehen was passiert.
import time
import subprocess
s = subprocess.Popen(["sleep 100"], shell=True)
print("start")
print(s.pid)
time.sleep(5)
s.kill()
print("finish")
Führe es aus und zeige
start
832758
finish
Dann kannst du ps -auxf > 1
vor finish
und dann ps -auxf > 2
nach finish
verwenden. Hier ist die Ausgabe
1
cy 71209 0.0 0.0 9184 4580 pts/6 Ss Oct20 0:00 | \_ /bin/bash
cy 832757 0.2 0.0 13324 9600 pts/6 S+ 19:31 0:00 | | \_ python /home/cy/Desktop/test.py
cy 832758 0.0 0.0 2616 612 pts/6 S+ 19:31 0:00 | | \_ /bin/sh -c sleep 100
cy 832759 0.0 0.0 5448 532 pts/6 S+ 19:31 0:00 | | \_ sleep 100
Siehst du? Anstatt direkt sleep 100
auszuführen, führt es tatsächlich /bin/sh
aus. und die pid
, die es ausgibt, ist tatsächlich die pid
von /bin/sh
. Wenn du dann s.kill()
aufrufst, tötet es /bin/sh
, aber sleep
ist immer noch vorhanden.
2
cy 69369 0.0 0.0 533764 8160 ? Ssl Oct20 0:12 \_ /usr/libexec/xdg-desktop-portal
cy 69411 0.0 0.0 491652 14856 ? Ssl Oct20 0:04 \_ /usr/libexec/xdg-desktop-portal-gtk
cy 832646 0.0 0.0 5448 596 pts/6 S 19:30 0:00 \_ sleep 100
Die nächste Frage ist, was kann /bin/sh
tun? Jeder Linux-Benutzer kennt es, hat von ihm gehört und verwendet ihn. Aber ich wette, dass es viele Menschen gibt, die eigentlich nicht verstehen, was shell
tatsächlich ist. Vielleicht hast du auch schon von /bin/bash
gehört, sie sind ähnlich.
Eine offensichtliche Funktion der Shell ist es, Benutzern die Bequemlichkeit zu bieten, Linux-Anwendungen auszuführen. Durch Shell-Programme wie sh
oder bash
kannst du beispielsweise den Befehl ls
direkt verwenden, anstatt /usr/bin/ls
. Es wird dann suchen, wo ls
ist und es für dich ausführen.
Die andere Funktion besteht darin, dass sie Zeichenfolgen nach dem $
als Umgebungsvariable interpretiert. Du kannst diese beiden Python-Skripte vergleichen, um es selbst herauszufinden.
subprocess.call(["echo $PATH"], shell=True)
subprocess.call(["echo", "$PATH"])
Und das Wichtigste: Es ermöglicht das Ausführen von Linux-Befehlen als Skript. Solche wie if
else
werden von der Shell eingeführt. Es sind keine native Linux-Befehle
47 Stimmen
Der erste Befehl ist falsch:
-l
wird an/bin/sh
(die Shell) übergeben statt an dasls
Programm auf Unix wennshell=True
. Ein String-Argument sollte in den meisten Fällen mitshell=True
verwendet werden anstelle einer Liste.3 Stimmen
Bitte übersetzen: "der Prozess wird direkt gestartet": Was?
21 Stimmen
Die Aussage "Beide funktionieren." über diese 2 Aufrufe ist falsch und irreführend. Die Aufrufe funktionieren unterschiedlich. Das Umschalten von
shell=True
aufFalse
und umgekehrt ist ein Fehler. Aus Dokumenten: "Auf POSIX mit shell=True, (...) Wenn args eine Sequenz ist, gibt das erste Element den Befehlsstring an, und alle zusätzlichen Elemente werden als zusätzliche Argumente für die Shell selbst behandelt.". Auf Windows gibt es eine automatische Umwandlung, die unerwünscht sein könnte.0 Stimmen
Siehe auch stackoverflow.com/q/59641747/874188
2 Stimmen
@DeusXMachina Du wiederholst fälschlicherweise die beiden älteren Kommentare, die dies erklären.
subprocess.run(['ls', '-l'r, shell=True)
führt dazu, dasssh -c 'ls' 'sh' '-l'
ausgeführt wird. Die Argumente werden nicht "stillschweigend ignoriert", sondern man muss wissen, wie man damit umgeht. Zugegeben, für die meisten praktischen Zwecke lautet die einfachste und meist korrekte Anleitung: "Verwenden Sieshell=True
nicht, wenn Sie eine Liste von Token übergeben, und umgekehrt". Windows toleriert dies besser, ist jedoch aus anderen Gründen natürlich völlig untragbar.