[PHP] システムコマンドの返り値で失敗しないポイント

Pocket
LINEで送る
GREE にシェア
LinkedIn にシェア

こんにちわ。
 

ターミナルコマンドをこよなく愛している、下駄です。
 

本日も、IT謎掛けやってみます。
 

「ターミナルコマンド」とかけまして、
 

「独り身で寂しい人の見方」と、ときます。
 

そのココロは・・・
 

cat(catコマンドと、猫)を使えば、助かります。

PHPでシステムコマンドを叩く理由

サーバー・サイド言語は、サーバー内の操作をほぼなんでもできるようになっていますが、それでも、システムコマンドを実行した方が効率がいい場合が多々あります。
 

ただし、同じシステムで常に同じサーバーOSを使用する場合は問題ないのですが、開発段階は、ウィンドウズOSで、公開サーバーはLINUXという場合には、入力するコマンドが違ってくるので、システムコマンドを利用する場合は、そうした環境差分を注意しなければいけません。
 

もっと細かく言うと、システムコマンドそれぞれにも、バージョンが存在していて、そのバージョンが違う事で、結果が若干変わってきたり、上位互換や下位互換が担保されているとは限らないので、エラーが返ってしまうケースも稀にあります。
 

そうした事を十分理解している場合、PHPでシステムコマンドを利用する価値は大いにあります。
 

具体的に言うと、特定のデータフォルダ内に入っている画像ファイル(jpegファイルのみ)の一覧を取得したい場合、PHPで行うと・・・
 

 

通常、jpg拡張子だけを判別したい場合は、上記のように書きますが(もっと効率的に書く方法もありますが・・・)、
 

システムコマンドを利用すると、以下のような感じです。
 

 

lsコマンドって便利なんですね・・・
 

もちろん、PHPで関数を作ってプログラム本文を短くすることは可能ですが、決定的な違いは、そのスピードです。
 

phpのloop文(for文やforeach文やwhile文)のスピードとシステムコマンドのスピードは格段に違います。
 

数十件程度であれば、体感的にあまりかわらないのですが、1000個、1万個・・・となってくると、phpだけの処理では、遅くて仕方がない状態になります。
 

IOに直結することができる、システムコマンドって、クオリティ担保にも十分に役立てるんですね。

execを使っていて起きたトラブル

そんな便利なPHPのシステムコマンド連携ですが、ごく稀に、想定した返り値が得られない時があります。
 

というか、そんな事があって、プログラムバグにつながった事を経験したので、その話をしたいと思います。
 

それは、catコマンドなどを使って、テキスト内部の行の文字列を取得しようと思った時に、行の末尾に半角スペースが入っていると、execコマンドを通ると、勝手にtrim処理が掛かっていたという事件です。
 

サンプルプログラムを実行してみるとよくわかります。
 

 

ぱっと見で分かりづらいですが、4行目の末尾には、半角スペースが入っています。
 

“4,d,____”(半角スペースを_アンダースコアに変換してみました)
 

 

この状態で、見た目にはわかりませんが、行末の半角スペースが無くなっています。
 

※改行コードを”┘”に置き換えています。
 

もちろん、サーバー側で、実際にコマンドを叩いてみると以下の通りです。
 

 

5行目の先頭文字列にある半角スペースは残ったままになっているので、単純にtrimが実行されているのではなく、行末のみtrimされているようです。
 

ここからは、僕の推測ですが、execコマンドは、改行コマンドで分割されて、配列で受け取れるようになる特徴があるので、
 

改行コマンドを、¥nと¥rだけでなく、半角スペースで終わる行末も対象になっていると考えられます。
 

通常であれば、行末の半角スペースなどは、ファイル名でもあり得ないし、単語取得をしたい場合は、むしろ、trimしてくれて有り難いぐらいなのだが、文字列をきっちり取得したい場合は、この状態ではエラーになってしまいます。

passthruを使うと解決できる

そこで、phpには、execの他に、system関数や、shell_exec関数・・・などなど、たくさんのシステム関数連携機能を持っているのですが、
 

参考 : PHPはコマンド実行関数多すぎだろ

 

その中の”passthru”を使うことで解決できました。
 

書き方が少しめんどくさくなりますが、
 

 

“ob_start”や”ob_get_contents”と組み合わせて使うので少しめんどくさい書き方になりますが、確実に文字列をゲットできます。
 

便利だけど、めんどくさくて、重要な気付きでした・・・

Leave a Reply

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です