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.
Related
I have a question regarding running a shell command via PHP. My goal is to successfully run compass compile [project] via PHP. I have tried the following:
echo system('compass compile [project]', $s); // prints [31m[0m
echo $s; // prints 1
echo passthru('compass compile [project]', $p); // prints [31m[0m
echo $p; // prints 1
echo shell_exec('compass compile [project]'); // prints [31m[0m
echo exec('compass compile [project]', $e, $ee);
print_r($e); // Array ( [0] => [31m[0m )
echo $ee; // prints 1
I even tried running a shell command to an executable file that contained compass compile test and I still got the same results as the trials above.
My questions
What does [31m[0m mean? Does this represent binary data? Do these represent bash colors as search engines suggest?
As far as I know, the output should be the following:
For kicks, I tried to execute via system(/usr/local/bin/compass compile [project]); and I got the same result. I double checked my path so I know I can execute these commands as expected. Here is the output from echo $PATH:
/usr/lib/lightdm/lightdm:
/usr/local/sbin:
/usr/local/bin:
/usr/sbin:
/usr/bin:
/sbin:/bin:
/usr/games:
/usr/local/games:
/var/lib/gems/1.9.1/bin
Is there a way to compile compass projects using PHP?
I've seen a similar error before.
Typically it is due to the things being output in the bash startup scripts. For example, I had an echo in one of my bash startups that jacked up a lot of scripts till I realized what was causing the problem.
Or, perhaps the user (www-data ?) doesn't actually have a home dir and appropriate startup scripts in place?
You can try this to get a non interactive shell:
exec("/bin/bash -c \"compass compile [project]\"", $e, $ee);
print_r($e);
echo $ee;
If you still have issues, try redirecting the output to a tmp file, an checking it:
exec("/bin/bash -c \"compass compile [project] > /tmp/compass.compile.output\"", $e, $ee);
print_r($e);
echo $ee;
See also: What's the difference between .bashrc, .bash_profile, and .environment?
The issue was fixed by using sass --compass and redirecting the stderr to stdout via echo shell_exec("sass --compass [project] 2>&1");
It was a pretty long and arduous process figuring this out since it's been awhile since I've dabbled in command line programs. Remember that error streams and output streams might be on different outputs. The easiest way to test this is to shovel the output into a file via:
# do this once with a good file and once with a file that will give errors
sass --poll style.scss > output.txt
If output.txt is empty then the error output is on the stderr stream such as the case above. We can correct this by redirecting the stderr to the srdout. For example:
sass --poll > output.txt 2>&1
#shows results
cat output.txt
I created a simple PHP script that redirects the output from one textarea to the other. The code can be found here.
First guess would be a permissions issue. Odds are the user account running PHP (unless you're running this from the command line, I'm guessing that this is the user that the httpd apache daemon is running under) doesn't have the permissions to do what you're asking. The errors are extremely unhelpful, however.
From what I can tell, it looks like an attempt to have the error show up in red on the command line. My guess is that there are hidden (or somehow never printed out) characters in-between the codes. Check out some of your apache and/or PHP error logs to see if anything helpful is showing up there that never made it into the PHP variable. Or, for kicks, try copy and pasting the output with the bash colors into a basic text editor and first delete each character from the beginning one by one... see if anything magically appears. If that doesn't work, try the same in reverse, backspacing from the end. Either way, there's an error occurring, so important that it must show in bold red letters to you, it's just not getting to you.
If it does in fact turn out to be a permissions issue, and it's one you can't remedy through permissions wrangling, you could create an intermediary file that your Apache user has permissions to write to, and your cron user has permissions to read from. Instead of running the code directly from PHP, put it in the file, then run a cron on a frequent basis looking for anything in that file, CHECKING IT FOR VALIDITY, and then running it through the compiler and removing it from the file.
It'd be ugly, but sometimes pretty things don't work.
You guessed it right it is colors but the way it is defined is not right. For more information regarding using colors in console please refer to this document. Also, for compiling SCSS via compass you can use shell_exec command in linux. For more information regarding shell_exec please refer to this document. Let us know how it goes.
For common commands like 'ls', exec() works fine, eg:
exec('ls',$output,$retval);
var_dump($output,$retval);
// $output contains an array of filenames, and retval === 0
But when trying to execute another program, I can't get the output:
exec('some_command --a_parameter',$output,$retval);
var_dump($output,$retval);
// $output contains an empty array, end $retval === 0
This command prints some lines when executing it directly from the command-line though.
I know the command has been successful because of the results (some files updated, data added, etc), and yet I can't see the output.
Any ideas?
It sounds like the program is outputting its warnings to standard error rather than standard output. exec will only catch standard output. I don't know for certain that standard error is always sent to the apache error log, but it seems likely.
If you don't need compatibility with non-*nix systems, you can redirect standard error to standard output by appending 2>&1 to the command:
exec('some_command --option 2>&1', $output, $ret);
This should both make the warnings available to your php program and prevent unnecessary logging.
All the output was being sent to httpd/error_log when for some * reason, when the application found a warning (something internal, not even fatal)
My solution: When there is no output, assume it failed.
My apache logs are going to get dirty, but whatever.
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.
I am using exec function to execute the specific executable files in php .
exec ( $file , $output , $return_value ) ;
When the given file executed successfully I am able to get the output in the second argument
by checking the return values , So, It is working fine. But My requirement is when the command execution getting failed due to some reason. I need to get that error message of that executed program . What I need to do to get the error . through second argument we can get the successful output only . Not error message.
Thanks.
The second argument $output only captures STDOUT from your executable. Error messages are usually sent to STDERR so that they easily can be written to an error log or similar, but this means that you won't see them when you call exec.
If this is a linux system, you could append 2>&1 to your command, in order to redirect STDERR to STDOUT. I haven't tried this, but it should forward the error messages to your $output variable.
Edit:
I've read up on it on www.php.net/exec, and it seems this would work.
exec($file.' 2>&1', $outputAndErrors, $return_value);
It is also possible to redirect the errors to a temporary file and read them separately.
exec($file.' 2> '.$tmpFile, $outputOnly, $return_value);
Edit 2
It seems windows also uses this Bourne style output redirecting syntax, so the examples should work for windows too.
More on input and output streams
If you need to keep stderr and stdout separate, try proc_open:
http://php.net/manual/en/function.proc-open.php
The $return_value will have the error code returned by the program which should be meaningfull enough, I don't think you can have better.
In a previous post, I was trying to update the encoding for a download file from php. One of the suggestions was to run the unix2dos command before sending the file to the user. This works great when I run the command on the linux box, but when I try and run the command from php I get nothing. Here is what I tried:
$cmd = "unix2dos -n $fullPath $downloadFile";
echo exec($cmd, $out, $retVal);
This displays nothing to the screen, $retVal is 0, and $out is an empty string.
echo system($cmd, $retVal);
This displays nothing to the screen, $retVal is 0.
echo shell_exec($cmd);
This displays nothing to the screen.
I have also tried escaping the command and it parameters like:
$cmd = escapeshellcmd($cmd);
and
$cmd = "unix2dos ". escapeshellarg("-n \"$fullPath\" \"$downloadFile\"");
Please let me know if you see something that I am doing wrong.
Thanks!
Edit: Here is some info that may be helpful.
unix2dos version: 2.2 (1995.03.31)
php version 5.2.9
Running in apache 2 on in Redhat Enterprise Linux 4
Have you considered a pure PHP solution?
<?php
$unixfile = file_get_content('/location/of/file/');
$dosfile= str_replace("\n", "\r\n", $unixfile );
file_put_contents('/location/of/file/', $dosfile);
?>
Something like that should do it, although untested :)
Shadi
See which user the PHP exec command is running as:
<?php system('whoami'); ?>
If this command fails then you likely do not have permission to use exec() or system(), so check your INI files. But be sure to check the correct ones! On Debian systems there are separate Apache and CLI INI files stored at /etc/php5/apache/php.ini and /etc/php5/cli/php.ini respectively. Sorry I do not know the locations for RedHat.
If the whoami command succeeds, make sure that the unix2dos command can be run by the user that is shown, and that the same user is allowed to make changes to the files in question by using chmod or chown.
Are you using the full path to unix2dos? Perhaps the executable is in your path for your shell but not in the path that PHP is using.
My implementation of unix2dos produces no output. If the return value is 0 then the command succeeded and your file has been updated.
The only other thing I see is the -n option which my version doesn't seem to have. You should probably check your man page to see what options it supports
unix2dos does not display the file it converts. Therefor you must display it yourself. A very basic way to do it could be :
$cmd = "unix2dos -n $fullPath $downloadFile";
echo exec($cmd, $out, $retVal);
include "$fullPath."/".$downloadFile;
Using include is pretty dirty but quick and easy. A cleaner way would be to use fopen and read the file then display it.
You'd better create a function that enclose all the operation : conversion + display so you'll have everything at hands.
But, If I were you, I'd prefer to not use exec at all and use FileIterator with a trim on every line so you will not have to care about the carriage return nor deal with a hazardous shell binding.
Not sure about your exact problem, but debugging suggestion:
Try first setting $cmd to ls. See if that works. Then try using /bin/ls (use the full path.)
If those don't work, then there might be a problem with your PHP configuration - there might be a safemode parameter or something which disallows the use of exec(), shell_exec(), or system() functions.
I got the source code from here.
http://www.sfr-fresh.com/linux/misc/unix2dos-2.2.src.tar.gz
I compiled it and then ran the tool. This was my output:
rascher#danish:~/unix2dos$ ./a.out -n 1.txt 2.txt
unix2dos: converting file 1.txt to file 2.txt in DOS format ...
I think the problem is this: the program writes all of its output to stderr, rather than stdout. If you look at the source code, you can see "fprintf(stderr, ...)"
As far as I know, PHP will only read the part of your program's output that is sent to STDOUT. So to overcome this, it seems like you have to redirect the output of your program (unix2dos uses stderr) to stdout. To do this, try something like:
$cmd = "unix2dos -n $fullPath $downloadFile 2>&1"
The "2>" means "redirect stderr" and "&1" means "to stdout".
In either case, I would imagine that the file was converting properly, but since you weren't getting any of the expected output, you thought it was failing. Before making the change, check on the output file to see if it is in DOS or UNIX format.