tags:

views:

1191

answers:

8

This is driving me crazy. I'm trying to execute a command line statement on a windows box for my PHP web app. It's running on windows XP, IIS5.1. The web app is running fine, but I cannot get @exec() to work with a specific contactenated variable. My command construction looks like this:

$cmd = ($config->svn." cat ".$this->repConfig->svnParams().quote($path).' -r '.$rev.' > '.quote($filename));

This command does not work as is above, when it generates the following string:

svn --non-interactive --config-dir /tmp cat "file:///c:/temp/test/acccount/dbo_sproctest.sql" -r 1 > "C:\Inetpub\sites\websvn\temp\wsv5B45.tmp"

If I copy/paste this to my own command line, it works fine.

If I hard code that very same path instead of adding it with the variable, it works! I've tried with and without quotes around the file name. I've tried with and without quotes around the entire command. I've tried other directories. I've tried passing an output paramter to exec(), and it comes back empty (Array () ). I've tried redirecting the output of the error stream of the command to a file, and that error output file never gets created.

The only thing I can possibly concieve of is that exec() is failing silently. What on earth am I doing wrong here? If I hard code the file path, using the same dir structure and filename, it works fine. If I don't, it doesn't.

Maybe the slashes () in the file path aren't being escaped properly, but when I do it manually with single quotes they are not considered escape sequences??

UPDATE:

I took the @ off of exec, and still not seeing any errors.

I gave the full path to SVN, still no luck. It should be noted that the command worked fine before with the non-full path SVN so long as I manually specify the file destination for cat.

Update 2: RE: Kieth

I'm calling exec by trying both:

exec($cmd);

or

exec($cmd, $out);

My php.ini already had safe_mode = 0.

I added error_reporting(E_ALL); and didn't see anything new

If I echo (or print_r) my exec call, I am not actually seing anything

If I echo (or print_r) my exec call when included an output var, I get an empty arr

Update 3

I tried both escapeshellcmd and escapeshellarg to no avail (good idea though).

I should add that the file is being created through invoking

tempnam("temp", "wbsn");

The fact that it works just fine if I manually specify the string instead of letting it be generated by tempname seems to suggests that the source of the problem, but I can't figure out how. I did a comparison of the manual string with the one generated, and it came back as a match.

+2  A: 

It could be that the PATH isn't the same from your php script vs your user account. Try removing the @ and see if it's trying to throw an error.

In addition, you may want to try putting the full filesystem path to the SVN executable.

Jordan S. Jones
+14  A: 

@exec will always fail silently, because @ is PHP's error suppression operator.

R. Bemrose
+1  A: 

Well, if removing @ isn't working, try including this at the start of the piece of code you're running:

error_reporting(E_ALL);

That'll turn on full error reporting, just in case you have it turned down or disabled in your php.ini file.

I don't suppose you could show us how exactly you're calling exec()? Could you also check to make sure you're not accidentally running the script in safe mode? Are you echoing out what exec() is returning, and if so, what is it returning?

Keith Gaughan
A: 

I'm not a big fan of adding another response, but if I just edit my previous response, you may not see it.

PHP has some special escaping commands for shell scripts: escapeshellcmd and escapeshellarg.

I think you should be able to use escapeshellcmd around your entire $cmd, but I'm not sure.

R. Bemrose
I *think* so too, yet I am not certain. Those docs need work.
Liam
More info: http://stackoverflow.com/questions/982904/best-way-to-sanitize-exec-command-with-user-inserted-variables
Liam
+1  A: 

Have you tried echo exec("dir") or something simple to see if exec() is working at all?

ithcy
yes, exec("dir") returned data
Matt
A: 

I don't know what going on, but I at least have a workaround.

This works:

$tmp = tempnam("./", "wbsn");
$filename = dirname($tmp).'\\temp\\'.basename($tmp);

This, however, does not, but I would have expected it to generate the same path (diff file name since it's a new tempnam()).

$tmp = tempnam("temp", "wbsn");

Also, this does not work, which I also would expect to generate the same thing:

$tmp = tempnam("temp", "wbsn");
$filename = dirname($tmp).'\\'.basename($tmp);

All 3 of these solutions appear to generate the same file paths, but only the first one actually works when used in my exec. I have no clue why it does not.

Visual inspection (echo) of all 3 of these appear to generate the same paths (with the exception of filenames differing, of course). A string comparison of dirname() of each of these 3 shows as a match. I have no clue what the deal is, but the first one is a workaround.

Matt
A: 

A very useful trick when debugging shell exec problems is to place an "echo" at the beginning of the command. Make sure that you can view the standard output somewhere.

This will let you examine the command for any obvious problems. Perhaps it has a wildcard that is expanding unexpectedly, or perhaps the shell quoting is not exactly right. The echo will let you see this, and you can cut and paste the echoed command into another shell to see if it is working properly.

Zan Lynx
A: 

Not sure if this will help you since you're on Windows and I'm on Linux, but I ran into this same problem of silent errors from PHP exec(). I figured out that the command I was attempting to issue (nconvert) sends its error messages to the standard error stream, not standard out. So I added

2>&1

at the end of the command line to redirect my error back to the standard stream. Then I could see that nconvert was giving me a permission denied error.

matt