Catch when php file written to - php

I would like to know if its possible to force PHP to execute as a file rather than being overwritten?
I have set the sendmail -X option for logging which will happily log to a file. When I set it to point to a PHP file it appended to the actual file. Is there anyway (I'm using Ubuntu) to effectively run the file rather than it being written to?
The file currently reads (which I would like to execute):
<?php
$pointer = fopen('php://stdin', 'r');
file_put_contents('/home/www/dev1/log.log',$pointer);
?>

If you are using Bash, you can try process substituion:
sendmail other-args -X >(php your-php-file.php)
This will pass the contents to your PHP file's stdin directly.
However, use stream_copy_to_stream, because if you use stream_get_contents or other one-time functions like that, nothing will be written until the process closes.

Related

Running shell_exec() in background AND getting its output afterwards

First of all, I would like to point out that this is NOT a duplicate to this or this and other related questions. I am asking how to get the output as well and my question is mostly related to that.
I need to run a bash script from PHP and get its output in PHP. However, doing:
echo shell_exec('script');
dies out on the 60th second due to Apache's FcgidIOTimeout. If I use the following to run it in the background, I won't be able to get the output:
shell_exec('<myscript> > /dev/null 2>/dev/null &');
I cannot:
Modify the bash script;
The code and all the functionality needs to be in a single file (unless I use a temp file);
If I were to write the output of the shell_exec() function to a temp file, I would also need to find a way to verify whether the
process has finished;
Using a database is an overkill which I cannot afford;
My current and only idea is to create a tmp file using PHP and write the output to it, then using top -c | grep <myscript> (with a refresh button) and if it returns true then it is still ongoing. However, I suspect that would not be practical and efficient in most of the time.
It is important that I use a temp file and not actually creating a "permanent" file to write to.
Solution for a similar problem: A few years ago I had a similar problem. I had to upload a file to a FTP server. I wondered how to communicate to the FTP server that the file was uploaded completely, so that the FTP server can perform some tasks on it. My solution was to rename the file to something like *.completed after it was uploaded completely. Then the process on the FTP server could look for *.completed files only.
Solution adjusted to your problem: I'd suggest you to rename your temp file after it was generated by your bash script. This way you can independently find out if the script was executed successfully. shell_exec() could look like this:
shell_exec('<myscript> > tmp-file && mv tmp-file tmp-file.completed &');
Be aware that this only redirects the channel STDOUT into the the tmp-file. If you also want to redirect STDERR into the tmp-file, try this:
shell_exec('<myscript> &> tmp-file && mv tmp-file tmp-file.completed &');

Using a single command line through php

I am trying to run a c++ executable that I have on my computer through my PHP interface. I do not have admin rights on the computer that my PHP is being hosted from and therefore cannot add the appropriate items to my PATH for my c++.
I am able to call the exec function in PHP and run my program via a batch file. In my batch file I am able to set my path variable to what I need it to be.
Here is what I am currently doing (with runVideoparser being the batch file):
exec("C:\\Users\\hewittjc\\Desktop\\runVideoParser", $output, $return);
echo "Program returned $return.";
The above works just fine when passing a fixed parameter to my c++ in the batch.
However, my issue is that I need to be able to pass the program different arguments each time. If I run it via batch file then I loose this ability.
So my question is, How can I:
1) Open a command prompt via PHP (I'm running windows)
2) Set my path variable in the prompt via PHP
3) Then, using that same prompt to preserve the path variable, run my program passing it the required argument.
I suppose I could generate the batch in my PHP then run that, but I am seeking any more elegant solutions.
In theory, you can do something like this:
$old_path = getenv("PATH");
$new_path = "/my/additional/path:$old_path";
putenv("PATH=$new_path");
system("command -with flags -and args -and such");
However, this won't work if the host machine has Safe Mode on and PATH is not in the safe_mode_allowed_env_vars directive.

Linux command populate file from php script output

