要するに
- escapeshellarg:引数を一重引用符で囲むために使用され、引数内の引用符をエスケープします。
- escapeshellcmd:シェルのメタ文字、つまり <,>,| をエスケープするために使用されます。等
お使いのバージョンの php がコマンドの実行を bash に依存していると仮定すると、bash のマニュアルからわかるように、
文字を一重引用符で囲むと、引用符内の各文字のリテラル値が保持されます。バックスラッシュが前にある場合でも、単一引用符の間に単一引用符が出現しない場合があります。
したがって、コマンドを作成する次の方法で十分であるという結論に達することができます。
$c = escapeshellcmd( $cmd ) . ' ' . escapeshellarg( $arg1 );
ただし、$c を exec、system、passthru などの関数のいずれかに渡す必要がある場合は、問題が発生する可能性があります。経験的な分析によると、これらの関数は一部の文字を評価できることが示されています。例として、これを試してください:
$cmd = 'echo';
$arg = 'TEST\0ING'; // Since we are using single quotes, \0 shouldn't be evaluated as a null byte char
$c = escapeshellcmd( $cmd ) . ' ' . escapeshellarg( $arg1 ); // echo 'TEST\0ING'
exec( $c . ' > output.txt'); // writes TEST without the ING to output.txt
exec 関数は '\0' をヌル バイト文字として評価するため、output.txt には '\0' までのデータのみが含まれます。これは、PHP 5.4.6 を実行する Ubuntu でテストされています。私の意見では、データの文字通りの意味が失われているため、これはバグです。そのため、シェルのメタ文字であるバックスラッシュ '\' もエスケープするため、完全な文字列に対して escapeshellcmd を使用する方が比較的安全です。
$c = escapeshellcmd( $cmd . ' ' . escapeshellarg( $arg1 ) );
exec( $c . ' > output.txt'); // writes TEST\0ING to output.txt
このアプローチの欠点は、他のメタ文字もエスケープされ、引数が渡されるプログラム ($cmd) によってエスケープ解除する必要があることです。
完全なコマンド文字列で escapeshellcmd を使用しなかったことに注意してください。「>」がエスケープされないように、「> output.txt」の部分を省略しました。
結論:
コマンドライン引数として文字列を渡さないようにしてください。代わりに、データをファイルに書き込み、ファイルから読み取ります。このようにして、渡されるデータが変更されていないことを確認できます。
文字列をコマンドライン引数として渡す必要がある場合は、常に英数字であることを確認してください。
文字列をコマンド ライン引数として渡す必要がある場合は、完全な文字列に対して escapeshellcmd を使用する方が比較的安全です。