web-dev-qa-db-fra.com

Exécutez les commandes Shell dans Python

J'étudie actuellement tests de pénétration et Python programmation. Je veux juste savoir comment je ferais pour exécuter une commande Linux en Python. Les commandes que je veux exécuter sont:

echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A PREROUTING -p tcp --destination-port 80 -j REDIRECT --to-port 8080

Si j'utilise simplement print dans Python et l'exécute dans le terminal, cela fera-t-il la même chose que l'exécuter comme si vous le tapiez vous-même et appuyez sur Enter?

70
iZodiac

Vous pouvez utiliser os.system(), comme ceci:

import os
os.system('ls')

Ou dans votre cas:

os.system('echo 1 > /proc/sys/net/ipv4/ip_forward')
os.system('iptables -t nat -A PREROUTING -p tcp --destination-port 80 -j REDIRECT --to-port 8080')

Mieux encore, vous pouvez utiliser l'appel du sous-processus, il est plus sûr, plus puissant et probablement plus rapide:

from subprocess import call
call('echo "I like potatos"', Shell=True)

Ou, sans invoquer Shell:

call(['echo', 'I like potatos'])

Si vous souhaitez capturer la sortie, une façon de procéder est la suivante:

import subprocess
cmd = ['echo', 'I like potatos']
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

o, e = proc.communicate()

print('Output: ' + o.decode('ascii'))
print('Error: '  + e.decode('ascii'))
print('code: ' + str(proc.returncode))

Je recommande fortement de définir un timeout dans communicate, ainsi que de capturer les exceptions que vous pouvez obtenir lors de l'appel. Il s'agit d'un code très sujet aux erreurs, vous devez donc vous attendre à des erreurs et les traiter en conséquence.

https://docs.python.org/3/library/subprocess.html

114
Kira

La première commande écrit simplement dans un fichier. Vous ne l'exécuteriez pas en tant que commande Shell car python peut lire et écrire dans des fichiers sans l'aide d'un shell:

with open('/proc/sys/net/ipv4/ip_forward', 'w') as f:
    f.write("1")

La commande iptables est quelque chose que vous voudrez peut-être exécuter en externe. La meilleure façon de le faire est d'utiliser le module de sous-processus .

import subprocess
subprocess.check_call(['iptables', '-t', 'nat', '-A',
                       'PREROUTING', '-p', 'tcp', 
                       '--destination-port', '80',
                       '-j', 'REDIRECT', '--to-port', '8080'])

Notez que cette méthode n'utilise pas non plus de shell, ce qui est une surcharge inutile.

30
jordanm

Le moyen le plus rapide:

import os
os.system("your command here")

Ce n'est pas l'approche la plus flexible; si vous avez besoin de plus de contrôle sur votre processus que de "l'exécuter une fois, jusqu'à la fin et de bloquer jusqu'à ce qu'il se termine", vous devez utiliser le module subprocess à la place.

13
Tom Hunt

En règle générale, il vaut mieux utiliser les liaisons python dans la mesure du possible (meilleure capture des exceptions, entre autres avantages).

Pour la commande echo, il est évidemment préférable d'utiliser python pour écrire dans le fichier comme suggéré dans la réponse de @ jordanm.

Pour la commande iptables, peut-être python-iptables ( page PyPi , page GitHub avec description et doc ) fournirait ce dont vous avez besoin (je n'ai pas vérifié votre commande spécifique).

Cela vous ferait dépendre d'une bibliothèque externe, vous devez donc pondérer les avantages. L'utilisation de sous-processus fonctionne, mais si vous souhaitez utiliser la sortie, vous devrez l'analyser vous-même et gérer les modifications de sortie dans les futures versions de iptables.

8
Jérôme

Une version python de votre Shell. Attention, je ne l'ai pas testée.

from subprocess import run

def bash(command):
        run(command.split())

>>> bash('find / -name null')
/dev/null
/sys/fs/selinux/null
/sys/devices/virtual/mem/null
/sys/class/mem/null
/usr/lib/kbd/consoletrans/null
2
Timothy Pulliam

Si vous souhaitez exécuter cette commande dans un autre système après SSH, vous devrez peut-être utiliser le module nommé Paramiko. C'est vraiment utile.

Si l'exécution de la commande doit être effectuée à partir d'une machine locale, les fonctions du module os seront utiles.

Page d'accueil: https://www.paramiko.org/

Développement: https://github.com/paramiko/paramiko

0
Mikhilesh Sekhar