5

これは私を夢中にさせています。PHP Web アプリの Windows ボックスでコマンド ライン ステートメントを実行しようとしています。Windows XP、IIS5.1 で動作しています。Web アプリは正常に動作していますが、@exec() を特定の contactenated 変数で動作させることができません。私のコマンド構成は次のようになります。

$cmd = ($config->svn." cat ".$this->repConfig->svnParams().quote($path).' -r '.$rev.' > '.quote($filename));

このコマンドは、次の文字列を生成する場合、上記のようには機能しません。

svn --non-interactive --config-dir /tmp cat "file:///c:/temp/test/acccount/dbo_sproctest.sql" -r 1 > "C:\Inetpub\sites\websvn\temp\wsv5B45.tmp"

これを自分のコマンド ラインにコピーして貼り付けると、問題なく動作します。

変数を追加する代わりに、まったく同じパスをハードコーディングすると、機能します! ファイル名を引用符で囲んだり付けたりせずに試しました。コマンド全体を引用符で囲んだり付けたりせずに試しました。他のディレクトリを試しました。出力パラメーターを exec() に渡そうとしましたが、空に戻りました (Array () )。コマンドのエラー ストリームの出力をファイルにリダイレクトしようとしましたが、そのエラー出力ファイルは作成されません。

私が想像できる唯一のことは、 exec() が静かに失敗していることです。ここで一体何が間違っているのですか?同じディレクトリ構造とファイル名を使用してファイルパスをハードコードすると、正常に機能します。私がしなければ、そうではありません。

ファイルパスのスラッシュ () が適切にエスケープされていない可能性がありますが、単一引用符を使用して手動で行うと、エスケープシーケンスとは見なされませんか??

アップデート:

@ を exec から外しましたが、まだエラーは表示されません。

私はSVNへのフルパスを与えましたが、まだうまくいきません。catのファイル宛先を手動で指定する限り、コマンドは以前はフルパスではないSVNで正常に機能していたことに注意してください。

更新 2: RE: キース

両方を試して exec を呼び出しています:

exec($cmd);

また

exec($cmd, $out);

私のphp.iniにはすでにsafe_mode = 0がありました。

error_reporting(E_ALL); を追加しました。そして何も新しいものを見ませんでした

exec 呼び出しをエコー (または print_r) しても、実際には何も表示されません。

出力変数が含まれているときに exec 呼び出しをエコー (または print_r) すると、空の arr が返されます

アップデート 3

escapeshellcmd と escapeshellarg の両方を試してみましたが、役に立ちませんでした (ただし、良い考えです)。

呼び出しによってファイルが作成されていることを追加する必要があります

tempnam("temp", "wbsn");

文字列を tempname で生成するのではなく、手動で指定すると問題なく動作するという事実は、問題の原因を示唆しているようですが、方法がわかりません。手動文字列と生成された文字列を比較したところ、一致していました。

4

9 に答える 9

23

@exec@ は PHP のエラー抑制演算子であるため、常に暗黙のうちに失敗します。

于 2009-04-03T16:43:34.877 に答える
6

あなたがWindowsを使用していて、私がLinuxを使用しているので、これが役立つかどうかはわかりませんが、PHP exec()からのサイレントエラーという同じ問題に遭遇しました。発行しようとしたコマンド(nconvert)は、エラーメッセージを標準出力ではなく標準エラーストリームに送信することがわかりました。だから私は追加しました

2>&1

コマンドラインの最後で、エラーを標準ストリームにリダイレクトします。次に、nconvertが許可拒否エラーを表示していることがわかりました。

于 2010-02-16T17:28:33.130 に答える
2

PHPスクリプトとユーザーアカウントのPATHが同じではない可能性があります。@ を削除してみて、エラーをスローしようとしているかどうかを確認してください。

さらに、SVN 実行可能ファイルへの完全なファイルシステム パスを入力してみてください。

于 2009-04-03T16:42:46.187 に答える
1

shell execの問題をデバッグするときに非常に役立つトリックは、コマンドの先頭に「エコー」を配置することです。どこかで標準出力を表示できることを確認してください。

これにより、明らかな問題がないかコマンドを調べることができます。ワイルドカードが予期せず拡張されているか、シェルの引用が正確に正しくない可能性があります。エコーによってこれを確認できます。エコーされたコマンドを切り取って別のシェルに貼り付け、正しく機能しているかどうかを確認できます。

于 2009-08-01T16:52:52.127 に答える
1

exec() がまったく機能しているかどうかを確認するために、echo exec("dir") または簡単なものを試しましたか?

于 2009-04-03T19:37:32.243 に答える
1

何が起こっているのかわかりませんが、少なくとも回避策があります。

これは機能します:

$tmp = tempnam("./", "wbsn");
$filename = dirname($tmp).'\\temp\\'.basename($tmp);

ただし、これはそうではありませんが、同じパスが生成されると予想していました (新しい tempnam() であるため、差分ファイル名)。

$tmp = tempnam("temp", "wbsn");

また、これは機能しません。これも同じものを生成すると予想されます。

$tmp = tempnam("temp", "wbsn");
$filename = dirname($tmp).'\\'.basename($tmp);

これらの 3 つのソリューションはすべて同じファイル パスを生成するように見えますが、私の exec で使用すると実際に機能するのは最初のソリューションだけです。なぜそうならないのか、私にはわかりませ

これら 3 つすべてを目視検査 (エコー) すると、同じパスが生成されるように見えます (もちろん、ファイル名が異なることを除いて)。これら 3 つのそれぞれの dirname() の文字列比較は、一致として表示されます。取引が何であるかはわかりませんが、最初のものは回避策です。

于 2009-04-03T19:52:36.013 に答える
-1

私のアドバイスは、WIN、IISからLinuxに切り替えることですが、代わりにこれを試すことができます:

function exec_alt($cmd) {
    exec($cmd, $output);
    if (!$output) {
        /**
         * FIXME: for some reason exec() returns empty output array @mine,'s machine.
         *        Somehow proc_open() approach (below) works, but doesn't work at
         *        test machines - same empty output with both pipes and temporary
         *        files (not we bypass shell wrapper). So use it as a fallback.
         */
        $output = array();
        $handle = proc_open($cmd, array(1 => array('pipe', 'w')), $pipes, null, null, array('bypass_shell' => true));
        if (is_resource($handle)) {
            $output = explode("\n", stream_get_contents($pipes[1]));
            fclose($pipes[1]);
            proc_close($handle);
        }
    }
    return $output; }
于 2013-03-26T16:32:09.087 に答える