Pythonでシェルコマンドを実行する


65

現在、侵入テストとPythonプログラミングを勉強しています。PythonでLinuxコマンドを実行する方法を知りたいだけです。実行したいコマンドは次のとおりです。

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

printがPythonで使用してターミナルで実行すると、自分で入力して押すと同じように実行されますEnterか?


5
os.systemはこれを行うことができます。
愚か者

2
と私bashは肥大化したシェルだと思った
...-mikeserv

3
モジュールのos.system使用を推奨するドキュメントsubprocess
ヨルダン

iptablesの出力が必要ですか?
キラ

3
この質問はStackoverflowに移行する必要があります。
www139

回答:


106

次のos.system()ようにを使用できます。

import os
os.system('ls')

またはあなたの場合:

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')

さらに良いことに、サブプロセスの呼び出しを使用できます。これはより安全で、より強力で、おそらくより高速です。

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

または、シェルを呼び出さずに:

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

出力をキャプチャする場合、それを行う1つの方法は次のとおりです。

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))

私は非常に設定することはお勧めtimeoutではcommunicate、また、それを呼び出すときにあなたが得ることができる例外をキャプチャします。これは非常にエラーが発生しやすいコードであるため、エラーが発生することを想定し、それに応じてエラーを処理する必要があります。

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


23
os.systemはバージョン2.6以降廃止されました。サブプロセスは、使用に適したモジュールです。
バイナリ基板

@binarysubstrate、サポートされていない、または利用できないなどの非推奨?私は最近(選択ではなく)2.7を搭載したマシンで作業しており、os.systemまだ動作しています。
openwonk

1
また、使用している場合はsubprocess.call推奨されているように、次のように指定する必要があるかもしれshell=True見る... ここに
openwonk

Python 3.4では、shell = Trueを指定する必要があります。そうしないと、呼び出しコマンドが機能しません。デフォルトでは、shell = Trueが設定されていない限り、呼び出しは文字列で指定されたファイルを開こうとします。また、Python 3.5の呼び出しはrunに置き換えられているようです
DLH

一般的なPOSIXコードは、おそらく環境変数decode()からの文字セットで呼び出す必要がありLC_CTYPEます。
ミッコランタライネン

29

最初のコマンドは、単にファイルに書き込みます。シェルpythonの助けを借りずにファイルを読み書きできるため、シェルコマンドとしてそれを実行しません。

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

iptablesコマンドを使用すると、外部から実行することをお勧めしますものです。これを行う最良の方法は、サブプロセスモジュールを使用することです

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

このメソッドはシェルを使用しないことにも注意してください。これは不必要なオーバーヘッドです。


13

最速の方法:

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

これは最も柔軟なアプローチではありません。「一度実行して完了し、終了するまでブロックする」以外にプロセスを制御する必要がある場合は、subprocess代わりにモジュールを使用する必要があります。


8

一般的なルールとして、可能な限りpythonバインディングを使用することをお勧めします(他の利点の中でも、より優れた例外キャッチ)。

echoコマンドについては、@ jordanmの回答で示唆されているように、Pythonを使用してファイルに書き込む方が明らかに良いです。

iptablesコマンドについては、多分python-iptablesPyPiページ説明とドキュメントを含むGitHubページ)が必要なものを提供します(特定のコマンドをチェックしませんでした)。

これにより、外部ライブラリに依存するようになるため、メリットを重視する必要があります。サブプロセスの使用は機能しますが、出力を使用する場合は、自分で解析し、将来のiptablesバージョンでの出力の変更に対処する必要があります。


もう1つ注意すべき点は、subprocess呼び出しによるコードの単体テストはあまり有用ではないということです。はい、呼び出しをモックアウトできますが、テストでは外部呼び出しの結果について推測する必要があります。
ヨルダン

あなたの答えはアドバイスのようなものです。OPは、PythonからLinuxシステムコマンドを実行する方法を具体的に尋ねました。
kapad

@kapadはい、しかし彼はまた、なぜそうしたいのかを特定し、私は代替案を提案しました。
ジェローム

2

シェルのPythonバージョン。注意してください、私はそれをテストしていません。

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.