Open batch file php [duplicate] - php

This question already has answers here:
How do you run a .bat file from PHP?
(7 answers)
php How do I start an external program running - Having trouble with system and exec
(3 answers)
Closed 3 years ago.
Before everyone starts butting in with "security risks" "cant be done" stop there and read the ENTIRE post
I have a web server set up from a home laptop which is serving as a games web server im trying to create a GUI so its easier for us to maintain the server and im trying to use batch files to do the actions on the computer
So to put this into perspective I have my index file index.php
<form method="post">
<input type="submit" name="startServer" value="Start Server">
</form>
<?
if(isset($_POST['startServer'])){
exec('batch/startServer.bat');
}
?>
And my startServer.bat will run on the laptop running the server and will do all the actions nesscary to start our game server so there is another directory "Instance" containing an excutable "Server.exe" which the batch file will run
The issue im having is running the web server and testing this it doesnt work if I open the batch file directly it works but it seems the php code doesnt work
For clarification I am using apache and my browser is chrome
And just a quick question for anyone willing to answer the route im going is correct right? Using php would allow everything to run on the machine hosting the server so the end user will only see the GUI and the server would run the batch files and everything on the web server and not the local machine if that makes sense?
EDIT: To be more clear about what's going on the function exec runs but it just hangs like the application is loading I need a solution that will actually open the application are my host computer for example if I wanted to open up notepad I press a button on the Web server and notepad will open on the computer
EDIT 2: I would like to note that I dont exactly need to use the exec function and I have tried all the answers to date 7/19/2017:3:45pm none are working if I do something on the sorts echo exec('start text.bat'); I will get a This is a test to show your batch is working and simply just have echo ..... in the batch file the main issue I am having is the server is not physically showing the opened file like displaying the GUI lets just take notepad for example
I can open notepad and get some return value as long as my batch file closes notepad once its finished running however the GUI for notepad is never displayed and thats very important
I read in a few articles about using apache as a service which im pretty sure I am but I do know that xaammp has suffiecient priveleges and I have checked the box that says "Allow apache to interact with desktop" however no GUI is popping up thats the main point I guess im trying to get across is I need to display the GUI not just open the file as a background service.
If it makes answering easier I am open to switching programming languages if theres one that can do what I want easier

Your theory is correct, it will run on the server however you may have issues running applications directly from php (with this method afaik it does not detach from the PHP, and the webapp "hangs" while the application is running).
Make sure: return values are printed / logged. Just an
<?php
if(isset($_POST['startServer'])){
echo exec('batch/startServer.bat');
}
?>
Could point you to the right direction. The exec function may have been disabled in your distribution.
Using
<?php
instead of
<?
is highly advised, by default short_tags are not enabled in most distributions (wamp, xamp, etc).
Set debug mode and print everything to get information about the problem:
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
if(isset($_POST['startServer'])){
echo exec('batch/startServer.bat');
}
?>
If you don't have any response, try a simple batch file with a "hello world" to test if it works.
Be aware, the rights and limitations are comes from the php environment, the batch file inherits the same rights running the PHP code / Apache (in case of mod_php)

In php manual about exec function, there is a note :
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.
I think "hangs like the application is loading" is your application waiting for the bat file terminated / closed to get the output result
Let's try another approach, i found it here, the concept is to create a scheduler that execute the program you want and call it using command.
hope this help :
shell_exec('SCHTASKS /F /Create /TN _notepad /TR "notepad.exe" /SC DAILY /RU INTERACTIVE');
shell_exec('SCHTASKS /RUN /TN "_notepad"');
shell_exec('SCHTASKS /DELETE /TN "_notepad" /F');
If this doesn't work
Check whether you have declared safe_mode = Off inside php.ini

From here:
How do you run a .bat file from PHP?
Have you tried:
system("cmd /c C:[path to file]"); ?

You might need to run it via cmd, eg:
system("cmd /c C:[path to file]");
Or Try following options
1.
<?php
exec('c:\WINDOWS\system32\cmd.exe /c START C:\Program Files\VideoLAN\VLC\vlc.bat');
?>
2.
When you use the exec() function, it is as though you have a cmd terminal open and are typing commands straight to it.
Use single quotes like this $str = exec('start /B Path\to\batch.bat');
The /B means the bat will be executed in the background so the rest of the php will continue after running that line, as opposed to $str = exec('start /B /C command', $result); where command is executed and then result is stored for later use.
<?php
pclose(popen("start /B test.bat", "r")); die();
?>

