简而言之
- escapeshellarg:用于将参数用单引号括起来,并转义参数中的引号。
- escapeshellcmd:用于转义shell元字符,即<,>,| ETC
假设你的 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 相对更安全,因为它还转义了作为 shell 元字符的反斜杠 '\':
$c = escapeshellcmd( $cmd . ' ' . escapeshellarg( $arg1 ) );
exec( $c . ' > output.txt'); // writes TEST\0ING to output.txt
这种方法的缺点是其他元字符也将被转义,并且必须被传递参数的程序($cmd)转义。
请注意,我们没有在完整的命令字符串上使用 escapeshellcmd。我们省略了“> output.txt”部分,这样“>”就不会被转义。
结论:
尽量避免将字符串作为命令行参数传递。相反,将数据写入文件并从文件中读取。通过这种方式,您可以确保传递的数据保持不变。
如果您绝对需要将字符串作为命令行参数传递,请始终确保它们是字母数字的。
如果您绝对需要将字符串作为命令行参数传递,则对完整字符串使用 escapeshellcmd 相对更安全。