2017-04-18 7 views
0

私はtest.pyスクリプトの中でいくつかの引数を取るシェルコマンドラインを実行したいと思う。 test.pyはこれに類似の内側に見えるPythonのコマンドライン引数でshell = Trueを避ける

python test.py filename file_2 int 

import sys 

filename = sys.argv[1] 
file_2 = sys.argv[2] 
num = sys.argv[3] 

subprocess.call("xargs /bin/bash build/install/programme/bin/programme option -n "+num+" --csv-file="+str(filename)+" -c files/"+str(file_2)+ "< /tmp/my_ids_"+str(file_2)+"_"+str(num),shell=True) 

ポイントは、私はシェル= Trueのを使用して避けたいということですが、すべてのtest.pyは、以下のように実行されます私が今までに見つけたオプションは、私がコマンドラインで追加している引数に対して良い解決策を提供していません。

import sys 

filename = sys.argv[1] 
file_2 = sys.argv[2] 
num = sys.argv[3] 

subprocess.Popen(["xargs","/bin/bash","build/install/programme/bin/programme","option","-n", str(num),"--csv-file=",str(filename),"-c","files/",str(file_2),"<",str("/tmp/my_ids_"+str(file_2)+"_"+str(num))]) 

しかし、私は何の作業結果を得なかっ:

は、これまでのところ私は、例えばとして、Popenでそれを分割を経由してさまざまなオプションを試してみました。 shlexでも試しましたが、ドキュメントではコマンドに引数を追加できるオプションがありませんでした。

ご協力いただきありがとうございます。

+0

なぜ 'shell = True'を避けたいですか? –

+0

@ PedroLobitoこれは非効率で、引用エラーが発生しやすいためです。可能であれば、文字列引数のリストを 'execve'(または' exec'ファミリのどのメンバーが使用されているか)に直接渡すほうがずっと良いです。 – chepner

+0

@PedroLobito、...私は "クォートエラー"を超えて - 文字列連結を介してコマンドを生成し、それらの文字列をコードとして評価することで、あなたのソフトウェアはインジェクション攻撃に対して脆弱になります。 [Bobby Tables](https://xkcd.com/327/)を考えてみましょう。彼は 'Johnny $(rm -rf $ HOME) '$(rm -rf $ HOME)'という兄弟を持っています。 –

答えて

2

あなたの元のコードは、次のbashコマンドを実行するのと同じだった:

xargs \ 
    /bin/bash \ 
    build/install/programme/bin/programme \ 
    option \ 
    -n   "$int" \ 
    "--csv-file=" "$filename" \ 
    -c   "files/"   "${file_2}" \ 
    '<'   "/tmp/my_ids_${file_2}_${int}" 

いずれか働いた、とすべて同じ理由でなかったでしょう。


import sys 

filename = sys.argv[1] 
file_2 = sys.argv[2] 
num = int(sys.argv[3]) 

subprocess.Popen([ 
    "xargs", 
    "/bin/bash", 
    "build/install/programme/bin/programme", 
    "option", 
    "-n", str(num), 
    "--csv-file=%s" % filename, 
    "-c", "files/%s" % file_2, 
], stdin=open("/tmp/my_ids_%s_%s" % (file_2, num), 'r') 

違い注:単一の引数は、常に単一のリストメンバーとして渡され

  • 。つまり、--csv-file=filenameはすべて一つのことであり、プレフィックスfiles/と変数file_2に含まれる文字列は、同じリスト要素内で渡す必要があります。
  • リダイレクト(<)は、プログラムへの引数ではなく、からシェルへの命令です。したがって、ここでは使用できませんが、その効果をシミュレートするために他のオプション(Popenへのstdinおよびstdoutの引数など)を使用する必要があります。
  • intは、整数型の名前です。変数名numを使用すると、元の名前を使用できます。
+0

'int'を' num'に変更し、ビルトインを壊すことについての注意を追加することがあります。 –

+0

@DavidCullen、よろしくお願いします。私はそれについて少し前から考えていましたが、私たちがここでやっていることは学習リソースを作ることなので、私は本当にそれを前もって取り組むべきだったのです。 –

+0

元の投稿でも変更しましたが、アドバイスありがとう – jotNewie

関連する問題