440 votes

Signification réelle de "shell=True" dans un sous-processus

J'appelle différents processus avec le subprocess module. Cependant, j'ai une question.

Dans les codes suivants :

callProcess = subprocess.Popen(['ls', '-l'], shell=True)

et

callProcess = subprocess.Popen(['ls', '-l']) # without shell

Les deux fonctionnent. Après avoir lu les docs, j'ai appris que shell=True signifie exécuter le code par l'intermédiaire du shell. Cela signifie donc qu'en cas d'absence, le processus est directement lancé.

Alors, que dois-je préférer dans mon cas - j'ai besoin d'exécuter un processus et d'obtenir sa sortie. Quel avantage ai-je à l'appeler depuis le shell ou en dehors de celui-ci ?

49 votes

La première commande est incorrecte : -l est transmis à /bin/sh (le shell) au lieu de ls programme sous Unix si shell=True . L'argument chaîne doit être utilisé avec shell=True dans la plupart des cas, au lieu d'une liste.

3 votes

Re "le processus est directement lancé" : Quoi ?

21 votes

L'affirmation "Les deux fonctionnent" à propos de ces deux appels est incorrecte et trompeuse. Les appels fonctionnent différemment. Il suffit de passer de shell=True a False et vice versa est une erreur. De docs : "Sur POSIX avec shell=True, (...) Si args est une séquence, le premier élément spécifie la chaîne de commande, et tous les éléments supplémentaires seront traités comme des arguments supplémentaires pour le shell lui-même.". Sous Windows, il y a conversion automatique ce qui pourrait être indésirable.

-3voto

lauc.exon.nod Points 109

Supposons que vous utilisez shell=False et que vous fournissez la commande sous forme de liste. Et qu'un utilisateur malveillant essaie d'injecter une commande 'rm'. Vous verrez que 'rm' sera interprété comme un argument et que 'ls' essaiera de trouver un fichier appelé 'rm'.

>>> subprocess.run(['ls','-ld','/home','rm','/etc/passwd'])
ls: rm: No such file or directory
-rw-r--r--    1 root     root          1172 May 28  2020 /etc/passwd
drwxr-xr-x    2 root     root          4096 May 29  2020 /home
CompletedProcess(args=['ls', '-ld', '/home', 'rm', '/etc/passwd'], returncode=1)

shell=False n'est pas une sécurité par défaut, si vous ne contrôlez pas correctement l'entrée. Vous pouvez toujours exécuter des commandes dangereuses.

>>> subprocess.run(['rm','-rf','/home'])
CompletedProcess(args=['rm', '-rf', '/home'], returncode=0)
>>> subprocess.run(['ls','-ld','/home'])
ls: /home: No such file or directory
CompletedProcess(args=['ls', '-ld', '/home'], returncode=1)
>>>

J'écris la plupart de mes applications dans des environnements de conteneurs, je sais quel shell est invoqué et je ne prends aucune entrée utilisateur.

Ainsi, dans mon cas d'utilisation, je ne vois aucun risque de sécurité. Et il est beaucoup plus facile de créer de longues chaînes de commandes. J'espère que je ne me trompe pas.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X