アルパカログ

Webエンジニアでマネージャーな人がプログラミングやマネジメントの話題を中心に書いているブログです。

Python シェルコマンドを安全にパイプして実行する

f:id:otoyo0122:20200812201531p:plain:w300

Python3でシェルコマンドを実行するにはsubprocessモジュールを使います。

シェルコマンドをパイプして実行する方法を検索すると、shell=Trueとして'command1 | command2'のように文字列で渡す例がよく出てきます。

しかしこの方法には、セキュリティ上考慮すべき点があることを忘れてはなりません。

shell=True でシェルを明示的に呼びだした場合、シェルインジェクション の脆弱性に対処するための、すべての空白やメタ文字の適切なクオートの保証はアプリケーションの責任になります。

このエントリではshell=Falseとしながら、安全にシェルコマンドをパイプして実行するコード例を紹介します。

良くない例(shell=True)

echoしたテキストをjumanppコマンド(形態素解析システムJuman++)で形態素解析するコードを例に説明します。

まずはshell=Trueの方から。

from subprocess import Popen, PIPE

command = "echo '" + sentence.replace("'", "\'") + "' | jumanpp"
proc = Popen(command, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE)
stdout, stderr = proc.communicate()

良い例(shell=False)

これをshell=Falseにするには次のように書きます。

from subprocess import Popen, PIPE

p1 = Popen(['echo', sentence], stdout=PIPE)
p2 = Popen(['jumanpp'], stdin=p1.stdout, stdout=PIPE)
p1.stdout.close()
stdout, stderr = p2.communicate()

以上です。

参考になった方は、ぜひ「はてブ」やSNSでシェアしていただけると嬉しいです。

参考文献