prevent file collision PHP with Matlab - php

i have php file that run from cmd matlab function -> that function is create .txt file and fill it up with the analysis results. then the php file takes this .txt file and sending the information as a string(lines from .txt) to a database (phpmyadmin).
my problem is that the php start to send the info from the .txt while the matlab is still writing to the file.
i thought to solve it with a global var that matlab and php know him, and use it as a flag that Flag determines when Matlab finished building the necessary file. i thought to use the window registry, but it is very complicated. there is any easier way?
thanks alot,
doron
my php file:
unlink('test.txt');
if(isset($_POST['filepath'])) {
$filename = $_POST['filepath'];
$inputDir = "C:\\xampp\\htdocs\\login";
$outputDir = "C:\\xampp\\htdocs\\login";
// here php open the matlab function from the cmd:
$command = "matlab -sd ".$inputDir." -r phpcreatefile2('".$outputDir."\\".$filename.".txt')";
exec($command);
$fileLoc= "".$outputDir."\\".$filename.".txt" ;
echo $fileLoc ;
echo "The following command was run: ".$command."<br/>";
echo $filename." was created in ".$outputDir."<br/>";
echo " Now the txt file will write in the DB <br/>";
// here i tried to check if the file exists and if it is not empty. but its not working because matlab still writing to the file.
while (1) {
if (file_exists("test.txt") ){
echo "check1";
if (filesize("test.txt")!= 0) {
echo "check2";
$file = file('test.txt');
$sql = "INSERT INTO `ID_5525_Medical_record`(`Data`,`AV_Power`,`Highest_Amp`,`90BW`,`Url_figure`) VALUES ('$file[0]','$file[1]','$file[2]','$file[3]','$file[4]')" ;
if(mysqli_query($connection,$sql))
{
unlink('test.txt');
echo "the txt file is now in the DB <br/>";
}
break;
}
else {
echo "i am going to sleep";
sleep(1);
echo "i am awake";
}
}
}
`

Normally, using COM would be the proper way to implement inter process communication between php and MATLAB (Or maybe some alternative, think all are sufficient for this simple task).
Here it seems you call MATLAB only one, you can fix the behaviour appending -wait to the command. This forces launcher to stay open until matlab closes, blocking your PHP-Script at exec($command);. Big disadvantage is, that you have to start Matlab for every function call and close it afterwards. With com one instance can stay open and do everything.

Related

Save the console text into a txt file? (PHP)

actual I finished writing my program. Because it is only a plugin and it runs on a external server I still want to see if I get some errors or something else in the console.
I wrote every console input with echo ...;. My question now is if it is possible to get the text of the console?
Because then I could easily safe it in a .txt file and could get access to it from the web :) - Or is there another way to get the console text?
I could probably just say fwrite(...) instand of echo ...;. But this will cost a lot of time...
Greetings and Thank You!
An alternative that could be usefull on windows would be to save all the output buffer to a txt, first check your php configuration for the console app implicit_flush must be off then
<?php
ob_start(); //before any echo
/** YOUR CODE HERE **/
$output = ob_get_contents(); //this variable has all the echoes
file_put_contents('c:\whatever.txt',$output);
ob_flush(); //shows the echoes on console
?>
If your goal is to create a text file to access, then you should create a text file directly.
(do this instead of echoing to console)
$output = $consoleData . "\n";
$output .= $moreConsoleData . "\n";
(Once you've completed that, just create the file:)
$file = fopen('output.txt', 'a');
fwrite($file, $output);
fclose($file);
Of course, this is sparse - you should also check that the file exists, create it if necessary, etc.
For console (commando line interface) you can redirect the output of your script:
php yourscript.php > path-of-your-file.txt
If you haven't access to a command line interface or to edit the cronjob line, you can duplicate the starndar output at the begining of the script:
$fdout = fopen('path-to-your-script.txt', 'wb');
eio_dup2($fdout, STDOUT);
eio_event_loop();
fclose($fdout);
(eio is an pecl extension)
If you are running the script using the console (i.e. php yourscript.php), you can easily save the output my modifying your command to:
php yourscript.php > path/to/log.txt
The above command will capture all output by the script and save it to log.txt. Change the paths for your script / log as required.

Php Lock files when writte

I am testing my code using little database in txt files. The most important problem that I have found is: when users write at the same time into one file. To solve this I am using flock.
OS of my computer is windows with xampp installed (comment this because i understand flocks works fine over linux no windows) However I need to do this test over linux server.
Actually I have tested my code by loading the same script in 20 windows at the same time. The firsts results works fine, but after test database file appears empty.
My Code :
$file_db=file("test.db");
$fd=fopen("".$db_name."","w");
if (flock($fd, LOCK_EX))
{
ftruncate($fd,0);
for ($i=0;$i<sizeof($file_db);$i++)
{
fputs($fd,"$file_db[$i]"."\n");
}
fflush($fd);
flock($fd, LOCK_UN);
fclose($fd);
}
else
{
print "Db Busy";
}
How it's possible that the script deletes database file content. What is proper way: use flock with fixing of existing code or use some other alternative technique of flock?
I have re-wrote the script using #lolka_bolka's answer and it works. So in answer to your question, the file $db_name could be empty if the file test.db is empty.
ftruncate after fopen with "w" is useless.
file function
Returns the file in an array. Each element of the array corresponds to a line in the file, with the newline still attached. Upon failure, file() returns FALSE.
You do not have to add additional end of line symbol.
flock function
PHP supports a portable way of locking complete files in an advisory way (which means all accessing programs have to use the same way of locking or it will not work).
It means that file function not affected by the lock. It means that $file_db=file("test.db"); could read file while other process somewhere between ftruncate($fd,0); and fflush($fd);. So, you need read file content inside lock.
$db_name = "file.db";
$fd = fopen($db_name, "r+"); // w changed to r+ for getting file resource but not truncate it
if (flock($fd, LOCK_EX))
{
$file_db = file($db_name); // read file contents while lock obtained
ftruncate($fd, 0);
for ($i = 0; $i < sizeof($file_db); $i++)
{
fputs($fd, "$file_db[$i]");
}
fflush($fd);
flock($fd, LOCK_UN);
}
else
{
print "Db Busy";
}
fclose($fd); // fclose should be called anyway
P.S. you could test this script using console
$ for i in {1..20}; do php 'file.php' >> file.log 2>&1 & done

overwrite zip file using php

I wrote a method to create a zip entry and rewrite it if this function is called second time but it is not working. here is my code:
public function zipFile($filepath,$fileName){
$zip = new ZipArchive;
$zip_name = $fileName.'.zip';
echo "$zip_name";
if($zip->open($zip_name, ZIPARCHIVE::OVERWRITE)===TRUE) {
$zip->addFile($filepath,$fileName.'.csv');
$zip->close();
echo 'ok';
} else {
echo 'failed';
}
return '/home/daily_reports/'.$zip_name;
}
what is missing in my logic. I want to replace the file with new one if the method is called again
Perhaps try explicitly deleting the zip file first if it exists. The overwrite option may not behave as expected.
clearstatcache();//For good measure clear out any cached file paths
$file = "{$filepath}/{$fileName}"
if(file_exists($file)){
unlink($file);
}
However, I have had mysterious issues trying to use the built-in zip functionality in php, especially with platform differences, performance, and memory issues. I prefer to zip the files on the command line through php.
On linux/osx:
$cmd = "zip archivefile file1 file2";
exec($cmd);
On windows use 7zip, also from the command line. http://www.dotnetperls.com/7-zip-examples
$cmd = "7za.exe a archivefile.7z file1 file2";
exec($cmd);
Technically you don't need to install 7zip, you just need the stand alone exe, but you might need to install it first to get the exe. http://www.7-zip.org/download.html

Calling a bash script from PHP to generate another script

I am writing an application which takes text input from the user to generate a text file. A bash script, which takes the generated text file as input should generate another script as output.
I tried using exec command but I am not sure if it works. I want something like this:
exec('generate.sh input.txt generated.sh');
generate.sh takes two inputs:
input.txt file - has user input from PHP page(text separated by '\n')
generated.sh - name of the generated file(to be generated by 'generate.sh').
How can I execute the bash script from PHP to get the above output?
Thanks in advance.
The whole argument to exec needs to be a string like this:
exec('generate.sh input.txt generated.sh');
$generate = '/path/to/generate.sh';
$input = '/path/to/input.txt';
$generated = '/path/to/generated.sh';
if(file_exists($generate))
{
chmod($generate, 0755);
if(file_exists($input))
{
exec($generate.' '.$input.' '.$generated);
}
else
{
echo "Input file not found: ".$input."<br />";
}
}
else
{
echo "Generate file not found: ".$generate."<br />";
}
Furthermore you can also consider system(), shell_exec(), passthru() or proc_open() to execute external commands.

PHP Pipe into a background process

I'm trying to use popen to run a php script in the background. However, I need to pass a (fairly large) serialized object.
$cmd = "php background_test.php >log/output.log &";
$fh = popen($cmd, 'w');
fwrite($fh, $data);
fclose($fh);
//pclose($fh);
Without the ampersand this code executes fine but the parent script will wait until the child is finished running. With the ampersand STDIN gets no data.
Any ideas?
You can try forking letting child process to write data and main script continue as normal.
Something like this
// Fork a child process
$pid = pcntl_fork();
// Unable to fork
if ($pid == -1) {
die('error');
}
// We are the parent
elseif ($pid) {
// do nothing
}
// We are the child
else {
$cmd = "php background_test.php >log/output.log";
$fh = popen($cmd, 'w');
fwrite($fh, $data);
fclose($fh);
exit();
}
// parent will continue here
// child will exit above
Read more about it here: https://sites.google.com/a/van-steenbeek.net/archive/php_pcntl_fork
Also check function pcntl_waitpid() (zombies be gone) in php documentation.
As far as I know there is no way in php to send a process in background and continue to feed its STDIN (but maybe I'm wrong). You have two other choices here:
Refactor your background_test.php to get its input from command line and transform your command line in php background_test.php arg1 arg2 ... >log/output.log &
If your input is pretty long, write it to a temporary file and then feed the background_test.php script with that file as in the following code
Example for point 2:
<?
$tmp_file = tempnam();
file_put_content($tmp_file, $data);
$cmd = "php background_test.php < $tmp_name > log/output.log &";
exec($cmd);
Make a background processes listen to a socket file. Then open socket file from PHP and send your serialized data there. When your background daemon receives connection through the socket, make it fork, read data then process.
You would need to do some reading, but I think that's the best way to achieve this. By socket i mean unix socket file, but you can also use this over the network.
http://gearman.org/ is also a good alternative as mentioned by #Joshua

Categories