PHP - How to get Shell errors echoed out to screen - php

I am in the process of using shell_exec() for the first time. I am trying to convert some video files on my server using the ffmpeg shell script.
When I the below code in the browser, it returns NULL:
var_dump(shell_exec("ffmpeg -i /var/www/html/sitedomain/httpdocs/tmp/ebev1177.mp4"));
However when I run the equivalent code in my terminal:
> ffmpeg -i /var/www/html/sitedomain/httpdocs/tmp/ebev1177.mp4
I get back a whole load of useful information which ends in an error "At least one output file must be specified"
Why is this info not being passed back to my PHP script so I can echo it out?

The error data is output from the target program's STDERR stream. You can get access to the error data through the normal returned string from shell_exec() by appending 2>&1 to the command, which will redirect STDERR to STDOUT, the stream that you are currently seeing:
var_dump(shell_exec("ffmpeg -i /var/www/html/sitedomain/httpdocs/tmp/ebev1177.mp4 2>&1"));
You may also want to take a look at proc_open() which will allow you to get access to STDIN, STDOUT and STDERR as three individual streams, which can afford much finer grained control over the target program and exactly how you handle the input and output to it, including redirecting any and all of them directly to a log file if so desired. Be aware though that this is a much more complex mechanism with many pitfalls and tripping hazards.
More information on the standard streams can be found here.

Related

Write the PHP command line log to a file like in Python

In Python, we can add the command line log to a file instead of the console using this command:
python script.py >> mylogfile.txt
How can I do it using PHP? I've tried
php script.php >> mylogfile.txt
but it doesn't work.
I use Windows 10.
I finally found the answer. It's based on the article PHP on the Command Line – Part 1 Article
I first used php script.php > mylog.txt which returns some of the log text to the console, so I thought it's not writing to the log, but it does. I wanted php script.php > mylog.txt 2>&1 which will add any log to the file.
The article says it doesn't work in Windows, but I use Windows 10 and it works.
The error messages are mixed with the normal output as before. But by
piping the output from the script, I can split the errors from the
normal output:
php outwitherrors.php 2> errors.log
This time, you’ll only see these messages:
Opening file foobar.log Job finished
But, if you look into the directory in which you ran the script, a new file called errors.log will have been created, containing the error
message. The number 2 is the command line handle used to identify
standard error. Note that 1 is handle for standard output, while 0 is the handle for standard error. Using the > symbol from the command line, you can direct output to a particular location.
Although this may not seem very exciting, it’s a very handy tool for
system administration. A simple application, running some script from
cron, would be the following:
php outwitherrors.php >> transaction.log 2>> errors.log
Using ‘>>‘, I tell the terminal to append new messages to the existing
log (rather than overwrite it). The normal operational messages are
now logged to file transaction.log, which I might peruse once a month, just to check that everything’s OK. Meanwhile, any errors that need a quicker response end up in file errors.log, which some other cron job might email me on a daily basis (or more frequently) as required.
There’s one difference between the Unix and Windows command lines,
when it comes to piping output, of which you should be aware. On Unix,
you can merge the standard output and standard error streams to a single destination,
for example:
php outwitherrors.php > everything.log 2>&1
It reroutes standard error to standard output, meaning that both get
written to log file everything.log.

How do I redirect the STDOUT for a PHP process that is invoked via screen -d -m?

I'm invoking a PHP process using screen -d -m so that it launches the process in a new screen session. I'd like to store the STDOUT of that PHP process in a log file. Normally, I can simply add > output.log and that log file will be created and populated with the STDOUT of the PHP process. This does not work when the PHP process is launched within a new screen session. The log file is created but it is never written to.
How do I record the STDOUT of this PHP process?
screen -d -m php process.php user_input_1 user_input_1 > output.log
I believe this command is redirecting the STDOUT of the screen command to output.log and not the STDOUT of the process.php.
An alternative to screen is to use tmux. Here is a good overview of what it offers over screen: http://dominik.honnef.co/posts/2010/10/why_you_should_try_tmux_instead_of_screen/
It's a scriptable piece of software, so it seems likely that you can control the output. This post (http://ricochen.wordpress.com/2011/04/07/capture-tmux-output-the-much-less-painful-way/) seems to indicate as much. The commands listed on there should be scriptable.
YMMV, I haven't tried this. I think I'd probably try a different method (maybe using a logging server). Let me know if you have any other questions on this, or if you're pursuing a different approach.
Now gimmie my karma ;)

C++ display output into php

I have a C++ console application that returns some kind of things, then, I need to show that in a browser. So I tried to write every console.write from C++ to a .txt file for future PHP reading, but no success because it doesn't write the errors!
Then I tried to use exec('program.exe', $output); at PHP but no success too.. :/
Is there another way to do that?
Or any function in C++ that writes to a .txt every single thing that shows up in the console?
Or some function in another Programming Language that catches everything in the console?
You have to understand that cout (standard output) and cerr (standard error output) are two different streams, so probably you forgot to redirect cerr to your text file as well. Here some ideas you can use:
Redirect your streams to a file on your code (see How to redirect cin and cout to files?)
Redirect the output of any console program from the command line (you don't require to change the code and works on windows and unix / linux) by calling it this way executable.exe > out.txt 2>&1 (see Redirect all output to file)
Connect your web application to your console application using TCP sockets (might be an overhead but useful if the application requires some kind of interactive control)
There are three standard file handles known as stdin, stdout, stderr. Looks like you're only fetching stdout right now. Try to redirect stderr to stdout.
exec('program.exe 2>&1', $output);
(works not only on *nix but also win32).
see also: In the shell, what does " 2>&1 " mean?

Processing Gem Data

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.

ImageMagick compare not returning anything to php shell_exec()

I want to compare two images using Image Magick. For this I am using following command in windows command prompt
compare -verbose -metric mae image1.jpg image2.jpg difference.png
This command compares image1 and image2 and prints the resultant output to command prompt window and generates a difference.jpg file that shows difference between two images.
But when I run same command using php shell_exec() no output is returned. I know that the command is being executed by php as difference.jpg is being generated but no output is returned by the function. Similarly when i try passthrough() or system() to get output, again the command is being executed but no output is returned.But when I use builtin system commands like dir I can easily get output.
Any help will be appreciated as I am stuck on this for hours but still no success Thanks
I solved the problem. Its strange that imagemagick compare with verbose arguement does not send anything to normal command promt output. It sends output to stderr. Stderr normally receives error output. But here this command is writing normal output to stderr. As output is going to stderr so shell_exec() is unable to get it. In order to capture it in shell_exec() we will have to append 2>&1 to command. This will redirect stderr to normal command prompt output.
The ImageMagick compare command normally doesn't produce any output. You give it two input files and the name of the output file, and it quietly creates the output file.
If there's an error, it will write an error message to stderr and set a non-zero exit status. (There should be a way to get the exit status, but I don't know PHP.)

Categories