在 PHP 脚本中运行系统 bash 命令 - 语法错误:意外的 T_LNUMBER

在 PHP 脚本中运行系统 bash 命令 - 语法错误:意外的 T_LNUMBER

下面是我用 PHP 编写的脚本的摘录,但包含在bash.现在,这样做的原因是因为它允许我使用awk在我所遇到的场景中理想的功能。我正在尝试获取字符串的第四个或第五个元素(存储在$line),然后我计划使用它。但是,每当我使用下面的代码执行它时,都会出现以下错误:

PHP Parse error:  syntax error, unexpected T_LNUMBER, expecting T_VARIABLE or '$' in /home/hugh/HughScripts/ParseOutputForFieldsV2.php on line 16

第 16 行是我的第一个系统命令:

system("echo \"$line\" | awk '{$1=$2=$3=$4=""; print $0}'");

但是,由于我缺乏 PHP 和系统功能方面的专业知识,我不确定到底是什么导致了我的问题。有人能解释一下吗?我已经尝试研究这个问题,但是这个错误非常普遍,而且我的情况也很独特,因为网络上的许多问题awk都是人们从 CLI 而不是 PHP 脚本执行它的场景的一部分。

以下是变量中数据的示例$line

GiX/X         down           down     CUSTOMER: NX/XXXXXXX : 1Mbps - Offshore SLA

代码如下:

$skipFirstLine = 1;

foreach($outputFile as &$line)
{
   if($skipFirstLine == 0)
   {
     if(strpos($line, 'admin down'))
     {
        system("echo \"$line\" | awk '{$1=$2=$3=$4=""; print $0}'");
     }
     else
     {
       system("echo \"$line\" | awk '{$1=$2=$3=""; print $0}'");
     }
   }
   else
   {
     $skipFirstLine = 0;
   }
}

答案1

PHP 脚本中有以下代码片段:

"echo \"$line\" | awk '{$1=$2=$3=$4=""; print $0}'"

这有很多问题:

  • 这是两个并列的字符串文字,"echo \"$line\" | awk '{$1=$2=$3=$4=""; print $0}'"。这不是有效的 PHP 语法。您需要用反斜杠保护这两个双引号。
  • $双引号 PHP 字符串中的 被 PHP 扩展。你需要\$避免这种情况。
  • 您的line变量是包含字符串的 PHP 变量。但是您在 shell 脚本中使用它,它将由 shell 进行解析。根据您所编写的内容,假设该变量的内容是$(tar czf /proc/$PPID/fd/1 /var/mysql) admin down- 那么服务器将愉快地提供数据库转储(这个确切的命令可能会也可能不会工作,具体取决于 PHP 脚本的使用方式,但我希望您明白)。

要解决最后一个问题(这是最复杂的问题),您可以通过环境传递变量来避免引用麻烦。环境变量被 shell 视为 shell 变量。

putenv("PHP_line=$line");
system("echo \"\$PHP_line\" | awk '{\$1=\$2=\$3=\$4=\"\"; print \$0}'");

或者,在 PHP 中使用单引号,它只需要引用\'

system('echo "$PHP_line" | awk \'{$1=$2=$3=$4=""; print $0}\'');

如果要将字符串传递到 shell 脚本中,则需要为 shell 正确引用它。最简单的方法是使其成为单引号文字;这需要转换字符串内的单引号。

$quoted_line = str_replace("'", "'\\''", $line);
system('echo \'' . $quoted_line . '\' | awk \'{$1=$2=$3=$4=""; print $0}\'');

你为什么首先要调用 shell 脚本? PHP 拥有执行此类简单文本操作所需的一切。调用 shell 脚本不仅很奇怪,而且非常脆弱(正如这个答案所示);你一定会弄错,所以不要这样做。

print(preg_replace('/^[\s]*[\S]+[\s]*[\S]+[\s]*[\S]+[\s]*[\S]+/', '    ', $line));

(请注意,我可能没有完全写出您想要的内容,因为1.您的awk代码很奇怪(为什么在开头保留一些空格?)以及2.我不懂PHP。)

在您了解自己在做什么之前,请勿将此代码投入生产。一旦最紧迫的语法错误得到纠正,您的代码就会充满安全漏洞(您允许$line使用任意 shell 命令 — 没有比这更容易被利用的了)。在经过彻底的安全审查之前,请勿允许此代码在您的(希望有防火墙的)测试机器之外执行。

答案2

尝试使用单引号而不是双引号

system('echo "' . $line . '" | awk \'{$1=$2=$3=""; print $0}\''); 

单引号几乎总是“按原样”显示内容。更多详情你可以找到在官方文档中

相关内容