shell_exec - logging & outputting - php

I am running multiple shell_exec, process.php's run in the background
On the shell/ssh, I execute the code like this: username [~/public_html/curl]# php index.php
Example....
index.php
<?php
shell_exec("php process.php > /dev/null 2>&1 &");
shell_exec("php process.php > /dev/null 2>&1 &");
shell_exec("php process.php > /dev/null 2>&1 &");
shell_exec("php process.php > /dev/null 2>&1 &");
?>
process.php
<?php
$section = rand(999,999999);
$z = 1;
print "STARTED .... \n";
while($z <= 10) {
print "---------------------------------\n";
print $section . ": " . $z . "\n";
$z++;
sleep(2);
}
print "LOOP FINISH at " . time();
?>
when process.php's is running, I am having two problems with this:
I cant not see the output from process.php's (I need to know what they are doing)
I need to know which process is finish and which have started.
What the best way logging the output in real time? saving into text file? or how can it be done to mysql database (logs table)?

If your processes will be alive only within the lifetime of another php script, you could use popen instead of shell_exec:
http://us.php.net/popen
This gives you a very convenient way to get data from the other processes into your php script, using the same interface as file handles. To know then the process is done, you could make sure the process sends an EOF (end-of-file) when it's done, and use the feof php function to detect it.
On the other hand, if your processes may live longer than any other php scripts that talk to it, then a text file may be a very practical solution. Keep in mind, though, that disk access is always much much slower than memory access, so if you use text files for communication, it will not be optimally fast.

Related

Php read a log content after executing a script

I have a php script that creates a shell script which is run after making it from the same php file, the shell script generates a registry file that I need to read after the script is executed, again from the same php. The php reads the file, but I think it does it before the file is filled or created, if I go back at the browser and execute the php again, then there is content at the textarea. I have tried to solve it adding sleep(), exit() functions and some other strategies but no success. Here are some of the things I've tried:
// Creation of the shell script: Corpus alignment target to origin
......
$cmd = "cwb-align-encode -r $REGDIR -D $CORPUSLOCATION$corpusname/$corpusname"._."$lang_tg.align\n\n";
file_put_contents($scriptfile, $cmd, FILE_APPEND | LOCK_EX);
// Run the corpus indexation script
$cmd = "/bin/bash $scriptfile > /dev/null 2>&1 &";
shell_exec($cmd);
Read the registry file from the same php:
// 1st try: no content at the textarea
echo "<textarea id='txtArea'>".htmlspecialchars(file_get_contents( $REGDIR.$corpusname ))."</textarea>";
// 2nd try: no content at the textarea
echo "<textarea id='txtArea'>".sleep(10); htmlspecialchars(file_get_contents( $REGDIR.$corpusname ))."</textarea>";
// 3rd try: no content at the textarea
echo "<textarea id='txtArea'>".exit(); htmlspecialchars(file_get_contents( $REGDIR.$corpusname ))."</textarea>";
// 4th try: no content at the textarea
echo "<textarea id='txtArea'>".if(filesize($REGDIR.$corpusname) != 0) { echo htmlspecialchars(file_get_contents( $REGDIR.$corpusname )); } else { exit(0); sleep(10); htmlspecialchars(file_get_contents( $REGDIR.$corpusname )); }."</textarea>";
The command line you are using created a new thread that performs the task. PHP wont wait for it, as you do not refer the strout to php (but to /dev/null)
So, by changing the command, you can make PHP wait and thus get the result you expect.
Now I don't know for sure what the correct command is, but I would start with something like
$cmd = "/bin/bash $scriptfile"
Also have a look here. You want the opposite of what that guy wants. It does however give a bit more information about what the command actually does.
Even though the answer given by #Jeffrey is the right one, I realized that this answer is only good enough if the shell script takes short execution time, otherwise your php webpage can expire or hang up, so I gave another try with another php function: header('Refresh: x'), and that made it work right!
So here's what I get now:
// Run the corpus indexation script
$cmd = "/bin/bash $scriptfile > /dev/null 2>&1 &";
shell_exec($cmd);
<textarea id="txtArea" rows="28"><?php if (filesize($REGDIR.$corpusname) != 0) { echo htmlspecialchars(file_get_contents( $REGDIR.$corpusname )); }
else { header('Refresh: 0.5'); htmlspecialchars(file_get_contents( $REGDIR.$corpusname ));} ?></textarea>
UPDATE
Yet another solution:
do { echo htmlspecialchars(file_get_contents( $REGDIR.$corpusname )); } while (filesize($REGDIR.$corpusname) == 0);

How to write PHP script for cronjob that uses cat /dev/null > to reset log files