i think this is a containment issue.
if you run the app under the process of php run by iiswebuser when php terminates it will close all spawned child processes in windows. there is a very quick way a command to break an application out of the child process containment using the start command.
if(isset($_POST['startServer'])){
exec('start batch/startServer.bat');
}
Diagram of containment as i explained it (simplisticly)
IIS (IIS runs as an IISUser)
php (application)
cmd.exe (batch)
using start bring it to the root of that tree
IIS (IIS runs as an IISUser)
php (application)
cmd.exe (batch)

Baim Wrong was correct in the first part of the response: you have to redirect output of the script or your PHP code will hang. Also, you have to move process in the background.
This is easy to do on *nix:
system("/usr/local/bin/shell.sh >> /tmp/log.log 2>&1 &");
I know that you can redirect the output on Windows but not sure how to move the process in the background. You should check DOS manual or try with power shell.

you can use either system or exec php function
$path = __DIR__ . '/batch/startServer.bat';
exec('cmd /c start ' . $path);
or
$path = __DIR__ . '/batch/startServer.bat';
$lastLine = system('cmd /c start ' . $path);

You are having some issue about running application directly from exec. I was having the same issue of running file using exec. It was solved by passing another parameter 2>&1.
exec('some_command 2>&1', $output);
print_r($output); // to see the response to your command
Check the values printed by output see exec function
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
$output = array();
if(isset($_POST['startServer'])){
exec('batch/startServer.bat 2>&1', $output);
print_r($output);
} else {
echo "Not posted";
}
?>

Related

Asynchronous popen exec in PHP on Windows

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?

PHP exec to run a file

I am trying for last 3 hours to tell PHP to run a simple file. I am using wamp server for windows in local host (Windows 8)
I've tried with exec() working with:
echo exec('whoami');
I got response nt authority.
Also tested with:
if(function_exists('exec')) {
echo "exec is enabled";
}
So it probably works?
I am trying to run a file called tester.php
When I include it, its working, when I require it its working. I need to execute it in background. When I refresh file, code is working without any error, it writes to the database normally.
When i try to exec it its not working.
I tried :
exec("php http://localhost/diplomski/program/defender/tester.php");
exec("php-cli http://localhost/diplomski/program/defender/tester.php");
exec("http://localhost/diplomski/program/defender/tester.php");
Not working, also tried:
exec("php http://127.0.0.1/diplomski/program/defender/tester.php");
exec("php-cli http://127.0.0.1/diplomski/program/defender/tester.php");
exec("php-cli d:\wamp\www\diplomski\program\defender/tester.php")
Not working also tried:
exec("php tester.php");
exec("php-cli tester.php");
exec("tester.php");
Also tried:
$WshShell = new COM("WScript.Shell");
$oExec = $WshShell->Run("D:\wamp\bin\php\php5.3.13\php-win.exe -f d:\wamp \www\diplomski\program\defender/tester.php", 0, false);
Tried this, its refreshing infinitely and not working:
exec("php d:\wamp\www\diplomski\program\defender/tester.php");
exec("php-cli d:\wamp\www\diplomski\program\defender/tester.php");
exec("d:\wamp\www\diplomski\program\defender/tester.php");
I'm starting to pull my hair out here. First time I'm trying to use exec() and I'm not very good with it or with the commands.
Give the full path to the PHP executable and the full path to the PHP script. You can save the output in $output to see what the script produced:
exec("d:/path/to/php.exe d:/wamp/www/diplomski/program/defender/tester.php", $output);
print_r($output);
1) What version of php? If it is older then 5.4.0 php can be in safe mode, when safe mode is enabled, you can only execute files within the safe_mode_exec_dir.
2)Note to this function in php.net
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.
3) So you can try this How to make php script run another php script you can try this
<?php
$somearg = escapeshellarg('blah');
exec("php file2.php $somearg > /dev/null &");
4) You can create a scheduled task How to run a PHP file in a scheduled task (Windows Task Scheduler)
In addition to the earlier answers, let me add that if you want to execute a PHP file from within PHP, you may want to consider the PHP function include instead:
include $path."tester.php"
I guess that would be (much?) more efficient than to spawn a new shell which executes a new instance of PHP which executes the file. But of course the choice of the "better option" may depend on the context.

PHP - Can't open .exe files with exec command

