I need to execute mkdir command (e.g. via PHP's exec command). How do I access standard error (e.g. EACCES, see: http://pubs.opengroup.org/onlinepubs/009695399/functions/mkdir.html). Suggestions? Thanks.
UPDATE:
I added 2>&1 to my command:
$command = "sudo mkdir /home/test 2>&1";
$output = array();
$return = 0;
exec($command, $output, $return);
Without it, I used to get either 0 (success) or -1 (error). Now, I get a 1 during one of my tests -- and I think it's because the directory I am trying to create already exist. It would seem that 1 maps to EEXIST. How do I map the rest of the errno?
You cannot.
You want to catch the error of the mkdir function via errno, but your call to PHP's exec() means that you will instead deal with the exit code of the external program mkdir.
It is the difference between:
http://pubs.opengroup.org/onlinepubs/009695399/functions/mkdir.html (which you cite)
and
http://pubs.opengroup.org/onlinepubs/009695399/utilities/mkdir.html (which you exec)
You're probably looking for proc_open, which gives you the ability to work directly with stdin, stdout and stderr as PHP streams, meaning you can use the normal file reading and writing functions on them.
Please be sure to read more details about the proc_ family tree on the proc_close and proc_get_status pages.
You might have more luck working with the text of the error as provided to stderr instead of working with exit codes.
Related
(Seemingly) no matter what command I try to run with PHP's system function, the command always does nothing and then fails with exit code 1. For example,
system("echo 'this should definitely work'", $retval);
sets $retval = 1. So does
system("dir", $retval);
as well as running an executable that I've written; when I run
vfmt -h cat.v
from cmd.exe the command works and returns with exit code 0, but running
system("vfmt -h cat.v", $retval);
again sets $retval = 1. This vfmt.exe file is in the same directory as the src.php script that is attempting these system calls.
I am nearly at my wit's end trying to figure out what's wrong. What could possibly be causing this issue?
You should check your php.ini for line like the next:
disable_functions =exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source
^^^^ ^^^^^^^^^^^^^^^^^^
and such.
Also check your "safe mode" status, (php ver. < 5.4) if you have enabled it you can only execute files within the safe_mode_exec_dir and so on...
More information in the doc and for the execution of commands here and especially for system here.
echo is invariably a shell internal command, not a separate executable. You need something more like
system('/bin/sh -c "echo \'foo\'"'); // unix-ish
system('cmd.exe /c echo foo'); // windoze
Most likely issue is that the "working directory" is not what you expect.
This is hidden as you're checking return value and not screen output; they are different.
Firstly, to monitor: try using exec http://au2.php.net/manual/en/function.exec.php as this will help you debug by giving both screen output and return value.
Secondly, to fix:
1 - Specify full paths to both the executable and included files. Assuming this is Windows (you refer to cmd.exe) then run
system("c:\PathToPhpFile\vfmt -h c:\PathToCatVFile\cat.v, $retval);
or
2 - Change the working directory before calling system() or exec() by using chdir() first.
(Or you can do the cd in a batch file (windows) or concatenate the commands in Linux; but this is less portable.)
You need to redirect the output of the command you're running with system() in order for it to run in the background. Otherwise, PHP will wait for program execution to end before continuing.
system('mycommand.exe > output.log', $retval);
system('mycommand.exe 2>&1', $retval);
Not sure how you're invoking your script, but perhaps you're running into a PHP max_execution_time (or related) limit. Something to investigate. Also, since you're running on windows, you may need to use absolute paths with your commands when executing system calls as the file you're invoking may not be in any defined PATH.
I am writing php script, which will be used for making sites from "standart" site.
There's a lot of unix shell commands, and I've found the problem with displaying errors.
Example: I need to check that the site folder doesn't exist yet.
$ls_newsite = exec('ls /vhosts/'.$sitename, $output, $error_code);
if ($error_code == 0) {
Shell::error('This site already exists in /vhosts/');
}
Shell::output(sprintf("%'.-37s",$sitename).'OK!');
So, I can handle error, but it will be display anyway.
php shell.php testing.com
Checking site...
ls: cannot access /vhosts/testing.com: No such file or directory
testing.com.................................OK!
How can I prevent displaying? Thanks
You don't need the output from these CLI calls, just the error code. So direct your output to /dev/null (otherwise PHP will print whatever goes to stderr unless you use proc_open and create pipes for each of these - overkill).
$ls_newsite = exec('ls /vhosts/' . $sitename . ' > /dev/null 2>&1', $output, $error_code);
That will work without giving you any output.
Now, on to a few other issues:
Use escapeshellarg for anything you're passing to a shell command.
A better way to write this same code is:
$ls_newsite = exec(sprintf('ls %s > /dev/null 2>&1', escapeshellarg('/vhosts/' . $sitename)), $output, $error_code);
Be 100% sure that you need to use console commands. There are PHP equivalents for most file-based console commands (stat, file_exists, is_dir, etc) that would make your code both more secure and would allow it to be platform-independent.
I have to design a interface using PHP for a software written in python. Currently this software is used from command line by passing input, mostly the input is a text file. There are series of steps and for every step a python script is called. Every step takes a text file as input and an generates an output text file in the folder decided by the user. I am using system() of php but I can't see the output but when I use the same command from command line it generates the output. Example of command :
python /software/qiime-1.4.0-release/bin/check_id_map.py -m /home/qiime/sample/Fasting_Map.txt -o /home/qiime/sample/mapping_output -v
try this
$script = 'software/qiime-1.4.0-release/bin/check_id_map.py -m /home/qiime/sample/Fasting_Map.txt -o /home/qiime/sample/mapping_output -v';
$a = exec($script);
If you are not on windows, have you tried adding 2>&1 (redirect stderr to stdout) to the end of the command?
$output = system("python /software/qiime-1.4.0-release/bin/check_id_map.py -m /home/qiime/sample/Fasting_Map.txt -o /home/qiime/sample/mapping_output -v 2>&1", $exitcode);
Found from http://www.php.net/manual/en/function.system.php#108713
Also the doc says that it
Returns the last line of the command output on success, and FALSE on
failure.
So if you are trying to get multiple lines, you may need to redirect it to a file and read that in.
instead of system() try surrounding the code in `ticks`...
It has a similar functionality but behaves a little differently in the way it returns the output..
I have a file named gcc.exe and I have a php page...
I want to use:
gcc test.c
And, if there's some compilation error, I want to show it on the php page...
But I can't.
What happens is: If the file is correct, it generates the .exe file,
but if it's wrong, nothing happens. What I want here, again, is to show all errors.
Anyone has an idea?
Edit[1]:
Some code:
<?php
exec("gcc teste.c",$results);
print_r($results)
?>
Output:
*Nothing*
Edit[2]:
I tryed put gcc output on a text file:
This way (on prompt):
gcc test.c > teste.txt
Teorically, everythings on the screen go to text file.
But this was unsucessfuly!
Edit[3]: quantumSoup:
I tryed it, and...
array(0) { } int(1)
Nothing... Anything more?
gcc is likely to generate error output on stderr, which it would appear exec doesn't capture in the $results array. Solutions to this are likely to be kinda platform-specific. If you're working in a unix-like environment, it would be possible to do something like gcc foo.c 2>&1 to redirect stderr to stdout. I've no clue how one might achieve that on Windows, or if analogous concepts even exist. Perhaps someone else can elaborate if your question is platform-specific.
This is supported by the fact that piping to a file didn't work either.
exec() reference
string exec ( string $command [, array &$output [, int &$return_var ]] )
Try
exec('gcc test.c', $output, $return);
var_dump($output);
var_dump($return);
Use proc_open to capture stderr:
<?php
$process = proc_open('gcc test.c',
array(
1 => array("pipe", "w"), //stdout
2 => array("pipe", "w") // stderr
), $pipes);
echo stream_get_contents($pipes[2]);
gives, for example:
sh: gcc: command not found
We use a PHP-based system that performs builds and captures results and errors under windows. We had the best success by having the PHP script create a batch file containing all the build commands, and then exec-ing that batch file. When it creates the batch file, it redirects the standard output of the compiler to one logfile and the standard error to another (commandname >>log.txt 2>>err.txt). Since your output is split between two files, it also helps to have the script generate lines that echo out descriptions of what is happening (such as "Building library libsockets.dll") so that you can better match up the two logs. Sometimes, it even helps to echo out every command before it is executed. Usually your build process will halt when an error is encountered (at least it probably should), so the contents of the error log typically match up with the tail end of the normal log.
I am trying to run a shell from one of my controllers in a PHP codeigniter applications,
I am trying to run the file /x/sh/xpay4.sh however I just get 127 returned to the screen, I can even use basic commands like ls or pwd can any suggest why this would be, I thought it might be safe_mode when I ini_get('safe_mode') it returns 1
system function is restricted in safe mode.
You can only execute executables
within the safe_mode_exec_dir. For
practical reasons it's currently not
allowed to have .. components in the
path to the executable.
escapeshellcmd() is executed on the
argument of this function.
http://www.php.net/manual/en/features.safe-mode.functions.php
system() returns only the last line of the shell output.
Sounds likt this is "127".
If you need the whole output instead, try:
$output = array();
exec('/x/sh/xpay4.sh', $output);
echo implode("<br>", $output);