0

以下の CGI スクリプトで Python からシェル コマンドを実行しようとしています。シェルでスクリプトを実行するときと、Web ブラウザーから実行するときの理由をexit_status説明してもらえますか? 前もって感謝します。また、 (例)のようなサブプロセスを試すと、ターミナルで実行すると終了ステータスはゼロになりますが、ブラウザで実行すると終了ステータスが表示されます。私は本当に困惑しています...0exit_status127echo somethingexit_status = subprocess.call('echo something', shell=True)500 Internal Server Error

#!/usr/bin/env python

import subprocess

print 'Content-type: text/html\n\n'  
print '<html><head>'
print '</head><body>'

exit_status = subprocess.call('ls', shell=True)

print exit_status

print '</body></html>'
4

1 に答える 1

2

@abarnert がコメントで述べたように、shell=True選択の余地がない場合 (たとえば、システム シェルの拡張機能が絶対に必要な場合) を除き、使用は通常避けるべきです。サブプロセスドキュメントのこのセクションとして説明によると、シェルを使用すると、コマンド (引数を含む) が外部ソース (フォーム送信など) から取得される場合に、さまざまな深刻なセキュリティ問題が発生します。これらの問題に加えて、シェルがホスト システム上で正しく構成されていることも信頼していますが、これは、Web サービスに使用されるような特別なユーザーにとって常に安全な仮定ではありません。セキュリティ ホールに加えて、直接実行できるコマンドを実行するためだけに余分なシェル プロセスを fork するのも無駄です。また、プラットフォームが異なればコマンド文字列に適用される展開や規則も異なるため、システム シェルに依存することで移植性が損なわれている可能性があります。

. _ subprocess_ shell=Falseすべてのプラットフォームで必要なわけではありませんが、確かに Linux では必要なため、コードの移植性が向上します。さらに、引数を自分で分割することで、シェルへの引数のエスケープやクォートを忘れるという事故の可能性を回避できます。

また、@ababert は、CGI 環境で必ずしもPATH正しく設定されているとは限らないことを正しく説明しているため、すべてを絶対パス名で参照することをお勧めします。繰り返しますが、これは通常、さまざまなプラットフォームや環境への移植性を高めるための優れた方法です (もちろん、バイナリへのパスをハードコーディングすることは既に移植性の妨げになっていますが、少なくとも問題を最小限に抑えることができます。このコードを移植する必要があります)。

これを考慮するlsと、例とecho例は次のようになります。

exit_status = subprocess.call(['/bin/ls'])
exit_status = subprocess.call(['/bin/echo', 'something'])

また、多くのシェルechoが実際のコマンドをオーバーライドするビルトインとして扱うという事実によって多少混乱していますecho-絶対パスで参照すると(つまり/bin/echo)、ビルトインではなく実際のコマンドを使用するように強制されます。

CGI スクリプトとして実行している場合、通常、内部サーバー エラーは、キャッチされていない Python 例外が発生したことを意味します。Web サーバーのログ ファイルを調べると (それらにアクセスできると仮定して)、例外の全文を見つけることができますが、これはサーバーによって異なります。なしで実行すると、実行する実行可能ファイルが見つからないときに例外が発生するのではないshell=Trueかと思います。OSErrorシェルで実行すると、例外は発生しません。シェルのエラー メッセージとともに標準エラーに出力されるだけです。繰り返しますが、これはログに複製されます。例外が発生した場合は、有効なログインシェルが指定されていないために実行しているユーザーが原因であると思われます-一部の構成では、次のようなユーザーとしてスクリプトを実行します/bin/falseアカウントの悪用を避けるため、ログイン シェルとして使用します。これが事実である場合では1なく、リターンコードを期待します。127

つまり、Web サーバーのエラー ログに記録された情報を確認します。ベスト プラクティスはshell=True、空白で区切られた文字列ではなく、すべてのコマンドを引数のリストとして指定することを避け、確認することです。ログからさらに情報を取得してここに投稿できる場合は、回答を更新してより具体的なヘルプを提供できます。

fork()最後に、可能な限り、Web サーバーで使用するコードは避けます。これにはsubprocess. ls回避する方法がない場合もありますが、代わりに Python 関数を使用できるなどの単純なことには確かに (os.listdir())。標準の CGI スクリプトとして実行している間はおそらく問題ありませんが、コードをより効率的なホスティング環境 (mod-wsgi、fastcgi など) に移植する予定がある場合は、外部プロセスの生成に十分注意する必要があります。発生するファイル記述子およびその他のリソースの重複の。安全に実行できないと言っているわけではありませんが、将来的に紛らわしいバグの原因となる可能性があるため、可能であれば回避したいと思います. これは、Web 要求を処理するために外部プロセスを生成することの相対的な非効率性は言うまでもありません。これは、コードのスケーリングを計画している場合に問題になる可能性があります。

于 2013-01-23T10:59:20.660 に答える