• 締切済み

popen について

popen() を使いこなせるようになろうとしているのですが、少し難しくてつまづいています。この関数は基本的に、指定したスクリプトをバックグラウンドで実行させるためのもの、と考えてよろしいでしょうか? マニュアルを読んでわからなかった言葉があります。「パイプ」「片方向ストリーム」 なのですが、検索して、パイプはなんとなく出入力先のポートだということが書いてあったのですが、いまいちピンときません。パイプを経由することで生まれるメリットのようなものはあるのでしょうか? 次に、ファイルポインタなのですが、スクリプトを実行させるのになぜこれが必要になるのでしょうか?おそらくほとんどのスクリプトがファイルの先頭にポインタを置く必要があると思うのですが、例えば'a'などとして、最後に置くとスクリプトが実行されなくなったりしませんでしょうか? 現在の理解度では popen("php -f $script", "r"); exec("php -f $script > /dev/null &"); の違いがわかりません。どちらも$sriptをバックグラウンドで実行してくれますが、マニュアルに記載されているファイルポインタの指定とパイプのオープンがもたらす決定的な違いなどどのようなものになるのでしょうか? また、popen()使用後に、pclose() で閉じないでいるとどのようなことが起こるのでしょうか? たくさんありますが、ひとつでもお分かりになるかたおられましたらどうぞよろしくお願いいたします。

  • jyuu
  • お礼率83% (553/665)
  • PHP
  • 回答数2
  • ありがとう数2

みんなの回答

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.2

すみません。他の言語とごっちゃになってました。 execも第二引数を使えば起動したプロセスの出力を取れますね。 ただ、popenの場合一行分もしくは指定バイト数読み取れば いったん戻ってきますが、execの場合は起動したプロセスが終了するまで 制御が戻ってこないと思われます。 pcloseで始末しなかったときの起動プロセスの後始末ですが、 プロセスIDがわかればシグナル送って強制終了とかできると思いますが (PHPの組み込み関数でその手のものがあるかどうかは知りません)、 ゾンビプロセスとなってとどまり続けてしまうのではないでしょうか? PHPのマニュアルを再確認してみましたが、外部プログラムを起動する関数が exec passthru popen proc_open shell_exec system とたくさんありそれぞれ微妙に違うのでややこしいこと極まりないですね。

jyuu
質問者

お礼

結局popen() とexec() の違いがわからずじまいになってしまったのですが、それはそれでいつか理解できる時まで保留させようと思います。ありがとうございました。

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.1

この辺はUNIXでのCプログラミングの経験がないと わかりづらいかもしれませんね。 > popen("php -f $script", "r"); > exec("php -f $script > /dev/null &"); > > の違いがわかりません。 popen の嬉しいところは起動したプロセスの標準入力に データを送ったり、逆にプロセスの標準出力からデータを 受け取ることができるところにあるので、この例ではpopenを使う意味がないです。 ファイルポインタはデータのやり取りの際に使います。それとpopenの指定で "a"は使えなかったはずです。 たとえばあるディレクトリにあるファイル名を得たいとして、 $ifp = popen("/bin/ls", "r") while (!feof($handle)) { $item = fgets($ifp) echo '<li>' . $item . '</li>' } ということができます。 execでは直接にはできませんよね? > popen()使用後に、pclose() で閉じないでいるとどのようなことが起こるのでしょうか? pclose() で最期を見取ってやらないと起動したプロセスが 終われません。

jyuu
質問者

お礼

>execでは直接にはできませんよね? 直接的というのはどういうことなのでしょうか? <?php exec('ls', $output); foreach($output as $line) { echo '<li>' . $line . '</li>'; } ?> 教えていただいたコードがそのままでは動きませんでしたので修正いたしました。 <? $ifp = popen("/bin/ls", "r"); while(!feof($ifp)){ $item = fgets($ifp); echo '<li>' . $item . '</li>'; } ?> この場合、pclose をしていないのですが、プロセスがそのまま残っているということでしょうか?では exec() ではそのような心配はしなくてよいのでしょうか?ほったらかしにしてしまったプロセスを終了させる方法などありますでしょうか?

