- ベストアンサー
PHPでunzipコマンドを実行する際のエラー検出方法
- PHPでunzipコマンドを使用してファイルを解凍する際、disk fullのエラーを検出する方法について教えてください。
- unzipコマンドを使用してファイルを解凍する際、標準出力を使用して解凍結果を取得していますが、disk fullのエラーを検出することができません。
- 解凍結果の出力ファイルが0バイトであるため、エラーとして検出することも検討しましたが、具体的なエラー内容がわからないため困っています。どなたか解決策を教えてください。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
ああああああああああ そうですね、ディスクフルを書き込んで検出できるわけが無いですね。 なんかパラドックス的な事になってますね・・・ 方法は無くもないですが、、 unzip-5.5.2: --- fileio.c(1154): /* Function disk_error() */ fileio.c(1174): } /* end function disk_error() */ --- にディスク依存しない独自のエラールーチン仕込むとか。。。 しかし、やはり標準出力でディスクに書き込んでいる点で、詰んでるように思えます。 ですので、 --- ロックファイルを作ってロック ユニークなテンポラリディレクトリを作成 書庫ファイルを作製したディレクトリへ移動 proc_open()等で、unzipコマンドで普通に解凍 標準出力を確認してメッセージ確認 proc_close()等で戻り値確認 解凍されたファイルを任意のファイル名にリネームして元の位置に移動 テンポラリディレクトリを削除 ロックファイルのロックを解除 --- とかそういうカンジになるのではないですかね~ あとは出力先をディスクフル検出可能なデバイスにするとか。 もう1つ、根本的な解決にはならないとは思いますが、 zipファイルの仕様として、ファイルサイズのエリアが4バイト=32ビット、 zipファイルに格納できる最大ファイルサイズは約4GB(4294967296 bytes)なので、 解凍先ディスクが4GB+α(例えば適当に10GBくらい)を下回っていたら、 それをもってディスクフルとみなす、という策があります。 1TBとか普通の時代なので10GBくらいはいけるんじゃないでしょうか --- 潜在的にディスクフル問題を抱えているアプリは結構あるので、 本当にディスク容量が無くなってしまうと他のアプリでも挙動がおかしくなりそうです
その他の回答 (3)
- 城戸 誠(@kido_makoto)
- ベストアンサー率32% (21/65)
># unzip -c hoge.zip 1> fuga.txt > >と、標準出力オプションを与えて実行し、disk fullを発生させた場合は、何もエラーは出力されませんで >した。これは、お教えいただいた方法でも、おそらく検知できないことを示すのではないかと思いました。 エラーは通常、標準エラー出力に出力されます。 参考URLに詳しく載ってますので見てみてください。 抜粋: --- ●sh・bash の場合 まず、 標準出力は 1 番 標準エラー出力は 2 番 ということを覚えてほしい (ちなみに標準入力は 0 番)。 --- 私は「>&」でまとめちゃいますけど(理由なし)w # unzip -c hoge.zip 2> fuga.txt で試してみてください。
お礼
早速のご回答ありがとうございます。 失礼しました、コマンドの例の表記に、標準エラー出力を記載し忘れておりました。試したコマンドは、正しくは以下の通りです。 # unzip -c hoge.zip 1> fuga.txt 2> piyo.txt この状態で、disk fullが発生した場合の結果としては、 fuga.txt: 途中で途切れたデータが出力される piyo.txt: 何も生成されない 実行直後の # echo $? の戻り値は ゼロ を返す となりました。おそらく、エラー出力する時点では、disk full状態のために出力される領域がないので、生成できないのだろうと考えております。 また、補足になりますが、PHP上からexecコマンド等で実行した場合は、 $command = "unzip -c -qq hoge.zip 1> fuga.txt 2> piyo.txt"; $ret = exec($command, $output, $return_var); $ret: 空文字 $output:空の配列 $return_var:0 出力先ファイル:ゼロバイトのファイルが生成される エラー出力ファイル:ゼロバイトのファイルが生成される と、少々異なった結果となりました。PHP側である程度の不正なファイルハンドリングを監視しているのだろうと思いますが、エラー出力ファイルもゼロバイトという結果をみて、unzipコマンドが標準出力時に発生するエラーを関知していないのではないかと考えました。 標準出力をしている時点で、unzipがファイル書き込みのエラー検出の責任を放棄しているのは、何となくわかる気もしますが、別のプロセスでもかまわないので、システムとして何かしらのログなり、エラーを示す情報をはき出してくれていることを期待していたのですが、どうも見つけ出すことができませんでした。
- 城戸 誠(@kido_makoto)
- ベストアンサー率32% (21/65)
unzipでdisk fullになった場合、unzipあるいはunzip -vとかでエラーメッセージでますよね? それを、 --- CXV. 出力制御関数(output control) --- を用いてstdout/stderrへの出力を取得し、disk fullメッセージを確認すればよいのではないでしょうか?
お礼
ご回答ありがとうございます。 今回の質問のポイントの1つとして、できれば「unzipに標準出力オプション(-c)を使用した状態で、disk fullを検知したい」という、仕様上の縛りみたいなものがありました。これは、圧縮されている書庫内のファイルを、任意のファイル名に指定しながら展開したいという理由があったためです。(unzipコマンドには、そのような機能は見あたりませんでした) この標準出力オプションを使わなければ、仰るとおり実現可能だと思うのですが、たとえば直接コマンドライン上で、 # unzip hoge.zip と実行した際に、disk fullを起こした場合は、画面上にもそのエラー状況が表示されたのですが、これを、 # unzip -c hoge.zip 1> fuga.txt と、標準出力オプションを与えて実行し、disk fullを発生させた場合は、何もエラーは出力されませんでした。これは、お教えいただいた方法でも、おそらく検知できないことを示すのではないかと思いました。 ※直接実行して確かめることができていないので、推測になります。取り急ぎの回答で申し訳ありません。 しかし、いただいた方法は、エラーメッセージの取得に役立ちそうですので、有効利用させていただきたいと思います。おそらくこのままですと、標準出力を利用する方法はNGとなりそうですので(任意の名前で一時ディレクトリを掘ってそこに展開する方法に切り替えます)、その際に、教えていただいた関数を利用させていただきます。
-Z オプションを付けるか zipinfo を使って、先にファイルのサイズを調べてはいかがでしょうか。 同じことですが、Zip 拡張を利用してもサイズを調べることが出来ます。 http://www.php.net/manual/ja/book.zip.php http://www.php.net/manual/ja/zip.examples.php
お礼
ご回答ありがとうございます。 すみません、少々慌てて質問を投稿してしまったため、提供する 情報が足りていませんでした。 おっしゃるとおり、展開後のサイズを事前に確認することも 考えてはいたのですが、複数ユーザが同時にアクセスしたり、 他の処理が平行して走っていることを考慮すると、DISKの残容量が 事前の確認どおりにならない可能性が残ってしまいます。 とはいえ、このような間接的な回避方法(事前チェックなど)は 必須と考えており、実際に実装しておりました。 しかし、やはり何かの拍子にDISK FULLを起こした場合、直接的に そのエラー状態を検知できるのが、もっとも望ましいかなと考えて おりました。 また、補足ですが、一時ディレクトリを用意して展開することを 検討していると書きましたが、標準出力(-cオプション)を使用しな ければ、DISK FULLのエラーを、unzipコマンド自体が返してくれる という理由からでした。 その後、いろいろと調べてみましたが、どうやら、unzipコマンド に限らず、標準出力>ファイル保存によって、DISK FULLを起こした 場合のエラー検知は難しいようですね。。。
お礼
詳細なご回答、ありがとうございます。 1つ目のアドバイスについては、残念ながらCの知識に疎いため、よく理解ができませんでした。ただ、こういう独自のカスタマイズということが可能なんですね。参考になりました。 結論としては、仰るとおり、テンポラリディレクトリを作成する方法になりそうです。システムの仕様の都合上、できるだけこの方法は回避したいところでしたが、機能の安全性を確保するという命題が最優先ですので、標準出力でのエラー検出はあきらめようと思います。目的は、解凍先のファイル名にユニークなファイル名を使うことですので、それをディレクトリにやらせようと思います。 出力先を変更する方法については、すでに稼働中のシステムであることと、規模がそこそこ大きいためになかなか小回りや融通が効かず、使える策がかなり限られてしまうことなどで、なかなか難しいところです。 解凍ファイルサイズや使用率のチェックは、解凍処理直前に仕込みました。やはり、DISK FULLの発生自体を、できるかぎり回避すべきだと思いますので。 いろいろと、参考になるアドバイスをありがとうございました。おかげさまで、今回の件では、非常に勉強になりました。