I work with PHP 5.4, IIS 7.5.
If execute a simple command, it works:
<?php
exec("dir", $r);
print_r($r);
?>
But if open .exe file, it doesn't work, the page is loading until the php timeout and doesn't open the notepad:
<?php
exec("notepad.exe", $r);
print_r($r);
?>
And if execute the notepad's php in command line, it works:
php -f <file>
I think that the problem is with IIS, but I don't know what. Thanks!
UPDATE
I did another test case and doesn't work, the page finishes loading but doesn't delete the task:
<?php
$r = exec("SCHTASKS.exe /Delete /TN TaskTest /F");
print_r($r);
?>
The IIS_IUSRS have permission for execute the schtasks.
SOLUTION
Notepad doesn't open because is a interactive program.
For Tasks scheduler, gives read and write permissions to the task folder (C:\Windows\System32\Tasks) to IUSR.
What makes you think it isn't working?
Be aware that windows services cannot normally interact with the desktop, so it may be the case that notepad is starting, just not anywhere you can see it - and as PHP will wait for it to terminate, and nobody can see it to terminate it, it'll timeout, as you're seeing.
It may also be the case that the user that the web server is running as does not have execute permissions on the folder that notepad is in (assuming it had the relevant path).
The problem is that you are instructing exec to gather and return the output of the spawned process and the process must terminate for this to happen. Since Notepad does not terminate immediately PHP is stuck waiting forever (you can test this by running any non-interactive process instead, for example net.exe).
Takeaway: exec and friends are not meant to launch interactive processes.
In any case, exec will spawn a command interpreter which in turn will spawn Notepad. However, due to security features introduced in recent Windows versions, and depending on the user that IIS is running as, these processes will not create visible windows on your current desktop so there will be nothing for you to see. You will be able to verify that they were spawned using Task Manager or another equivalent program.

how to use php exec(), to run another script and run in the backround, and not wait for the script to finish

