'shell errors running php exec
I have a PHP script that executes a shell command to find the common items between two files given. This is the beginning of my PHP script:
$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);
I see this error message when I run the script:
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)'
I checked, and the parentheses look ok for my exec()
line.
When I run the shell command at the command line it returns a listing of numbers like I expect:
comm -12 <(cut -d ',' -f2 junk/PortParameter_E7_Single_cust_stats.csv| sort) <(cut -d ',' -f2 junk/PortParameter_E7_Bonded_cust_stats.csv| sort)
I looked online and I seem to be using exec()
correctly. I want the numbers returned to be stored as an array, $outputCommon
.
Any ideas about this error message?
*********Update on answer***************
My solution wound up being a combination of both mario and miken32/my co-worker
- Adding
#!/bin/bash
at the top of my php script, and Adding
/bin/bash -c
as follows:exec("/bin/bash -c /opt/IBM/custom/NAC_Dslam/Common_list.sh", $outputShell);
After I moved the comm part to a shell script:
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)
Solution 1:[1]
This error typically comes up for non-bash shells, which don't support <()
expression pipes.
On Ubuntu/Debian servers the default
/bin/sh
is typicallydash
.Check for symlinked binaries:
me@snip:~$ ls -l /bin/sh lrwxrwxrwx 1 root root 4 Jul 16 2017 /bin/sh -> dash
Or as @theotherguy mentioned, bash runs as restricted_shell when started as
sh
.See $_ENV[SHELL] on what Apache/PHP use as default. Change environment vars.
Either adapt that, or wrap the
shell_exec
cmdline with/bin/bash -c '…'
.
Solution 2:[2]
Probably the easiest solution would be to make this into an executable script on the server:
#!/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)
And then call that from 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);
Always escape your shell arguments with escapeshellarg()
even if you think they're safe.
Solution 3:[3]
when checking the script with a linter, it complains that:
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.
this happens when I define shebang #!/bin/sh
, while #!/bin/bash
does not complain... therefore the answer might be, to run the script with /usr/bin/bash
. escapeshellarg()
is indeed useful.
...
try shell_exec()
, simply because exec()
should not invoke any shell. the one returns the output as string and the other can return an array.
alternatively, you can explicitly invoke bash with exec()
:
exec('/bin/bash -c " command "', $stdOut);
Solution 4:[4]
So in case anyone else still needs to get substitution working in command execution in PHP, there is super dumb simple thing to do:
$a = 'Hello substitution';
var_dump(shell_exec("bash -c 'cat <(echo $a)'"));
Results in:
string(19) "Hello substitution
"
Which is expected/desired.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | miken32 |
Solution 3 | |
Solution 4 | morphles |