Here I am writing about my flow in detail.
I am doing an Ajax request on same host.
AJAX call to saveUser.php
in saveUser.php, I have included Common.php.
Common.php have createFile1() and createFile2() function.
createFile1() function just creating a sample1.php for another purpose.
in createFile2(), I am creating a file sample2.php and executing a exec('php /home/public/sample2.php > /dev/null &'); command to execute that file.
I am calling this createFile1() and createFile2() function respectively from saveUser.php which is being called by an AJAX request.
As I have set the exec command to run in background by '&' at end of command, it is returning without waiting for the response and all goes smoothly in front.
But when I am checking on my server, these files sample1.php and sample2.php are getting created again and again. It seems all this saveUser.php action are getting executed again and again until I stops the sample2.php process from SSH.
I checked the processes list, each time 'php /home/public/sample2.php' is having new process_id, so it confirms that it is getting executed again and again. If I remove the exec() code and execute this sample2.php from SSH, it works as expected, there is not such problem.
Please suggest me whats going on wrong? Is there any problem with server configuration, I am using hostgator shared account.
Also I am including same Common.php file in sample2.php also, informing in case it can help it.
Thanks for your help in advance.
saveUser.php code
include_once dirname(__FILE__).'/Common.php';
createFile1();
createFile2();
echo 'saved successfully!';
Common.php code
function createFile1()
{
$template = file_get_contents('sendDmTemplate.php');
$serviceFp = fopen('sendDmFiles/sample1.php',"w");
fwrite($serviceFp , $fileContent);
fclose($serviceFp);
}
function createFile2()
{
$fileContent = file_get_contents(dirname(__FILE__).'/sampleFileTemplate.php');
$serviceFp = fopen('sample2.php',"w");
fwrite($serviceFp , $fileContent);
fclose($serviceFp);
exec('php '.dirname(__FILE__).'/sample2.php > /dev/null &');
}
sample2.php code
include_once dirname(__FILE__).'/Common.php';
echo 'hi';
This exact same thing happened to me. I was trying to have one php script call exec() on another php script but for some strange reason it would just exec() itself again creating an infinite loop. The currently accepted answer didn't get me anywhere, but I was able to get it to work by specifying an absolute path to php.
So, instead of
exec('php /home/public/sample2.php > /dev/null &');
it would be
exec('/usr/local/bin/php /home/public/sample2.php > /dev/null &');
Check the following:
1) Are you sure you are NOT calling your script saveUser.php multiple times? Mayby a codingerror somewhere in the javascript XHR? Check this by looking in the (apache?) log.
2) Are you sure your php executes alright without the -q? I use php -q pathtoscript.php
3) If not 1 or 2: Post the code in here (or somewhere) of saveUser.php
EDIT: I see your problem. The file you create includes common.php again, and executes that again. Etc. <-- wrong Oops. I wrote that too early. Looking into it again now.
4) Is it possible you use some errorhandling that redirects to your saveUser.php?
Edit:
5) There might arise a problem from the fact that you are including the file that is executing the command itself in combination with include_once, but I am not sure. You could simply test this by changing your content of sample2.php content by adjusting sampleFileTemplate.php. Create a common2.php (with identical content as common.php), and use that one. COuld you testdrive that setup and report back?
Related
I use phpseclib to SSH into my remote server from a web browser and execute a php file. Below is the code I use:
$ssh->exec('cd myfolder/; php main.php ' . $file, 'packet_handler');
function packet_handler(){
echo "Completed";
header("Location: exec_completed.php");
}
The main.php file gets executed without any issue. The problem is with returning the data after execution. I have the following questions:
I do a lot of processing in the main.php file and i need to show real time progress of what the script does. When i execute the file through exec, only the first echo in the main.php is printed and the execution stops. Is there any way to get real time data from the executing script.
I follow this example from phpseclib for callbacks although my callback function packet_handler doesn't run after exec is executed. I want to redirect to another page once the main.php I execute through SSH has completed its execution. Now if i redirect to that page i get only partial results as the main.php file has not completed its execution. I tried to use sleep(10) but my main.php may take longer times to execute at times so it didn't work. please suggest any ideas
Callback example from phpseclib:
<?php
include('Net/SSH2.php');
$ssh = new Net_SSH2('www.domain.tld');
if (!$ssh->login('username', 'password')) {
exit('Login Failed');
}
function packet_handler($str)
{
echo $str;
}
$ssh->exec('ping 127.0.0.1', 'packet_handler');
?>
For #1... doing $ssh->exec without the callback should work. If it doesn't I'd need to see the logs, which you can get by doing define('NET_SSH2_LOGGGING', 2) at the top and then echo $ssh->getLog() after. Posting the log at pastebin.com and then posting a link would be good. But that said, that won't get you real time output either.
For #2... the callback function is mainly intended for real-time updates and odds are very likely that what you'll get with each call of the callback function will be an incomplete output. So for your callback to output "Completed" and redirect the user to another location is, in all likelihood, incorrect.
Another approach that may work for you: use the interactive shell. Example:
http://phpseclib.sourceforge.net/ssh/examples.html#sudo,
I don't know what your output is like. Maybe you could read() until you got to certain parts of the output that are guaranteed to be output. Or maybe you could use $ssh->setTimeout(5) and get updated output every five seconds or something..
I'm having trouble executing the lessc compiler from PHP. I'm using Symfony, and have tried using the sfLESSPlugin, but have been unsuccessful. I've put my code in a filter that executes before the page renders, so that every time the page is refreshed, my LESS files are compiled into one CSS file (don't want to have recompile manually every time I make a change, at least while I'm developing). Here are the different variations that I've attempted:
$fs = new sfFilesystem();
$command = '/Users/jordanb/node/node_modules/less/bin/lessc less/bootstrap.less css/bootstrap.css';
try
{
$fs->execute($command, null, array($this, 'throwCompilerError'));
}
catch (RuntimeException $e)
{
return false;
}
This returns an error: "Problem executing command", with an error code of 127. Digging deeper into Symfony's execute(), it calls proc_open() and then proc_close(). Some research online told me that an error code of 127 means that the command was not found.
Running the exact same command on the command line works just fine.
To be extra sure, I executed chmod 777 on /Users/jordanb/node/node_modules/less/bin/lessc, just to make sure it wasn't a permissions issue. Still didn't work.
I also tried just "lessc" instead of the full path, which didn't work. I've added lessc to my classpath, so typing "which lessc" gives me "/Users/jordanb/node/node_modules/less/bin/lessc".
I also tried a simple:
shell_exec('lessc less/bootstrap.less css/bootstrap.css');
which didn't seem to do anything. I printed the output to the PHP error log as well as to a text file, and the output was empty in both cases. I also tried using the full path in this case.
You can make a shell script that compiles things the way you want:
compile_css.sh
/Users/jordanb/node/node_modules/less/bin/lessc less/bootstrap.less css/bootstrap.css
Then
chmod +x compile_css.sh
And finally call it from your script
$command = '/path/to/compile_css.sh';
This will give you more control over what you can execute, but if you still want to do it from php, try this:
$command = '/Users/jordanb/node/node_modules/less/bin/lessc "less/bootstrap.less css/bootstrap.css"';
// note the quotes around the arguments.
Hi there are multiple specific examples but I just wanted to have a working generic calling PHP into background example from shell_exec.
So my php function runs a large processing job.
On the top of the script (process.php) I put?
!#usr/bin/php
i think - any way to get that specific path, maybe 'which php'?
then the actual command is
shell_exec(sprintf('php process.php %s %s > /dev/null 2>/dev/null &','data1','data2'));
and access the data from process.php with argsv[1] and argsv[2]
?
thanks
You can definitely access the arguments from process.php the way you described, but why would you want to kick off process.php like that?
If you're already in a php shell script, why not just include the process.php file?
You need to run curl multi exec on your php script with a parameter and receive an answer after run, like: http://localhost/phpjob.php?par1=asdasd&par2=1212....
I have a PHP script that creates other PHP files based on user input. Basically, there are files containing language specific constants (define) that can be translated by the user. In order to avoid runtime errors, I want to test newly written files for parse errors (due to "unusual" character sequences). I have read several posts here on SO (like PHP include files with parse errors) and tried a function that uses
$output = exec("php -l $filename");
to determine whether a file parses correctly. This works perfectly on my local machine, but at on the provider's machine, the output of calls to exec("php ...") seems to be always empty. I tried a call to ls and it gives me output, leading me to the assumption that PHP is somehow configured to not react to command line invocations or so. Does anyone know a way around this?
EDIT: I forgot to mention, I had already tried shell_exec and it gives no result, either. In response to sganesh's answer: I had tried that too, sorry I forgot to mention. However, the output (second argument) will always be an empty array, and the return value will always be 127, no matter if the PHP file to test has syntax errors or not.
I had the same problem. The solution that worked for me was found in running-at-from-php-gives-no-output. I needed to add output redirection.
$output = exec("php -l $filename 2>&1");
You can try with exec second and third arguments.
second argument will have the output of the command.
third argument will have the return value.
And exec will return only last line of the command.
$filename = "a.php";
$output = exec("php -l $filename",$op,$ret_val);
print $output."\n";
print $ret_val."\n";
var_dump($op);
By executing shell_exec(), you can see the output as if you executed that file via command line. You can just see if there is an error right here.
<?php
if (strpos(shell_exec('php -l file.php'), 'Syntax Error')) {
die('An error!');
}
There may also be a possibility that shell_exec() or exec() may be disable by your host.
Nice idea to check the file validity :-)!
Now, from the PHP manual for exec():
Note: When safe mode is enabled, you can only execute files within the safe_mode_exec_dir. For practical reasons, it is currently not allowed to have components in the path to the executable.
Can you check if this is not the case for you?
Also, can you check by providing the full path of the PHP interpreter in the exec() instead of only php. Let me know how you fare.
Pinaki
the correct way is to add >2&1 as tested on a windows system using imagemagick!
I worked around my original problem by using a different method. Here is what I do now:
Write a temporary file with contents <?php include "< File to test >"; echo "OK"; ?>
Generate the correct URL for the temporary file
Perform HTTP request with this URL
Check if result equals "OK". If yes, the file to test parses without errors.
Delete temporary file
Maybe this could be done without the temporary file by issuing an HTTP request to the file to test directly. However, if there is a parse error and errors are suppressed, the output will be empty and not discernible from the output in the case of a file that gives no parse errors. This method is risky because the file is actually executed instead of just checked. In my case, there is only a limited number of users who have access to this functionality in the first place. Still, I'm naturally not entirely happy with it.
Why the exec() approach did not work, I still do not know exactly. pinaki might be right by suggesting to provide the full path to the PHP executable, but I cannot find out the full path.
Thank you everyone for answering, I upvoted you all. However, I cannot accept any of your answers as none of your suggestions really solved my problem.
So I am trying to execute some script from my php code. That lives in page blah.php
<?php
// ....
// just basic web site that allows upload of file...
?>
Inside I use system call
if (system("blah.pl arg1") != 0)
{
print "error\n";
}
else
{
print "working on it..you will receive e-mail at completion\n";
}
Works great but it waits until it completes until it prints working on it.
I am aware that I am calling perl script from php not a typo.
How can I just start program execution and let it complete in background.
The blah.pl script handles e-mail notification.
Anyone?
Thanks I appreciate it
From system function documentation:
Note: If a program is started with this function, in order for it to continue running in the background, the output of the program must be redirected to a file or another output stream. Failing to do so will cause PHP to hang until the execution of the program ends.
Simply redirect the output of your Perl script and PHP should be able to run without having to wait for the script to finish.
system("blah.pl arg1 > /dev/null 2>&1 &");
Can you add an ampersand to spawn the process in the background?
if (system("blah.pl arg1 &") != 0)
You could probably use the popen function
http://www.php.net/manual/en/function.popen.php
Since all the PHP command line functions wait for a result - I recommend that you have a separate page to call the emailer script.
In other words, send a request to the email.php page (or whatever) using cURL or the file wrappers which allows you to close the connection before receiving a result. So the process will look something like this.
page_running.php
|
cURL call to (email.php?arg1=0)
| |
final output email.php
|
calls system("blah.pl arg1")