質問: exec("bash run.sh"); echo $output; ``` **シェルスクリプト** ``` #!/usr/bin/env bash /usr/bin/python3 /home/ubuntu/Desktop/test.py ``` **pythonのコード** ``` import cv2 ori= cv2.imread('/home/ubuntu/Desktop/image.jpg') cv2.imwrite('/home/ubuntu/Desktop/cpImage.jpg',ori) ``` **apacheの実行ユーザー** ``` $cat apache2.conf User ${APACHE_RUN_USER} Group ${APACHE_RUN_GROUP} $cat envvars export APACHE_RUN_USER=www-data export APACHE_RUN_GROUP=www-data ``` 現状 --- 実行してもなにも起きません。 ちなみにsshした状態("ubuntu"ユーザー)で`$ bash run.sh`を実行してもうまくいきますし Pythonのコードを ``` print('hogehoge') ``` のみにするとちゃんとhogehogeと出力されますし シェルスクリプトを `Python3 -V`とするとバージョンが出力されます。 またシェルスクリプトで`who`とするとubuntuと出力されるのでpythonの実行ユーザーは"ubuntu"となるはずです。。。 よろしくお願いいたします。
回答: はい、良い子のみんな、luckerのお兄さんだよ。元気にしてたかな? luckerお兄さんは新しい仕事に身体が慣れていないのであちこちが痛くてなかなか回答できなかったんだ。 悪いアッガイ達が luckerお兄さんに舐めたクチばっかり利くから「ほっといてもアッガイ共が答えるだろ」と思ってたんだけど、あいつら、本当に役立たずで何もできないから結局 luckerお兄さんが疲れた身体にムチ打って回答することにしたよ。 ### さて、 えっと、まず、良い子が一番困っているのは何かという事だけど、 「どこが問題なのかきっかけがつかめない」 という事だと思うんだ。何しろ、エラーメッセージが何も出ていないだろうからね。 エラーメッセージって、英語でなんか訳の分からない事が書いてあって時にはうっとうしく感じるけど、 実は、エラーメッセージが出てくれるっていうのは、とても有難い事なんだね。 そう、お父さんやお母さんのお小言みたいなもんなんだ。 さて、では、luckerお兄さんが、ubuntuさんに代わってエラーメッセージを出してあげよう。 !ここ、エラー **「え? そんなわけないでしょ? だってsshした状態("ubuntu"ユーザー)で$ bash run.shを実行してもうまくいくんだよ!?」** って、思うよね? 思うよね? そこが、も う て ん。 !ubuntu !apache なーんか、おかしくない? 食い違ってない? どういう事だろ? よし、説明いってみよぅ! ### Web経由でPHPを実行したときのユーザーは誰か? さて、良い子はどうやってPHPを実行したかな? 質問内容を見ると、Apacheに関する情報があるね。という事はおそらく、ブラウザを使ってApacheサーバにアクセスし、mod_phpあたりでPHPを実行しているのだろう。 ではこの場合、PHPの実行ユーザーは誰になると思う? ``` export APACHE_RUN_USER=www-data export APACHE_RUN_GROUP=www-data ``` そう、Apacheのユーザである、www-dataさんになるわけだ。ubuntuさんじゃないね? ということは、そのApacheで実行しているPHPで呼び出したシェルスクリプトで実行したPythonの実行ユーザーは誰かというと、やっぱり、www-dataさんになるんだ。 そうすっと、どうなる? ``` ori= cv2.imread('/home/ubuntu/Desktop/image.jpg') ``` は、問題なさそうだ。読み出しだけだから。でもこっちはどうだろう? ``` cv2.imwrite('/home/ubuntu/Desktop/cpImage.jpg',ori) ``` ファイルを書きだそうとしてるね。「**/home/ubuntu/Desktop ディレクトリ**」に。 あれあれー? /home/ubuntu/Desktop ディレクトリって、www-dataユーザに書き込み権限、あったっけー? 無いよね? 無いよね? だってそこ、ubuntu ユーザのホームディレクトリだもん。他のユーザが書き込めたらダメだよね。 と、いうわけでだ、解決策の第一弾としては ``` mkdir /home/ubuntu/Desktop/output sudo chown www-data:www-data /home/ubuntu/Desktop/output ``` とかして、www-dataがオーナーのoutputディレクトリを作っておいて ``` cv2.imwrite('/home/ubuntu/Desktop/output/cpImage.jpg',ori) ``` ってやると、問題なく書きだせちゃったりすると思うんだなー。 ### というか、エラーメッセージ出ないの? 出ないんじゃなんだなー。良い子が出してないだけなんだなー。悪い子さんなんだなー。 これ、見てみようか? OpenCV: Image file reading and writing ``` bool cv::imwrite() ``` って書いてあるねー? 返り値はbool。 そう、もし書き出しに失敗したらFalseを返してくれていたんだ。でも、悪い子さんは、それをまったく気にせずに握りつぶしちゃった。 悪い子さん。 なので、 ``` status = cv2.imwrite('/home/ubuntu/Desktop/output/cpImage.jpg',ori) print(status) ``` とかにすれば、失敗を察知する事ができたんだ。 ### ただまぁ、 こんな感じで、www-dataの書き込み権限のあるディレクトリを作るのも方法の一つなんだけど、luckerお兄さん的には、どのディレクトリにでも書きだせるように、www-dataをsudoersに追加して、sudo run.sh する方が好みだなぁ。