I'm able to call diff via exec() just fine with files, like so:
exec('diff -N -u '.escapeshellarg($oldfile).' '.escapeshellarg($newfile), $lines);
However, attempting to do this with arbitrary strings fails:
exec('diff -N -u <(echo '.escapeshellarg($oldstring).') <(echo '.escapeshellarg($newstring).')', $lines);
If I copy the command being run into bash, it works just fine. But when run in PHP I get no output. Even 2>&1 doesn't yield anything. Capturing the status code yields 1, which should indicate that diff found differences, but I still get 1 even in the case where $newstring === $oldstring.
So I'm not quite sure what's going on. I can only assume that, for some reason, exec doesn't like process substitutions? Any ideas?
execruns the command withsh, which does not support process substitution. You'd need to run it withbashexec('echo $SHELL');yields/bin/bash.'/bin/bash -c '.escapeshellarg('diff ...')and suddenly it's working. That leaves more questions (like why$SHELLis/bin/bash) but at least it works!$SHELLis not the currently running shell. It's the user's login shell, similar to how$EDITORis the user's editor and$PAGERis their preferred pager.