php Logging Issues - php

Code works fine, except for the fact that there is a problem here:
//Log Events
function logEvent($newinput) {
if ($newinput !== NULL) {
// Add a timestamp to the start of the $message
$newinput = date("Y/m/d H:i:s").': '.$newinput;
$fp = fopen('log.txt', 'w');
fwrite($fp, $newinput."\n");
fclose($fp);
}
}
//Problem writing these two lines to log.txt?
//The bad, the two lines below are not on the log.txt
logEvent('Selection'.$selections[$selection]);
logEvent('Change' . $change. 'cents.');
//This line is written to a text file (log.txt), okay that's good.
logEvent('Input' . $newinput);

i think you're not appending to the file, you're rewriting it. try fopen with 'a' instead of 'w'.

You need to use the append modifier when opening the file, you've gone
fopen('log.txt', 'w');
this means that every time you call that function, the log file is getting blown out and recreated, if you instead used
fopen('log.txt', 'a');
then your new log entries will append to the file instead.
You could also look into keeping the file open for later inserts too, but there may be issues with multiple updates in other requests.

Related

MAMP strange behaviour : php read external file from an http:// is very slow, but from https:// is quick

I have a simple PHP script to read a remote file line-by-line, and then JSON decode it. On the production server all works ok, but on my local machine (MAMP stack, OSX) the PHP hangs. It is very slow, and takes more than 2 minutes to produce the JSON file. I think it's the json_decode() that is freezing. Why only on MAMP?
I think it's stuck in while loop, because I can't show the final $str variable that is the result of all the lines.
In case you are wondering why I need to read the file line-by-line, it's because in the real scenario, the remote JSON file is a 40MB text file. My only good performance result is like this, but any good suggestion?
Is there a configuration in php.ini to help solve this?
// The path to the JSON File
$fileName = 'http://www.xxxx.xxx/response-single.json';
//Open the file in "reading only" mode.
$fileHandle = fopen($fileName, "r");
//If we failed to get a file handle, throw an Exception.
if($fileHandle === false){
error_log("erro handle");
throw new Exception('Could not get file handle for: ' . $fileName);
}
//While we haven't reach the end of the file.
$str = "";
while(!feof($fileHandle)) {
//Read the current line in.
$line = fgets($fileHandle);
$str .= $line;
}
//Finally, close the file handle.
fclose($fileHandle);
$json = json_decode($str, true); // decode the JSON into an associative array
Thanks for your time.
I found the cause. It is path protocol.
With
$filename = 'http://www.yyy/response.json';
It freezes the server for 1 to 2 minutes.
I changed the file to another server with https protocol, and used
$filename = 'https://www.yyy/response.json';
and it works.

How to rename() a file in PHP that needs to remain locked while doing so?

