LinuxシステムにPythonバージョンがあります - 2.7.5 - redhat 7.3
sedを使用してファイルの文字列を置き換える簡単なスクリプトを作成しました。
more test.py
#!/usr/bin/env python
import subprocess
subprocess.call("sed s'/2.6/2.6.4/g' /tmp/file.xml")
しかし、我々は得た
Traceback (most recent call last):
File "./test.py", line 5, in <module>
subprocess.call("sed s'/2.6/2.6.4/g' /tmp/file.xml")
File "/usr/lib64/python2.7/subprocess.py", line 524, in call
return Popen(*popenargs, **kwargs).wait()
File "/usr/lib64/python2.7/subprocess.py", line 711, in __init__
errread, errwrite)
File "/usr/lib64/python2.7/subprocess.py", line 1327, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
Pythonスクリプトにどのような問題がありますか?
more file.xml
2.6.0.3-8
答え1
Pythonでは:
使用するとき
subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)
またはsubprocess.Popen(args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0)
args
これはすべての呼び出しに必要であり、プログラムパラメータの文字列またはシーケンスでなければなりません。一般に、さまざまなパラメータを提供することが推奨されます。これは、モジュールが必須パラメータのエスケープと引用符(ファイル名にスペースを含める)を処理できるようにするためです。これは、単一の文字列が渡される場合はshell
trueでなければなりませんTrue
(以下を参照)。そうでない場合、文字列は引数を指定せずに実行するプログラムの名前のみを指定する必要があります。
...
その場合、指定されたコマンドはshell
シェルTrue
を介して実行されます。 Pythonがほとんどのシステムシェルによって提供される制御フローを改善するために主にPythonを使用しており、まだシェルパイプ、ファイル名ワイルドカード、環境変数拡張、ユーザー~
ホームディレクトリ拡張などの他のシェル機能に簡単にアクセスしたい場合一緒に行うことができます。便利です。 。
したがって、次のように指定すると方法が機能します。
subprocess.call("sed s'/2\.6/2.6.4/g' /tmp/file.xml", shell=True)
しかし...
警告する:
shell=True
使用時に安全上の危険があります。
信頼できないソースからの洗練されていない入力を含むシェルコマンドを実行すると、プログラムは攻撃に対して脆弱になります。シェル注入、任意のコマンドの実行につながる可能性がある深刻なセキュリティの脆弱性です。このshell=True
ためとても落胆 コマンド文字列が外部入力として構成されている場合。
shell=True
を使用すると、pipes.quote()
シェルコマンドの設定に使用される文字列の空白と、シェルメタ文字を正しくエスケープするために使用できます。
結論:コマンドをargs
単一の文字列(shell=True
set)に渡す場合は、少なくともエスケープ/引用符を付ける必要があります。ただし、上記のようにさまざまなパラメータを提供することをお勧めします。
import subprocess
subprocess.call(['sed', 's/2\.6/2.6.4/g', '/tmp/file.xml'])