This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
php exec command (or similar) to not wait for result
exec() waiting for a response in PHP
I have a php script that calls and runs a Matlab script. The result of the Matlab script is a .png image, which I would then like to load in php and send to a webpage. The php code I have is:
$matlabExe = '"C:\\Program Files\\MATLAB\\R2012a\\bin\\matlab.exe"';
$mFile = "'C:\\processSatData.m'";
$combine = '"run(' . $mFile . ');"';
$command = $matlabExe . ' -nodisplay -nosplash -nodesktop -r ' . $combine;
passthru($command);
$im = file_get_contents('C:\\habitat.png');
header('Content-type:image/png');
echo $im;
However, it appears that after sending the 'passthru' command, php does not wait for the Matlab script to finish running. Thus, if the image file does not exist before running the php code, then I get an error message.
Is there a way to make it so that the php code waits for the Matlab script to finish running before it attempts to load the image file?
passthru is not the main issue here .. but i guess as soon you have a response from your command the image is not written instantly but by a 3rd process
file_get_contents might also fail in this instance because .. The image might not be written once or in the process of writing which can result to file lock .. in any case you need to be sure you have a valid image before output is sent;
set_time_limit(0);
$timeout = 30; // sec
$output = 'C:\\habitat.png';
$matlabExe = '"C:\\Program Files\\MATLAB\\R2012a\\bin\\matlab.exe"';
$mFile = "'C:\\processSatData.m'";
$combine = '"run(' . $mFile . ');"';
$command = $matlabExe . ' -nodisplay -nosplash -nodesktop -r ' . $combine;
try {
if (! #unlink($output) && is_file($output))
throw new Exception("Unable to remove old file");
passthru($command);
$start = time();
while ( true ) {
// Check if file is readable
if (is_file($output) && is_readable($output)) {
$img = #imagecreatefrompng($output);
// Check if Math Lab is has finished writing to image
if ($img !== false) {
header('Content-type:image/png');
imagepng($img);
break;
}
}
// Check Timeout
if ((time() - $start) > $timeout) {
throw new Exception("Timeout Reached");
break;
}
}
} catch ( Exception $e ) {
echo $e->getMessage();
}
I believe if you change passthru to exec it will work as intended. You can also try this:
$matlabExe = '"C:\\Program Files\\MATLAB\\R2012a\\bin\\matlab.exe"';
$mFile = "'C:\\processSatData.m'";
$combine = '"run(' . $mFile . ');"';
$command = $matlabExe . ' -nodisplay -nosplash -nodesktop -r ' . $combine;
passthru($command);
// once a second, check for the file, up to 10 seconds
for ($i = 0; $i < 10; $i++) {
sleep(1);
if (false !== ($im = #file_get_contents('C:\\habitat.png'))) {
header('Content-type:image/png');
echo $im;
break;
}
}
Related
I am trying to update the Path environment variable in Windows with a PHP script, but if I use putenv() it doesn't change. I can get the paths list in the Path variable but I am not able to update it.
Another problem is that if I use getenv('Path') to get the paths list, I have a unique string with all paths merged from the Path variable of User and of the Machine.
I'm wondering if there is a better way to do that, maybe acting directly in the registry key to update User Path variable.
UPDATE
I think I found out a half-solution, but it doesn't work as expected.
What do I want to do?
I just want to make a script that allow me to switch from a PHP version to another changing the Path variable.
I made the script, it seems to work and the Path variable is successfully updated, but even if I close and reopen the cmd prompt if I type php -v it doesn't seems to get the updated var. If I open the Environment Variables windows, then open the "Path" variable and click on Ok and Ok again, then the refresh is got but the cmd prompt.
This is very strange to me, and if I have to do this everytime, then script loose its benefit...
I recorded a video, I hope it explain the problem better than my English...
https://1drv.ms/v/s!Ao2s4w8xSxBSh7RY4y5pB8u1g_QFSQ
This is the code of the script:
// Load PHP available versions
$laragon_php_paths = 'D:\www-servers\laragon\bin\php';
$php_paths = scandir($laragon_php_paths);
$path_var_name = "Path";
// Backup before doing a disaster
$date = new DateTime();
exec('REG EXPORT HKCU\Environment BackupUserEnvironment_' . $date->format('YmdHisv') . '.reg');
// Load registry key of user's Path environment variable
exec('REG QUERY HKCU\Environment /v ' . $path_var_name, $output, $result);
$path = explode(' ', $output[2]);
$path_array = explode(';', $path[count($path) - 1]);
// Get the current PHP Version and get the key of the item of the PHP bin path
foreach ($path_array as $key => $path_item) {
if (strpos($path_item, $laragon_php_paths) !== false) {
$the_key = $key;
$current_php_version = substr($path_item, strrpos($path_item, '\\') + 1);
}
}
echo 'Available PHP versions:' . PHP_EOL . PHP_EOL;
$i = 0;
foreach ($php_paths as $dir) {
if ($dir === '.' || $dir === '..') continue;
echo ' [' . ++$i . '] ' . $dir;
if ($dir === $current_php_version) {
echo ' [Current version]';
}
echo PHP_EOL;
}
// Get file descriptor for stdin
echo PHP_EOL;
echo 'Select a PHP version: ';
$fd = fopen('php://stdin', 'r');
$choice = (int) fgets($fd);
echo PHP_EOL;
// Check if choice is between 1 and number of choices
if ($choice > 0 && $choice <= $i) {
// Change the original php version with the new one
$new_php_version = $php_paths[$choice + 1];
$path_array[$the_key] = $laragon_php_paths . '\\' . $new_php_version;
echo 'PHP version changed to: ' . $new_php_version . PHP_EOL;
} else {
echo 'No allowed choice, nothing changed.';
echo PHP_EOL;
}
// Escape some chars for cmd
$new_path_var = str_replace(['%', ' '], ['^%', '" "'], implode(';', $path_array));
$cmd = 'REG ADD HKCU\Environment /f /t REG_EXPAND_SZ /v ' . $path_var_name . ' /d ' . $new_path_var;
// Execute
exec($cmd);
I am attempting to write a script which automatically unzips 7zip archives. I'm able to get the command to run from the command prompt, but it doesn't work when running from within the php script.
Here's what I have in terms of code:
$filefolder = "F:/dev/";
$filename = "archive.7z";
$filepath = $filefolder . $filename;
$unzip = "cmd /c 7z x " . $filePath . " -o" . $fileFolder . " -spf";
print_r($unzip . "<br>"); //checking to make sure the command is formed correctly
exec($unzip, $outcome, $rtnStatus);
print_r($outcome);
print_r($rtnStatus);
The following is returned for $outcome and $rtnStatus:
Array ( )
1
What am I missing here?
I am using php to execute a find command in linux for search a file in a directory and copy it into a other directory.
My php code is :-
<?php
include 'config.php';
$mxf = $_POST['year'];
$year = substr($mxf, 0, 4);
$ndrive = $_POST['ndrive'];
$command = 'find /var/www/html/collections/'.$year.'/ -name ' . $mxf . ' -exec cp {} ' . $ndrive . ' \;';
$stream = ssh2_exec($con, $command);
stream_set_blocking($stream, true);
$stream_out = ssh2_fetch_stream($stream, SSH2_STREAM_STDIO);
echo stream_get_contents($stream_out);
ssh2_exec($con, 'logout');
?>
Now i want that script return false if requested file is not found in directory or file not available on server. So how can i handle this type of error with ssh2_exec command.
The new "setPassword" method doesn't take effect (unless I've misunderstood it).
This is my example code:
<?php
$zipFilePath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'filename.zip';
$password = 'P455W0RD';
if (file_exists($zipFilePath)) {
unlink($zipFilePath);
}
$zipArchive = new ZipArchive();
$zipArchive->open($zipFilePath, ZipArchive::CREATE);
if ($zipArchive->setPassword($password)) {
echo 'OK' . PHP_EOL;
}
foreach (range(1, 10) as $fileNumber) {
$zipArchive->addFromString('file' . $fileNumber . '.txt', rand());
}
$zipArchive->close();
It does print "OK" in PHP 5.6.0beta3 (Debian Testing), but there is no password
in the zip file.
What am I missing?
I found a way to bypass the ZipArchive::setPassword() method. I simply wrote a shell script:
#!/bin/bash
command -v zipcloak && echo "exist" || exit -1;
command -v expect && echo "exist" || exit -1;
MYPWD="[password]"
expect -c '
spawn zipcloak [filename]
expect "*Enter password*"
sleep 0.1
send "'"$MYPWD"'\r"
sleep 0.1
expect "*Verify password*"
sleep 0.1
send "'"$MYPWD"'\r"
sleep 0.1
'
I can simply use exec from my php code:
public function encryptZip($filename, $password, $bashdir){
$bash = str_replace('[filename]', $filename, (str_replace('[password]', $password, file_get_contents($bashdir))));
exec($bash);
}
It works only on linux servers, where expect and zipcloak are installed.
if (strlen($log) > 0)
{
// Use "WScript.Shell" to run the command with no command prompt window pop up.
$wShell = new COM("WScript.Shell");
$cmd = "cmd /c cscript.exe \"%DIR%\\bin\\eventquery.vbs\" /l \"" . $log . "\" > \"%DIR%\\Temp\\event.log\" 2>&1";
////echo $cmd;
$return = $wShell->Run($cmd, 0, true);
if ($return == 0 || $return ==254)
{
$handle = #fopen(getenv('DIR') . "\\Temp\\event.log", "r");
if ($handle)
{
$linenum = 1;
while (!feof($handle))
{
$buffer = fgets($handle);
// Skip the first three lines
if ($linenum > 3)
{
echo $buffer;
}
$linenum++;
}
fclose($handle);
}
}
else
{
echo "Error running \"" . $cmd . "\" command.";
}
}
It gives an error on windows 7:
ERROR: Unable to include the common module"CmdLib.Wsc"
When I try run it from command line# windows 7, it works fine:
cscript.exe \"%DIR%\\bin\\eventquery.vbs\" /l \"" . $log . "\" > \"%DIR%\\Temp\\event.log\" 2>&1
Try using escapeshellarg:
$cmd = "cmd /c cscript.exe \"%DIR%\\bin\\eventquery.vbs\" /l \"" . escapeshellarg($log) . "\" > \"%DIR%\\Temp\\event.log\" 2>&1";
My guess is that you have shell metacharacters in $log.`
$a = 'all';
file_put_contents('ip.txt',shell_exec($dump = sprintf('ipconfig /%s',$a)));