Should I use flock when reading a file in PHP? - php

Ok so I am new to PHP and the example from the book shows that when I write to a file in php i should use flock($fp, LOCK_EX) after opening the file and then flock($fp, LOCK_UN) before closing the file. Like this:
$fp = fopen("$DOCUMENT_ROOT/order.txt", 'ab');
flock($fp, LOCK_EX);
fwrite($fp, $outputstring, strlent($outputstring));
flock ($fp, LOCK_UN);
fclose($fp);
But in the other example of how to read a file I am not sure if the author forgot to put flock() or it is not necessary to put flock() when reading a file. Here is the example:
$fp = fopen("$DOCUMENT_ROOT/order.txt", 'rb');
while (!feof($fp))
{
$order = fgets($fp, 999)
echo $order."<br/>";
}
fclose($fp);
So should I put flock() in the second example or not?
Thank you in advance.

It is only necessary to use flock if there are going to be multiple processes accessing the file at the same time.
If the code that writes to the file is only ever going to have have one copy running at any time, then you probably don't need to use flock. However if it is possible that multiple processes could try to run the code (and therefore access the file) at the same time, then you should use flock to make sure they do it one at a time.

Related

with php fopen() flock() file() Why does it work like this

so
if i fopen one file with a+ like
fopen($filepath,'a+');
file($filepath);
and then i use file($filepath) get the file contents it's ok
but why i when
i locked the file with flock i also can use file() function get the content
why ?
$fp = fopen($filepath, "a+");
while (1) {
$f =flock($fp,LOCK_EX);
if($f){
fwrite($fp,'abc');
echo "ok loked \n";
sleep(1);
$te =file($filepath);
if(strlen($te[0])==10){
echo "this is cont ".$te[0]."\n";
echo "ok this the end \n";
ftruncate($fp,0);
fflush($fp);
}
flock($fp, LOCK_UN);
break;
}
}
fclose($fp);
what about they relation?
when flock file the file()function is use the fopen resource?
file is independent function or use fopen?
fopen and file are two different functions.
fopen The fopen function does something entirely different—it opens a file
descriptor, which functions as a stream to read or write the file. It
is a much lower-level function, a simple wrapper around the C fopen
function, and simply calling fopen won't do anything but open a
stream.
file — Reads entire file into an array
flock is per process. So if the same process (including all threads) attempts flock multiple times it will always succeed.
Read the warnings at the end of the documentation:
https://www.php.net/manual/en/function.flock.php

Does PHP offer file concurrency in this scenario?

I have a cache file that is updated every hour or so. The file size ranges from 100KB to 1MB. The way the cache is updated is with the file_put_contents() method.
Only the server writes to the file. However, there is continuous access to the file. The file is accessed by users by a script that performs a one time read through readfile() to echo it to the user.
If the file is being read by the caching script, and the server runs the user reading script, or the other way around, would there be a problem? Or is this handled automatically by PHP>
Basically, you should lock the file while writing or reading. At least, it guarantees that there is no problem. It is the way of good programming!. The example is shown below.
<?php
$fp = fopen("/tmp/lock.txt", "w+");
if (flock($fp, LOCK_EX)) { // do an exclusive lock
fwrite($fp, "Write something here\n");
flock($fp, LOCK_UN); // release the lock
} else {
echo "Couldn't lock the file !";
}
fclose($fp);
?>
More information

php fopen() and fwrite() under heavy ddos attack

In normal condition , everything is ok, an I can write and create new files with fopen() and fwrite() but under "heavy" DDOS attacks , when file pointer is located at 0 , i cant write anything to file.eg. using "w" mod ,result will be a blank file , but by using "a" or "c" mod , if file not exist or be empty, nothing will be written (and just create a blank file too) , but if file has some characters , it will writes after characters or will clear and rewrite new characters respectively.
and when DDOS stopped , everything would be Ok.
here is simple code that I'm using for test, what is the problem? Can I fix it?
I'm using php5 in ubuntu with apache and lighttpd...
<?php
$fp = fopen('data.txt', 'w');
fwrite($fp, '1');
fputs($fp, '23');
fclose($fp);
?>
The way I understood the question is that you have problems running this code when there are multiple requests accessing the .php file (and thus the file you are writing to) at the same time.
Now, while it is far from being foolproof, flock() is there to help with this. The basic concept is that you'd ask for a lock of the file before writing and only write to a file if you're able to get the lock to that file, like
$fp = fopen( $filename,"w"); // open it for WRITING ("w")
if (flock($fp, LOCK_EX | LOCK_NB)) {
// do your file writes here
// when you're done,
// flush your file writes to a file before unlocking
fflush($fp);
// unlock the file
flock($fp, LOCK_UN);
} else {
// flock() returned false, no lock obtained
print "Could not lock $filename!\n";
}
fclose($fp);
You can read some more details from the manual entry or this article.

Can this fopen code be improved

I'm seeing that this code first creates the file, closes it, then opens it with 'a', writes to it, then closes it. Is there a way to simplify it. The idea is that if the file name exists, it needs to be overwritten. I also don't understand the point of unset. Is it necessary?
$fp = fopen($file_name, 'w');
fclose($fp);
unset($fp);
$fp = fopen($file_name, 'a');
fputs($fp, "sometext");
fclose($fp);
unset($fp);
From php.net, under the 'w' mode in fopen: Open for writing only; place the file pointer at the beginning of the file and truncate the file to zero length. If the file does not exist, attempt to create it.
In other words, open for writing, and overwrite or create as necessary. No need to use append mode.
$fp = fopen($file_name, 'w');
fputs($fp, "sometext");
fclose($fp);
file_put_contents($file_name, 'sometext');
And, No, unset() is pointless in your case.

file locking in php

I had a newcomer (the next door teenager) write some php code to track some usage on my web site. I'm not familiar with php so I'm asking a bit about concurrent file access.
My native app (on Windows), occasionally logs some data to my site by hitting the URL that contains my php script. The native app does not examine the returned data.
$fh = fopen($updateFile, 'a') or die("can't open file");
fwrite($fh, $ip);
fwrite($fh, ', ');
fwrite($fh, $date);
fwrite($fh, ', ');
fwrite($fh, implode(', ', $_GET));
fwrite($fh, "\r\n");
fclose($fh);
This is a low traffic site, and the data is not critical. But what happens if two users collide and two instances of the script each try to add a line to the file? Is there any implicit file locking in php?
Is the code above at least safe from locking up and never returning control to my user? Can the file get corrupted? If I have the script above delete the file every month, what happens if another instance of the script is in the middle of writing to the file?
You should put a lock on the file:
$fp = fopen($updateFile, 'w+');
if (flock($fp, LOCK_EX)) {
fwrite($fp, 'a');
flock($fp, LOCK_UN);
} else {
echo 'can\'t lock';
}
fclose($fp);
For the record, I worked in a library that does that:
https://github.com/EFTEC/DocumentStoreOne
It allows to CRUD documents by locking the file. I tried 100 concurrent users (100 calls to the PHP script at the same time) and it works.
However, it doesn't use flock but mkdir:
while (!#mkdir("file.lock")) {
// use the file
fopen("file"...)
#rmdir("file.lock")
}
Why?
mkdir is atomic, so the lock is atomic: In a single step, you lock or you don't.
It's faster than flock(). Apparently flock requires several calls to the file system.
flock() depends on the system.
I did a stress test and it worked.
Since this is an append to the file, the best way would be to aggregate the data and write it to the file in one fwrite(), providing the data to be written is not bigger then the file buffer. Ofcourse you don't always know the size of the buffer, so flock(); is always a good option.

Categories