Here is the task:
I have a windows .cmd file that basically navigates to a given directory and runs a given Java program. I can directly run this file and it works just as I expect it to. However, I would like to run it from within a locally hosted php webpage and I would also like for this to be run asynchronously so that my webpage can make use of the data being produced by the java program.
I have tried several things that I was able to find online, including this proposed solution: PHP exec() as Background Process (Windows Wampserver Environment) but nothing seems to work for me.
I was under the impression that a function like this:
<?php
function runAsynchronously($path) {
$WshShell = new COM("WScript.Shell");
$oExec = $WshShell->Run($path, 7, false);
unset($WshShell,$oExec);
}
?>
when called with
runAsynchronously('notepad');
(for example), should open notepad and continue to run the php scrip from where it was called. However, nothing seems to happen when I do that. Any suggestions? Beware that I am not experienced with php at all, so I could be unknowingly doing something very stupid :)
Related
I am trying to build a small custom task scheduler. Basically the idea is I have cron run my process script, which looks in the database and finds any scheduled tasks that are ready to run, and runs them. So I think the best way to do this would be to try to launch the tasks "in the background" by way of shell_exec and using > /dev/null, which I understand makes it so the initial script (the process script) doesn't wait for the task scripts to complete.
So first, if there is a better way to achieve this, I'm open to suggestions. Though note I am on php 5.3 so there may be some options in 5.4 and up that I don't have access to :(
However here's the question at hand:
I am testing on WAMP on my windows machine and I am trying to make a call that looks like this:
shell_exec("php $path$base_url$querystring > output_test.txt 2>&1 &");
$path is the full windows path to the script
$base_url is the base url of the script I am calling
$querystring is of course the query string being passed to the task script
I am also outputting to output_test.txt which creates such file in same directory, where I get the following error:
Could not open input file:
C:\xampp\htdocs\email\batch_email_send_u2u.php?dealer=7
Yes I realize the path references an xampp installation, but that is not the issue - all the wamp files are executing from there and everything else has worked like this for years - it was just set up this way to support a legacy setup.
It seems to me shell_exec is locating and running php, it's just that it can't open the referenced script. Can't figure out why.
Also I need to eventually get this working on a real linux server so any advice on how to make that happen would be greatly appreciated!
Found a solution! Special thanks to dan08 for getting me set on the right path.
Ultimately I found the answer in this thread: Pass variable to php script running from command line
I ended up using the argv[] array as described in that post and with a little tweak to the script I'm calling it works like a champ now.
I am having a strange issue. I recently set up a process on our test servers to call a script asynchronously from another script. It has been working during testing, up until recently. Let me give some of the technical details before proceeding. The call from the originating script looks like this (I have updated the logic that makes the call):
exec('cmd /S /C "'.$command.' 1> nul 2>&1"');
Where $command is created using the following logic:
$args = array(
'php',
'"'.getcwd().'{absolute path to a php script}"',
escapeshellarg($job_id),
escapeshellarg($vhost),
escapeshellarg($debug),
);
$command = implode(' ', $args);
PHP version is 5.3.10 and the server is a hosted box running Windows Server 2008 R2 Standard.
I have verified that php is still in the system path
I have used debug output to see that the asynch call is being made, and what args it is being made with -everything still seems to be correct.
If I call the command contained in $command manually from the windows system terminal it runs as expected
If I run the $command as exec would run it (with 'cmd /S /C' it fails complaining that it cannot open the php script)
What really boggles my mind is that this was working this time last week. I made a few changes to the code (seemingly unrelated) and even after reverting my changes to see if that was the problem - this process is still broken.
At this point I am mystified and would welcome any insight, ideas or help.
Eventually I was able to simply get around this problem by not using popen or exec at all, it seems like those may be best avoided when using PHP on a Windows platform - if you are trying to create an asynchronous script call that is. Instead I resorted to the Windows COM object support in PHP.
$handle = new COM('WScript.Shell');
$handle->Run($command, 0, false);
This starts the process in the background (hides window/does not open a new window) and executes it asynchronously - i.e. does not wait for it to finish.
Included here is the documentation page for WScript.Shell which gives the official description of the effect(s) of the parameters passed. Although I did not stop to benchmark it, I will say that anecdotally it feels that his process now runs more quickly than it used to when I was trying to use exec/popen/etc.
Rather than redirecting the output to nul, try redirecting everything to a file. That should tells you if there's a PHP error somewhere:
$outFilePath = "/path/to/file.log";
pclose (popen('start /B cmd /S /C "'.$command.' > ' . $outFilePath . ' 2>' . $outFilePath . ' &"',"r") );
Also is there any reason you are using pclose / popen rather than something more simple like exec?
Basically my situation is as follows.
Upload file
Run external process on file (which generates another file)
When external process is down, process the generated file.
Currently in PHP I run the program as follows:
$cmd = 'cd the_directory/; ./the_program'
system($cmd);
The program runs fine and everything, but the program at the end says "Press Enter to exit..." And thus Apache is hanging indefinitely as this program is waiting for user input. Our partner declares that they have this program integrated into their backend flawlessly and does not experience this issue. Up until now all external programs that i have executed in PHP exit without requiring user input which seems to be the norm for this situation.
It seems to me that the code should just simply not have the end message requiring user input. Am I missing something? Or is there a way to get around this? Or do they just need to change their code?
Thanks!
I think you should try proc_open.
With it you can not only execute an external command as a process, but also set pipes to get and send information to that process.
Take a close look to the third parameter of this function, and study the example in the PHP manual for this function, where you can see something like this:
fwrite($pipes[0], '<?php print_r($_ENV); ?>');
so, you can write what you need to the input pipe of the process you've just opened.
if you use Windows environment:
$run_cmd = "cmd /c c:/app_folder/app.exe";
$WshShell = new COM("WScript.Shell");
$oExec = $WshShell->Run($run_cmd, 0, false);
Note that the latter will cause the process window to close on end
If you use UNIX (haven't tested it myself yet):
exec('\app_folder\app &');
I have a PHP website and I would like to execute a very long Python script in background (300 MB memory and 100 seconds). The process communication is done via database: when the Python script finishes its job, it updates a field in database and then the website renders some graphics, based on the results of the Python script.
I can execute "manually" the Python script from bash (any current directory) and it works. I would like to integrate it in PHP and I tried the function shell_exec:
shell_exec("python /full/path/to/my/script") but it's not working (I don't see any output)
Do you have any ideas or suggestions? It worths to mention that the python script is a wrapper over other polyglot tools (Java mixed with C++).
Thanks!
shell_exec returns a string, if you run it alone it won't produce any output, so you can write:
$output = shell_exec(...);
print $output;
First off set_time_limit(0); will make your script run for ever so timeout shouldn't be an issue. Second any *exec call in PHP does NOT use the PATH by default (might depend on configuration), so your script will exit without giving any info on the problem, and it quite often ends up being that it can't find the program, in this case python. So change it to:
shell_exec("/full/path/to/python /full/path/to/my/script");
If your python script is running on it's own without problems, then it's very likely this is the problem. As for the memory, I'm pretty sure PHP won't use the same memory python is using. So if it's using 300MB PHP should stay at default (say 1MB) and just wait for the end of shell_exec.
A proplem could be that your script takes longer than the server waiting time definied for a request (can be set in the php.ini or httpd.conf).
Another issue could be that the servers account does not have the right to execute or access code or files needed for your script to run.
Found this before and helped me solve my background execution problem:
function background_exec($command)
{
if(substr(php_uname(), 0, 7) == 'Windows')
{
pclose(popen('start "background_exec" ' . $command, 'r'));
}
else
{
exec($command . ' > /dev/null &');
}
}
Source:
http://www.warpturn.com/execute-a-background-process-on-windows-and-linux-with-php/
Thanks for your answers, but none of them worked :(. I decided to implement in a dirty way, using busy waiting, instead of triggering an event when a record is inserted.
I wrote a backup process that runs forever and at each iteration checks if there is something new in database. When it finds a record, it executes the script and everything is fine. The idea is that I launch the backup process from the shell.
I found that the issue when I tried this was the simple fact that I did not compile the source on the server I was running it on. By compiling on your local machine and then uploading to your server, it will be corrupted in some way. shell_exec() should work by compiling the source you are trying to run on the same server your are running the script.
I have a PHP script that calls a .bat file using system(). The output is written to the screen and I derive some values from parsing this output. This is running on windows 2003 IIS server. PHP v5.2.0
Specifically I am using this script to launch an Amazon EC2 instance and assign an IP address to it. It has worked great for me so far but recently the problem started.
Here is the code
$resultBatTemp = system("cmd /C C:\Inetpub\ec2\my_batch_file_to_launch_instance.bat");
$resultBat = (string)$resultBatTemp;
$instanceId = substr($resultBat, 9, 10);
...
Once I have this instace Id I can run another batch file that calls associates an ip address with this instance. It would appear that the instance does get launched but I never get the output on the screen.
For some reason this has all stopped working, the page freezes and never refreshes. I also need to completely exit safari or mozilla otherwise all pages from the website fail to load. Only when I relaunch the browser can i view the website again. I've connected to the webserver that hosts these scripts and checked PHP error log but nothing shows there. I've opened a DOS prompt and entered the code from the bat file that way and it connects to amazon and launches the instance fine. Ive isolated this bit of code and removed the system command and the rest of the script runs fine, so it appears that the hold up is with outputting the results of the bat file.
Recently I have purchased a new domain name for the site so this script is running from this domain. Might this cause the problem?
thanks
------------------------------------------------UPDATE-----------------------------------------------
Well hope this helps someone, I didnt find out what was wrong but created a new PHP file with a simple system command that called a .bat file, and a non-existent .bat file expecting to get an error back but nothing - just the usual hang for ages. So I restarted IIS and this fixed the problem. Dont know what was wrong but that did the trick.
Maybe first check what the system() call returns. According to documentation it will return FALSE in case of failure. Also, including your my_batch_file_to_launch_instance.bat in the question might help in solving it.
Try using the passthru function
Also make sure that all your commands are safe use escapeshellarg() or escapeshellcmd() to ensure that users cannot trick the system into executing arbitrary commands.