関連するQ&A

  • popen は pclose しないといけない?

    fopen はPHPの実行終了時に自動的に fclose してくれると聞きますが、 popen は、pclose しないといけない(自動的に閉じられない)でしょうか?

    • 締切済み
    • PHP
  • Rubyのpopen3について

    はじめまして Rubyをはじめて1か月の初心者です。 popen3を使用するにあたって大変困っております。 popen3で外部コマンドを実行して、実行結果の標準出力をファイルとして格納しようと思っています。 外部コマンドの内容は、SSH接続でサーバへログインし、そこにあるシェルスクリプトを実行させるもので、 呼び出すシェルスクリプトに対して、Rubyから標準入力を渡し、シェルスクリプトが標準入力を受け取り、 それをもとに呼び出したシェルスクリプトがさらに別のシェルスクリプトを呼び出し、実行結果を標準出力としてRubyで受け取ってファイルに格納したいと思っています。 ソースとしては、以下のようにしてますが、標準入力を引き渡す方法が分かりません。 その為、標準入力を引き渡す部分は記述していません。 Open3.popen3('ssh localhost sh test.sh ') do |stdin, stdout, stderr|   begin    loop do     IO.select([stdout,stderr]).flatten.compact.each { |io|      if stdout != "" then       stdout_lines = stdout        puts("stdout_lines = " + stdout_lines)      end      stderr_lines = stderr if stderr != ""      puts("stderr_lines = " + stderr_lines)     }     break if $stdout.classed? && $stderr.closed?   end   rescue EOFError   end end JRubyの1.6.8なので、Rubyのバージョンは1.8.7相当です。 なにぶん初心者の為、なにをどうすれば良いか分からない状態です。 まず、実現が可能かを知りたいです。 実現可能であれば、標準入力を引き渡す方法を教えていただきたく。 よろしくお願いします。

  • UNIX関数?(popen)について

    Cプログラムでpopen関数?を使用しコマンド(rcp)を実行するプログ ラムを造ったのですが、当分が動作していたのですが、何のタイミングか分からないのですが、失敗する時が有ります。一度失敗するとそれ以降はずーと失敗します 。どのような原因が考えられるのでしょうか? ちなみにプログラムの一部をとりあえずのせておきます。(ファイル名及び相手先 のディレクトリ名は現状存在します) 又、system関数とpopen関数の大きな違いは何でしょうか? ご教示お願い致します。 (cプログラムの一部) char buff[256] ; char cmnd[256] ; /* コマンド文字列 */ int fp_rtc ; memset( buff, NULL, sizeof(buff) ) ; memset( cmnd, NULL, sizeof(cmnd) ) ; strcpy( buff, argv[1] ) ; sprintf(cmnd, RCP_FMT , buff, RCP_DIR, buff ) ; printf( "rcp cmnd ( %s )\n", cmnd ) ; fp = popen(cmnd, "r") ; fflush(stdout) ; fp_rtc = pclose(fp) ; if ( fp_rtc != 0 ){ printf( "pclose err [ rtc:%d ] \n", fp_rtc ) ; }

  • _popen() のエラー取得

    WindowsNT/2000で_popen()を利用してコマンドを実行しているのですが、その際のメッセージを取得したいのですが、通常のメッセージは取得出来るのですが、エラーメッセージが取得出来ません。どうすればよいのでしょうか? 現在のソースは下記のようです。 int main(int argc, char* argv[]) { char str[512],*ptr; FILE *fp; if((fp = _popen("dir b:","rt")) == NULL) { fprintf( stderr , "error!!!\n"); return -1; } while(1) { fgets(str,512,fp); if(feof(fp)) { break; } ptr = strchr(str,'\n'); if(ptr != NULL) { *ptr='\0'; } printf("%s\n",str); } _pclose(fp); return 0; }

  • popen使用時の実行速度

    お世話になります。1000以上のファイルがあるディレクトリを再帰的に走査するのに、 fp = _popen("dir /s /b *.jpg", "r"); while (fgets(fn, sizeof(fn), fp) != NULL) { //処理内容 } _pclose(fp); のようにしました。ここでint型の変数をインクリメントして100毎に表示させて実行速度を確認すると、明らかに後になるほど速度が低下していました。 タスクマネージャーで確認しましたが、メモリも一定でメモリリークを起こしているわけでも無いようです。 原因は何でしょうか?

  • [cakePHP]外部ファイルの実行方法

    過去の質問や他サイトを参考にしても実行できなかったので、ここに質問させていただきます。 cakePHPを用いてa.ctpからb.ctpにredirectする処理の裏で別の処理を実行させるという、いわゆる非同期処理を試しています。 具体的に言うと、DBを更新する処理を書いたhoge.phpを外部ファイル実行しているものです。 その外部ファイル実行時のコマンドで悩んでいます。 「exec("php C:/hoge/hoge.php > /dev/null 2>&1")」  や 「popen('start /B cmd /c "C:/pleiades/xampp/php.exe C:/hoge/hoge.php > /dev/null 2>&1"',"r")」 などいくつか試してみたのですが実行されていません。 DB更新処理自体は、hoge.phpを単体で動かして動作確認が取れたので問題無しと考えます。 質問としては、 ・execないしpopenのコマンドの書き方はこれでいいのか。 ・そもそも外部ファイル(hoge.php)は上記のように自由な場所に置いていいのか。 となります。 どうかご教授ください。 よろしくお願いいたします。

    • 締切済み
    • PHP
  • phpからサーバー上のcronにジョブ登録したい

    プログラミング初心者です。 【ウェブブラウザでphpファイルを開くと、レンタルサーバーのcronにジョブ登録される】ようにしたいのですが、上手く行きません。 下記記述に不備はありますでしょうか? <?php $cron = popen("/usr/bin/crontab -", "w"); $line = "51 22 13 11 * /usr/bin/php /home/userid/public_html/絶対パスでファイルの場所/ファイル.php"; fwrite($cron, $line); pclose($cron); ?> ※テストとして 11/13 22:51 に実行するような記述をしていました。 諸々検索もしたのですが、レンタルサーバー上にphpでジョブ登録するような事例がなく… お力添えください。宜しくお願い致します。

    • 締切済み
    • PHP
  • includeとinclude_onceの使い分け

    まずマニュアルを。 ------------------------------------------------------ PHP: include_once - Manual http://www.php.net/manual/ja/function.include-once.php include_once 命令は、スクリプトの実行時に指定したファイルを読み込み評価します。この動作は、include 命令と似ていますが、ファイルからのコードが既に読み込まれている場合は、再度読み込まれないという重要な違いがあります。その名が示す通り、ファイルは一度しか読み込まれません。 include_once は、スクリプトの実行時に同じファイルが複数回読み込まれ、評価される可能性がある場合に、関数の再定義や 変数値の再代入といった問題を回避するために一回だけ読み込ませるために使用します。 ------------------------------------------------------ …。表面的な機能の違いはわかりました。しかしそれをどう使い分けるのかの説明はなく、分かりませんでした。 よく分からない点は以下です。 ・同じファイルを何度も「include」もしくは「include_once」するケース ・あえて何度も記述しながら実際には1度しか評価してほしくないケース ・何度も記述して、そのつど評価したいケース これらについて例を挙げて教えていただきたいです。 よろしくお願いします。

    • ベストアンサー
    • PHP
  • PHPでexecやpassthruすると

    execやpassthruで実行した実行プログラムが終了するまで待たされると思いますが バックグラウンドで実行する方法はあるでしょうか? PHPはその行で止まらずに実行プログラムとは別に以降の行を実行するということです 要するにexecは実行プログラム実行のトリガーをかけるだけにしたいのです もしあったら具体的に数行以下のコードで教えてください よろしくお願いします

    • ベストアンサー
    • PHP
  • phpのshell_exec関数の動作に関する質問です。

    phpのshell_exec関数の動作に関する質問です。 環境はFreeBSD7.1 php5.2.13です。 もともとperlスクリプトtest.cgiがあって、 /path/test.cgi filea fileb (以後これをコマンドラインという) というコマンドラインが正常に実行されることが確認済みです。 このコマンドラインが実行されるとfilebの内容が変化します。 次にphpスクリプトからコマンドラインを実行するために test.phpスクリプトの途中に、 shell_exec("/path/test.cgi $filea $fileb"); と書きました。 (test.cgiではperlライブラリを読み込んでいます。 phpには同等のライブラリがないためにやむを得ずこうしています。) ところがtest.phpを(ブラウザから)実行しても コマンドライン実行後に期待される$filebの変化がありません。 つまりコマンドラインが実行された形跡がないのです。 test.phpスクリプトの$filea, $filebが正しく変数展開されていることは確認済みです。 FireFoxブラウザから見るとtest.phpスクリプトは特にエラーもなく正常に実行されているように見えます。 質問 1 正常に実行できるコマンドラインをphpのshell_exec関数で実行できない理由としてどのようなことが考えられるでしょうか。

    • ベストアンサー
    • PHP

専門家に質問してみよう