時々、Webサーバからシェルのコマンドを呼び出したくなることがあります。 例えば、GraphVizでグラフを自動生成してWebページに貼り付けたい場合、 内部的にはdot
コマンドが実行されます。 おそらく、現実的にはPerlのGraphViz
モジュールを利用するなど、 外部ライブラリを使ってPerlなどのスクリプトを書いて実装すると思いますが、 内部的にはdot
コマンドが呼び出されているはずです。
さて、シェルから実行したときと同じように動作すれば問題ないのですが、 必ずしもコマンドラインからの実行と同じようにWebサーバからコマンドを呼び出せるとは限りません。 理由は、Webサーバの環境変数PATH
が普段のシェルの実行環境と同じとは限らないからです。 例えば、自分のFreeBSDのユーザ環境でのPATH
の中身は、
/sbin:/bin:/usr/sbin:/usr/bin:/usr/games:/usr/local/sbin:/usr/local/bin
となっています。 一方、Apacheの環境変数PATH
の中身は、
/sbin:/bin:/usr/sbin:/usr/bin
と、シェルの実行環境と異なります。 例えば、FreeBSDにGraphVizをpkg
経由でインストールすると、 dot
コマンドは/usr/local/bin/dot
にインストールされます。 すると、通常のシェルからはpathが通っているので、問題なくdot
コマンドを呼び出すことが出来ますが、 ApacheのWebサーバからはpathが通っていないので、単純には呼び出せません。
最も単純な解決方法は、Webサーバ上のpathが通っているディレクトリに 使いたいコマンドへのシンボリックリンクを張ることが挙げられます。 例えば、/usr/bin
に/usr/local/bin/dot
のシンボリックリンクを張ることで、 Webサーバからdot
コマンドを実行できるようになります。
ln -s /usr/local/bin/dot /usr/bin
しかし、簡易的なプログラムのためだけに、シンボリックリンクを張りたくない場合や、 MacのSIP(System Integrity Protection)のように、root権限でも特定のディレクトリを変更できない場合、 Apacheの環境変数PATH
を書き換える必要があります。
Apacheの設定ファイルに、以下の内容を記述することでpathを変更します。
SetEnv PATH /path/to/target/dir:${PATH}
.htaccess
ファイルに記述することで、記述した設定ファイルの存在するディレクトリ以下のpathを変更出来ます。 例えば、/usr/local/bin
をPATH
に加える場合は以下の通りになります。
SetEnv PATH /usr/local/bin:${PATH}
純粋にシェルコマンドをWebから使うことはそこまで多くないとは思いますが、 GraphVizをPerlのモジュールから利用するように、プログラマが意識しないところでコマンドを呼び出すことは意外とあるのかもしれません。 基本的にはシンボリックリンクを張ればおそらく解決すると思いますが、Macみたいに、 ディレクトリが保護されている場合は、環境変数を書き換えられると解決出来ると思います。 実際に、MacでGraphVizを使って自動生成したグラフを張るCGIプログラムを動かそうとして、 なかなかうまく動かなくて悩んでいましたが、Apacheの環境変数PATH
を書き換えて解決しました。 多分、Nginxでも同じようなことは出来ると思います。Nginx使ったことないけど... そんな感じで、今回はここまで。