运行php exec的shell错误

时间:2018-07-27 17:31:37

标签: php shell sh

我有一个PHP脚本,该脚本执行一个shell命令来查找给定两个文件之间的公用项。这是我的PHP脚本的开始:

$E7Bonded_File = "/opt/IBM/custom/NAC_Dslam/junk/PortParameter_E7_Bonded_cust_stats.csv";
$E7Single_File = "/opt/IBM/custom/NAC_Dslam/junk/PortParameter_E7_Single_cust_stats.csv";
$E7Common_File = "/opt/IBM/custom/NAC_Dslam/junk/Common_tn_SingleBonded_E7_cust_stats.csv";
//only do this once, with old single/bonded filenames. This will be a list to add to the existing Common file.
exec ("comm -12 <(cut -d ',' -f2 $E7Single_File| sort) <(cut -d ',' -f2 $E7Bonded_File| sort)", $outputCommon); 

我在运行脚本时看到以下错误消息:

sh: -c: line 0: syntax error near unexpected token `('
sh: -c: line 0: `comm -12 <(cut -d ',' -f2 /opt/IBM/custom/NAC_Dslam/junk/PortParameter_E7_Single_cust_stats.csv| sort) <(cut -d ',' -f2 /opt/IBM/custom/NAC_Dslam/junk/PortParameter_E7_Bonded_cust_stats.csv| sort)'

我检查了一下,我的exec()行的括号看起来还可以。

当我在命令行上运行shell命令时,它会返回一个如我期望的数字列表:

 comm -12 <(cut -d ',' -f2 junk/PortParameter_E7_Single_cust_stats.csv| sort) <(cut -d ',' -f2 junk/PortParameter_E7_Bonded_cust_stats.csv| sort)

我在网上看了看,似乎在正确使用exec()。我希望返回的数字存储为数组$outputCommon

关于此错误消息的任何想法吗?

*********更新答案***************

我的解决方案最终融合了马里奥和miken32 /我的同事

  1. 在我的PHP脚本顶部添加#!/bin/bash,并且
  2. 添加/bin/bash -c如下:

    exec(“ / bin / bash -c /opt/IBM/custom/NAC_Dslam/Common_list.sh”,$ outputShell);

  3. 将comm部分移至shell脚本后:

Common_list.sh:

#!/bin/bash
 comm -12 <(cut -d ',' -f2 /opt/IBM/custom/NAC_Dslam/junk/PortParameter_E7_Single_cust_stats.csv| sort) <(cut -d ',' -f2 /opt/IBM/custom/NAC_Dslam/junk/PortParameter_E7_Bonded_cust_stats.csv| sort)

3 个答案:

答案 0 :(得分:2)

最简单的解决方案可能是将其制成服务器上的可执行脚本:

#!/bin/bash
if [[ ! -r "$1" ]] || [[ ! -r "$2" ]]; then
    printf "File not found\n" >&2
    exit 1
fi

comm -12 <(cut -d ',' -f2 "$1"| sort) <(cut -d ',' -f2 "$2"| sort)

然后从PHP调用它:

$E7Bonded_File = escapeshellarg("/opt/IBM/custom/NAC_Dslam/junk/PortParameter_E7_Bonded_cust_stats.csv");
$E7Single_File = escapeshellarg("/opt/IBM/custom/NAC_Dslam/junk/PortParameter_E7_Single_cust_stats.csv");

//only do this once, with old single/bonded filenames. This will be a list to add to the existing Common file.
exec ("/usr/local/bin/your_script.sh $E7Single_File $E7Bonded_File", $outputCommon); 

始终使用escapeshellarg()转义您的shell参数,即使您认为它们很安全。

答案 1 :(得分:1)

此错误通常是针对不支持<()表达式管道的非bash shell出现的。

  • 在Ubuntu / Debian服务器上,默认/bin/sh通常是dash

  • 检查符号链接的二进制文件:

    me@snip:~$ ls -l /bin/sh
    lrwxrwxrwx 1 root root 4 Jul 16  2017 /bin/sh -> dash
    
  • 或者如@theotherguy所述,bash在以sh开头时以受限壳运行。

  • 请参阅$ _ENV [SHELL],以了解Apache / PHP默认使用的内容。更改环境变量。

  • 要么对此进行调整,要么将shell_exec cmdline换成/bin/bash -c '…'

答案 2 :(得分:0)

使用linter检查脚本时,它抱怨:

comm -12 <(cut -d ',' -f2 junk/PortParameter_E7_Single_cust_stats.csv| sort) <(cut -d ',' -f2 junk/PortParameter_E7_Bonded_cust_stats.csv| sort)
     ^-- SC2039: In POSIX sh, process substitution is undefined.

在我定义shebang #!/bin/sh时发生这种情况,而#!/bin/bash没有抱怨……因此答案可能是使用/usr/bin/bash运行脚本。 escapeshellarg()确实有用。

...

尝试shell_exec(),只是因为exec()不应调用任何shell。一个返回字符串输出,另一个可以返回数组。 或者,您可以使用exec()显式调用bash:

exec('/bin/bash -c "  command  "', $stdOut);