I have a PHP script which generates some complex XML output. The XML is currently being output as a webpage but instead of a webpage I need it as a physical file on my server.
So, I wonder if there is a way to pipe the output of my PHP script into the Linux touch command so that my PHP output populates, or overrides, a file on my server?
I am currently trying the following code without success:
touch test | php xml_reports.php
You can actually run PHP from the command line.
php filename.php
So if your php file consisted of:
<?php
echo "Hello World";
?>
The output would be "Hello World" (without the quotes) in your terminal. So if you were writing an application in PHP, try and think about how you would approach it without the browser rendering your output. I hope that helps.
[edit]
You might also want to look into shell_exec. (http://php.net/manual/en/function.shell-exec.php)
Assuming I understand your question correctly, here is a solution. In this case however, rather than piping the PHP output, the PHP code itself outputs a copy of the file on the server. I'm not sure how vital it is that this is done through a linux pipe. Also note that this solution is copied from http://forums.codewalkers.com/showpost.php?p=40350&postcount=3.
1) at the very start of your script put this line :
ob_start();
2) at the very end of your script, put this:
$page = ob_get_contents();
ob_end_flush();
$fp = fopen("output.html","w");
fwrite($fp,$page);
fclose($fp);
And, bam, you should have the whole page in a file called output.html.
Now, one thing you need to be sure of is that the webserver server can
write the file output.html. That means you need to make sure the
webserver has the permissions to write in whatever directory you plan
to store that file in.
How does it work? Basically, it just buffers all output from your
script. Then, you store that buffer into a string. Then you send the
buffer to the browser. Then you store that string in a file...

Problems when trying to exectue exec("unix2dos xxx") in PHP/Apache

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.

How do I escape a PHP script to an external editor and return afterwards?

Specifically I have a PHP command-line script that at a certain point requires input from the user. I would like to be able to execute an external editor (such as vi), and wait for the editor to finish execution before resuming the script.
My basic idea was to use a temporary file to do the editing in, and to retrieve the contents of the file afterwards. Something along the lines of:
$filename = '/tmp/script_' . time() . '.tmp';
get_user_input ($filename);
$input = file_get_contents ($filename);
unlink ($filename);
I suspect that this isn't possible from a PHP command-line script, however I'm hoping that there's some sort of shell scripting trick that can be employed to achieve the same effect.
Suggestions for how this can be achieved in other scripting languages are also more than welcome.
You can redirect the editor's output to the terminal:
system("vim > `tty`");
I just tried this and it works fine in windows, so you can probably replicate with vi or whatever app you want on Linux.
The key is that exec() hangs the php process while notepad (in this case) is running.
<?php
exec('notepad c:\test');
echo file_get_contents('c:\test');
?>
$ php -r test.php
Edit: As your attempt shows and bstark pointed out, my notepad test fires up a new window so all is fine, but any editor that runs in console mode fails because it has no terminal to attach to.
That being said, I tried on a Linux box with exec('nano test'); echo file_get_contents('test'); and it doesn't fail as badly as vi, it just runs without displaying anything. I could type some stuff, press "ctrl-X, y" to close and save the file, and then the php script continued and displayed what I had written. Anyway.. I found the proper solution, so new answer coming in.
I don't know if it's at all possible to connect vi to the terminal php is running on, but the quick and easy solution is not to use a screen editor on the same terminal.
You can either use a line editor such as ed (you probably don't want that) or open a new window, like system("xterm -e vi") (replace xterm with the name of your terminal app).
Edited to add: In perl, system("vi") just works, because perl doesn't do the kind of fancy pipelining/buffering php does.
So it seems your idea of writing a file lead us to try crazy things while there is an easy solution :)
<?php
$out = fopen('php://stdout', 'w+');
$in = fopen('php://stdin', 'r+');
fwrite($out, "foo?\n");
$var = fread($in, 1024);
echo strtoupper($var);
The fread() call will hang the php process until it receives something (1024 bytes or end of line I think), producing this :
$ php test.php
foo?
bar <= my input
BAR
system('vi');
http://www.php.net/system

Categories