I have a text file which multiple users will be simultaneously editing (limited to an individual line per edit, per user). I have already found a solution for the "line editing" part of the required functionality right here on StackOverflow.com, specifically, the 4th solution (for large files) offered by #Gnarf in the following question:
how to replace a particular line in a text file using php?
It basically rewrites the entire file contents to a new temporary file (with the user's edit included) and then renames the temporary file to the original file once finished. It's great!
To avoid one user's edit causing a conflict with another user's edit if they are both attempting an edit at the same time, I have introduced flock() functionality, as can be seen in my variation on the code here:
$reading = fopen($file, 'r');
$writing = fopen($temp, 'w');
$replaced = false;
if ((flock($reading, LOCK_EX)) and (flock($writing, LOCK_EX))) {
echo 'Lock acquired.<br>';
while (!feof($reading)) {
$line = fgets($reading);
$values = explode("|",$line);
if ($values[0] == $id) {
$line = $id."|comment edited!".PHP_EOL;
$replaced = true;
}
fputs($writing, $line);
}
flock($reading, LOCK_UN);
flock($writing, LOCK_UN);
fclose($reading);
fclose($writing);
} else {
echo 'Lock not acquired.<br>';
}
I've made sure the $temp file always has a unique filename. Full code here: https://pastebin.com/E31hR9Mz
I understand that flock() will force any other execution of the script to wait in a queue until the first execution has finished and the flock() has been released. So far so good.
However, the problem starts at the end of the script, when the time has come to rename() the temporary file to replace the original file.
if ($replaced) {
rename($temp, $file);
} else {
unlink($temp);
}
From what I have seen, rename() will fail if the original file still has a flock(), so I need to release the flock() before this point. However, I also need it to remain locked, or rename() will fail when another user running the same script immediately opens a new flock() as soon as the previous flock() is released. When this happens, it will return:
Warning: rename(temporary.txt,original.txt): Access is denied. (code: 5)
tl;dr: I seem to be in a bit of a Catch-22. It looks like rename() won't work on a locked file, but unlocking the file will allow another user to immediately lock it again before the rename() can take place.
Any ideas?
update: After some extensive research into how flock() works, (in layman's terms, there is no guarantee that another script will respect the "lock", and therefore it is not really a "lock" at all as one would assume from the literal meaning of the word) I have opted for this solution instead which works like a charm:
https://docstore.mik.ua/orelly/webprog/pcook/ch18_25.htm
"Good lock" on your locking adventures.

How can I delay deletion of file until after new file is written?

I have a file in a directory that I would like to replace with a current version every hour. I use shell_exec() to zcat the file and the process of unzipping it and writing it takes about 4 minutes. Prior to this reading and writing, I record the name of the file which is already in the directory so that I can unlink it after the new file is done writing. But it doesn't happen in the order I would like it to. PHP executes the deletion while the shell_exec is processing. Only after four minutes of an empty directory do I see the newlly written file. Is there any way I can defer this deletion or make it a callback to both reading and writing processes?
$log_files = scandir("/cached_logs/");
foreach ($log_files as $key => $val){
//non-secure file to delete
if (preg_match("/^access/", $val)){
$log_to_delete= $val;
}
}
$ssl_command_string = "zcat log." . $datetime . ".gz";
//execute
$ssl_res = shell_exec($ssl_command_string);
//build the local directory and append the new file name with the current $datetime
$cached_ssl_file_name = "/cached_logs/log." . $datetime . ".txt";
//open the file handle
$new_ssl = fopen($cached_ssl_file_name, 'w') or die("can't open file");
//write
fwrite($new_ssl, $ssl_res);
//close
fclose($new_ssl);
unlink("/cached_logs/" . $log_to_delete); //this is defined properly above, I just didn't post it as it's irrelevant to the problem.
Edit:
cleared some things up and corrected syntax errors resulting from scrubbing out information
Sounds to me like something bizarre is going on. The main reason being AFAIK, shell_exec blocks, meaning it will wait until the command it's been given has run to completion before the next PHP statement will run.
I put together a minimal version of the sample script and it works fine for me.
<?php
$log_file = './my-access.log.gz';
$ssl_command_string = "zcat $log_file";
//execute
$ssl_res = shell_exec($ssl_command_string);
$cached_ssl_file_name = "./my-access.log.txt";
//open the file handle
$new_ssl = fopen($cached_ssl_file_name, 'w') or die("can't open file");
//write
fwrite($new_ssl, $ssl_res);
//close
fclose($new_ssl);
unlink($log_file);
if(is_resource($new_ssl)){
//Handle still open
fclose($new_ssl);
#unlink("cached_logs/" . $log_to_delete);
}

php variable save to file

I'm new in using PHP and I would like ask for this question;
I have variable
$content = $recfile[0]['name'];
This variable $content include name selected from mysql DB.
I would like variable $content save to the file.
I used:
$fp = fopen(DIR_PATH . "\\public\\temp\\myText.txt","wb");
fwrite($fp,$content);
fclose($fp);
I don't know where is the mistake. I tried various options as serialize or var_export but nothing worked.
If you are writing to a linux file system, you should use forward slashes
$fp = fopen(DIR_PATH . "/public/temp/myText.txt","wb");
You should also check if fopen worked. If fopen failed, the value of $fp will be false
if($fp) {
//code to write to the file
}
Have you checked if $content does indeed have any content (by f.i. echo $content;) and if your constant DIR_PATH holds the right path?
If those are correct, try forward slashes (though escaped backslashes should work)
$fp = fopen(DIR_PATH . "/public/temp/myText.txt","wb");
fwrite($fp,$content);
fclose($fp);

Editing a PHP File, with another php file, using Fwrite

My last question wasn't explained very well.
What I'm trying to do here is insert data into a PHP File, Using the fwrite feature on another .php file.
To keep this simple, I'm labelling the one I want data inserted as file.php and the one I'm using fwrite to execute on, is edit.php
Now, I got the writing thing down, what my problem is, is I need to INSERT that data, Before the closing php tag on file.php.
What I tried doing was, deleting the closing php tag, writing the data, and then rewriting the tag.
Here is my source code for that:
<?php
$rows = file("file.php");
$tagremove = "?>";
foreach($rows as $key => $row) {
if(preg_match("/($tagremove)/", $row)) {
unset($rows[$key]);
}
}
file_put_contents("file.php", implode("", $rows));
$User = $_GET["user"];
$File = "file.php";
$Handle = fopen($File, "a");
fwrite($Handle, "");
fwrite($Handle, $User);
fwrite($Handle, "\r\n");
fwrite($Handle, "?>");
print "Data Written";
fclose($Handle);
?>
When I run this on Edit.php, it inserts that data into the file, but its only writing to the first line, and replacing whatever is already there. (In my case its the opening php tag). I don't know what I'm doing wrong, or if there is another way to do this, but any assistance would be appreciated.
Edit: this is again for a chat client.
I'm having a file, that sends a message into a .txt file that the client then reads.
And that file is reading file.php (staff.php) to check if the user submitting is a staff member.
If it comes up true that the user is a staff member, then it changes the username variable in the send.php.
And so far, the send.php has only sucessfully, included the Staff.php, I've tried staff.txt, and the reason is, php code is in the staff.php.
Try this:
$data="echo 'hello world!';";
$filecontent=file_get_contents('file.php');
// position of "?>"
$pos=strpos($filecontent, '?>');
$filecontent=substr($filecontent, 0, $pos)."\r\n".$data."\r\n".substr($filecontent, $pos);
file_put_contents("file.php", $filecontent);
Please don't forget, that you need to check data from user.
Ok much better alternative use a data file. Ill use json because its easy to use an very easy to parse by human eyes as well:
// read file
$data = file_get_contents('data.json');
$json = json_decode($data, true);
// manipulate data
$json['users'][] = $_GET['user'];
// write out file
$dataNew = json_encode($json);
file_put_contents('data.json', $dataNew);
the reason is, php code is in the staff.php
Well this isnt something you workaround. You should be writing/reading this kind of information form a data stor - that could be a file or a database... but not an actual script.

Categories