I could use some assistance in making a PHP script that I could add to a cronjob that would include multiple, (10 to 15), commands such as:
line1: cat /dev/null > /var/www/vhosts/website.com
/logs/access_log.webstat
line2: cat /dev/null > /var/www/vhosts/website.com/logs/big_access_log
line3: cat /dev/null > /var/log/plesk-roundcube/largefile.log
and so on. The commands work great from a command line, but doing this daily is time consuming and the files grow way too large even though they are being rotated. Any assistance would be greatly appreciated, thank you.
Could you possibly use the shell_exec command to complete these actions:
Example:
<?php
$output = shell_exec('cat /dev/null > /var/www/vhosts/website.com /logs/access_log.webstat');
echo "<pre>$output</pre>";
?>
Then just create a cron job to run them at interval times.
You can easily achieve the same result using native PHP code:
// The list of files to truncate
$listFiles = array(
'/var/www/vhosts/website.com/logs/access_log.webstat',
'/var/www/vhosts/website.com/logs/big_access_log',
'/var/log/plesk-roundcube/largefile.log',
);
// Process all the files in the list
foreach ($listFiles as $filename) {
// Open the file for writing ('w')
// Truncate it to zero length if it exists, create it if it doesn't exist
$fh = fopen($filename, 'w');
// Close the file; this commits the new file size to the disk
fclose($fh);
}
Thank you all for your assistance, the ending outcome is a awesome!
41 log files will no longer grow to gargantuan sizes. The implementation was as follows:
PHP script written as such:
<?php
$output = shell_exec('cat /dev/null > /var/www/vhosts/website.com/logs/access_log.webstat');
$output = shell_exec('cat /dev/null > /var/www/vhosts/website.com/logs/big_access_log');
$output = shell_exec('cat /dev/null > /var/log/plesk-roundcube/largefile.log');
?>
Then uploaded and set as a cron from the Plesk 12.5 panel. Tested and
functioning beautifully!
It's quite strange, by default this files should be rotated by psa-logrotate.
Maybe something happens with logrotate package or crontask.
Here is a default settings for rotating of domain's logs:

Equivalent of /dev/null for writing garbage test data?

I need to perform a series of test for picking the fastest branch of code for a set of functions I designed. As this functions output some text/HTML content, I would like to measure the speed without filling the browser with garbage data.
Is there an equivalent to /dev/null in PHP? The closest equivalent to write temporary data I've found are php://temp and php://memory but those two I/O streams store the garbage data and I want for every piece of data to be written in a 'fake' fashion.
I could always write all garbage data in a variable ala $tmp .= <function return value goes here> but I'm sure there must be a more elegant or a better way to accomplish this WITHOUT resorting to functions like shell_exec(), exec(), proc_open() and similar approaches (the production server I'm going to test the final code won't have any of those commands).
Is there an equivalent?
// For what its worth, this works on CentOS 6.5 php 5.3.3.
$fname = "/dev/null";
if(file_exists($fname)) print "*** /dev/null exists ***\n";
if (is_readable($fname)) print "*** /dev/null readable ***\n";
if (is_writable($fname)) print "*** /dev/null writable ***\n";
if (($fileDesc = fopen($fname, "r"))==TRUE){
print "*** I opened /dev/null for reading ***\n";
$x = fgetc($fileDesc);
fclose($fileDesc);
}
if (($fileDesc = fopen($fname, "w"))==TRUE)
{
print "*** I opened /dev/null for writing ***\n";
$x = fwrite($fileDesc,'X');
fclose($fileDesc);
}
if (($fileDesc = fopen($fname, "w+"))==TRUE) {
print "*** I opened /dev/null for append ***\n";
$x = fwrite($fileDesc,'X');
fclose($fileDesc);
}
I think your best bet would be a streamWrapper that profiles your output on write with microtime, that you can then stream_wrapper_register . The example in the manual is pretty good.
If your code is not that complicated or you fell this would be overkill, you can just use the ob_start callback handler
Hope this helps.

Show output taken from shell_exec and display it in real time instead of after waiting 5-7min

Right now, I have code as follows.
$output = shell_exec( !-- unix commands are here --! );
echo $output;
I have a website where, upon the clicking of a particular button, the shell script is outputted and it is displayed on the browser. This is working perfectly. The only issue is that I can't see what's happening with the output until it is finished. I have to wait about 5-7 minutes, and then I see about a hundred lines of output. I am trying to push the output to the browser as the output executes -- I want to be able to see the output as its happening in real time (on the browser).
I've tried to use popen, proc_open, flush(), ob_start, etc. Nothing seems to be working. I just tried opening a text file, writing the contents of the output to the textfile, and reading the textfile incrementally on a loop. I'm a php beginner so it's possible that I haven't been using any of the above methods properly.
What is the simplest way to accomplish this?
Because PHP runs exec, system, pass_thru, etc in blocking mode, you are very limited in possibilities. PHP will require the code to finish executing before moving on throughout the script, unless you do something like add the following to your command:
"> /dev/null 2>/dev/null &"
Of course, this will halt the output of your command, but.. maybe something like:
exec('command > /cmd_file 2>/cmd_file &');
$file = fopen('/cmd_file', 'r');
while (!feof($file)) {
echo fgets($file);
sleep(1);
}
fclose($file);
Worth a shot.

Execute multiple shell_exec at once?

How do I execute multiple shell_exec at once?
Also how do I switch each process to view output from test.php file? I need to know what each process (php file) is doing.
Take a look, example:
index.php
<?php
shell_exec("php test.php");
shell_exec("php test.php");
shell_exec("php test.php");
?>
That does not work how I wanted to be, first shell_exec (test.php) has to be completed first and then it will go to next shell_exec.
test.php
<?php
$section = rand(123,123);
$x = 1;
while($x <= 50) {
print $section . ": " . $x . "\n";
$x++;
sleep(1);
}
?>
It does not output when shell_exec is executed but when I type php test.php manually in shell, it does output.
Or is there a way to open multiple shells?
This is a quick example, however I will be executing multiple PHP file to run CURL
shell_exec("php test.php& php test.php");
Your best bet is to have those scripts log output to a file and actively parse it after running shell_exec().

Categories