[英]sed doesn't work with PHP exec function
echo "sed -i 's/NULL/\\N/g' ".$_REQUEST['para'].".sql";
上面的语句有效。 但是当我像这样在exec中使用它时会失败...
exec("sed -i 's/NULL//\/\/\N/g' ".$_REQUEST['para'].".sql");
您应该使用反斜杠而不是正斜杠来转义反斜杠,如下所示:
exec("sed -i 's/NULL/\\\\N/g' ".$_REQUEST['para'].".sql");
编辑我写了答案,而没有看代码实际做什么。 不要这样做,因为$_REQUEST['para']
可以是用户想要的任何东西,可以用于代码注入 。 另一个答案建议使用PHP函数。
尽管完全取决于您,但是我的建议是不要不必要地调用系统命令。 在PHP中,可以使用preg_replace()来执行sed的功能。
preg_replace("/NULL/","\\N",file_get_contents("$_REQUEST['para']"."sql") )
基于ghostdog的想法,下面的代码实际上可以完成您想要的操作(他发布的原始代码实际上并未读取文件的内容):
//basename protects against directory traversal
//ideally we should also do a is_writable() check
$file = basename($_REQUEST['para'].".sql");
$text = file_get_contents($file);
$text = str_replace('NULL', '\\N', $text); //no need for a regex
file_put_contents($file, $text);
但是,诚然,如果所涉及的文件超过几个兆,则不建议这样做,因为整个文件将被读入内存。 您可以分块阅读它,但是会变得更加复杂:
$file = basename($_REQUEST['para'].".sql");
$tmpFile = tempnam("/tmp", "FOO");
$in = fopen($file, 'r');
$tmp = fopen($tmpFile, 'w');
while($line = fgets($in)) {
$line = str_replace('NULL', '\\N', $line);
fputs($tmp, $line);
}
fclose($tmp);
fclose($in);
rename($tmpFile, $file);
老实说,如果文件是100+兆,那么像您一样直接调用sed会更快。 当涉及到大文件时,尝试重现sed / grep之类的工具(与PHP等效)的开销实在不值得。 但是,如果要这样做,您至少需要采取一些步骤来保护自己:
采取一些基本步骤来保护amnom的代码:
$file = basename($_REQUEST['para'].".sql");
if(!is_writable($file))
throw new Exception('bad filename');
exec("sed -i 's/NULL/\\\\N/g' ".escapeshellarg($file));
/etc/passwd; rm -rf /; #
/etc/passwd; rm -rf /; #
/etc/passwd; rm -rf /; #
,您将得到命令sed 's/blah/blah/' /etc/passwd; rm -rf /; #.sql
sed 's/blah/blah/' /etc/passwd; rm -rf /; #.sql
sed 's/blah/blah/' /etc/passwd; rm -rf /; #.sql
。 应该清楚的是,尽管该精确命令可能不起作用,但是找到实际上可以执行的命令却微不足道。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.