I am wanting to execute a large, database intensive script, but do not need to wait for the process to finish. I would simply like to call the script, let it run in the background and then redirect to another page.
EDIT:
i am working on a local Zend community server, on Windows 7.
I have access to remote linux servers where the project also resides, so i can do this on linux or windows.
i have this
public function createInstanceAction()
{
//calls a seperate php process which creates the instance
exec('php -f /path/to/file/createInstance.php');
Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('adminhtml')->__('Instance creation process started. This may take up to a few minutes.'));
$this->_redirect('instances/adminhtml_instances/');
return;
}
this works perfectly, but the magento application hangs around for the process to finish. it does everything i expect, logging to file from time to time, and am happy with how its running. Now all i would like to do is have this script start, the controller action does not hang around, but instead redirects and thats that. from what I have learnt about exec(), you can do so by changing the way i call exec() above, to :
exec('php -f /path/to/file/createInstance.php > /dev/null 2>&1 &');
which i took from here
if i add "> /dev/null 2>&1 &" to the exec call, it doesnt wait around as expected, but it does not execute the script anymore. Could someone tell me why, and if so, tell me how i can get this to work please?
Could this be a permission related issue?
thanks
EDIT : Im assuming it would be an issue to have any output logged to file if i call the exec function with (/dev/null 2>&1 &) as that would cancel that. is that correct?
After taking time to fully understand my own question and the way it could be answered, i have prepared my solution.
Thanks to all for your suggestions, and for excusing my casual, unpreparedness when asking the question.
The answer to the above question depends on a number of things, such as the operating system you are referring to, which php modules you are running and even as far as what webserver you are running. So if i had to start the question again, the first thing i would do is state what my setup is.
I wanted to achieve this on two environments :
1.) Windows 7 running Zend server community edition.
2.) Linux (my OS is Linux odysseus 2.6.32-5-xen-amd64 #1 SMP Fri Sep 9 22:23:19 UTC 2011 x86_64)
to get this right, i wanted it to work either way when deploying to windows or linux, so i used php to determine what the operating system was.
public function createInstanceAction()
{
//determines what operating system is Being used
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN')
{
//This is a windows server
//call a seperate php process to run independently from the broswer action
pclose(popen("start php /path/to/script/script.php","r"));
}
else
{
//assuming its linux, but in fact it simply means its not windows
// to check for linux specifically use (strtoupper(substr(PHP_OS, 0, 3)) === 'LIN')
exec('php -f /path/to/file/script.php >/dev/null 2>&1 &');
}
//the browser will not hang around for this process to complete, and you can contimue with whatever actions you want.
//myscript log any out put so i can capture info as it runs
}
In short, ask questions once you understand them. there are many ways to to achieve the above, and this is just one solution that works for my development and production environments.
thanks for the help all.
PHP popen
From the docs (this should help you do other stuff, while that process is working; not sure if closing the current PHP process will kill the opened process):
/* Add redirection so we can get stderr. */
$handle = popen('/path/to/executable 2>&1', 'r');
echo "'$handle'; " . gettype($handle) . "\n";
$read = fread($handle, 2096);
echo $read;
pclose($handle);
Solution 2:
Trick the browser to close the connection (assuming there is a browser involved):
ob_start();
?><html><!--example html body--></html><?php
$strContents=ob_get_clean();
header("Connection: Close");
header("Content-encoding: none");//doesn't work without this, I don't know why:(
ignore_user_abort(true);
header("Content-type: text/html");
header("Content-Length: ".strlen($strContents));
echo $strContents;
flush();
//at this point a real browser would close the connection and finish rendering;
//crappy http clients like some curl implementations (and not only) would wait for the server to close the connection, then finish rendering/serving results...:(
//TODO: add long running operations here, exec, or whatever you have.
You could write a wrapper-script, say createInstance.sh like
#! /bin/bash
trap "" SIGHUP
php -f "$1" > logfile.txt 2>&1 &
Then you call the script from within PHP:
exec('bash "/path/to/file/createInstance.sh"');
which should detach the new php process most instantly from the script. If that doesen't help, you might try to use SIGABRT, SIGTERM or SIGINT instead of SIGHUP, I don't know exactly which signal is sent.
I've been able to use:
shell_exec("nohup $command > /dev/null & echo $!")
Where $command is for example:
php script.php --parameter 1
I've noticed some strange behavior with this. For example running mysql command line doesn't work, only php scripts seem to work.
Also, running cd /path/to/dir && php nohup $command ... doesn't work either, I had to chdir() within the PHP script and then run the command for it to work.
The PHP executable included with Zend Server seems to be what's causing attempts to run a script in the background (using the ampersand & operator in the exec) to fail.
We tested this using our standard PHP executable and it worked fine. It's something to do with the version shipped with Zend Server though our limited attempts to figure out what that was going on have not turned anything up.

Problem using PHP exec command to execute a batch file

I'm attempting to get PHP to call a batch file which will take an RTF file and convert it to a PDF using an OpenOffice macro. I've tested the batch file on the command line and it works fine, but I'm not having any luck calling and using the same batch file from PHP.
My machine OS is XP professional SP 3. I'm running IIS 6 and PHP version 5.2.9.
I've granted execute permissions to the internet user on c:\windows\system32\cmd.exe.
I specified the full path to the batch file being executed and the full path to the RTF file to be converted.
The PHP looks like this where $arg is the RTF to be converted:
$arg = "C:\\web_root\\whatever\\tempOutput.rtf";
$command = "c:\\windows\\system32\\cmd.exe /c c:\\web_root\\whatever\\convert.bat $arg";
Then inside a try-catch I call the exec command:
exec("$command 2>&1 && exit", $ret, $err);
I echo the results after the catch:
echo "ret: ";
print_r ($ret);
print "<br>";
echo "err is ";
echo $err;
print "<br>";
echo "DONE!";
And this is what I see:
ret: Array ( )
err is 0
DONE!
The RTF file does not get converted and I'm not seeing the errors. Any ideas on what I can try next? Thanks!!!
I'm going to bet this is about permissions.
In a typical setup, PHP runs as apache - so you'll want to make sure apache has the rights to execute the batch file.
also, check this relevant SO question, and this google search.
Looks like the output array is empty. Is your batch script supposed to have output?
Also, escapeshellcmd and escapeshellarg should be used
Are you using IIS as your webserver? If so, the PHP exec function will not work by default and you should NOT circumvent the security measures that prevent it from running.
Check your event viewer and you should find some errors pertaining to your problem. Run a query through google for: IIS PHP exec. This should give you a large selection of information about the problem.
Basically, the PHP exec function tries to fork a new cmd.exe instance. IIS prohibits this because it could open a security hole in the system.
The best solution that I have come up with is to have your php script either write the command that you want to execute to a flat file or make a database entry. You will then need to write a seperate script that is launched by the windows scheduler to run every 10 minutes or so that will check your flat file or database for commands to run. The new script will then run the commands and then place either the results or an execution confirmation that your web app will be able to access at a later time.
It's a kludge for sure.
Is PHP running in safe-mode? If so, shell commands are escaped with escapeshellcmd. Perhaps this is the problem?
Do you have control of the server running the PHP script?

Categories