views:

88

answers:

6

Hello

I have to write script in PHP which will be dynamicly replace some files on server from time to time. Easy thing, but the problem is that I want to avoid situation when user request this file during replacing. Then he could get uncompleted file or even error.

Best solution to me is block access to my site during replacing by e.g. setting .htaccess redirecting all requests to page with information about short break. But normally .htaccess file already exist, so there may be situation when server gets uncomplited .htaccess file.

Is there any way to solve it?

A: 

maybe do try it like this:

  1. delete file and save it's path
  2. ln -nfs movedfilepath pathtosorrypage.html
  3. upload file to some temporary folder on the server
  4. remove symlink
  5. mv newfile movedfilepath
dfens
+1  A: 

Doesn't this work already? I never tested for this specifically but I've done what you're doing and that problem never showed up. It seems like an easy thing for an operating system to

  1. Upload / write to a temporary file
  2. When writing is done, block access to the original file (make the request for the file wait)
  3. Delete the file, rename the temporary one and remove any locks

I'm fairly sure this is what an OS should do for copying. If you're writing the file contents yourself with PHP you'll just have to do this yourself...

Michael Clerx
+1  A: 

Try railless Capistrano or a method they use:

in a directory you have two things:

  1. A folder containering folders, each subfolder is a release
  2. A soft link to the current release folder

When you upload the new file, do the upload making a new release folder. Check to see that no one is currently running the current release (this might be a little tricky assuming you dont have a crazy number of users you could probably do it with a db entry) and then rewrite the softlink to point to the newest release.

Ken Struys
+5  A: 

Here's something that's easy, and will work on any local filesystem on linux:

  1. Upload (or write) the file to a temporary filename
  2. Move the file (using the mv (move) command, either in FTP, or command line, etc, or the rename command in PHP) to overwrite the existing one.

When you execute the mv command, it basically deletes the old file pointer, and writes the new one. Since it's being done at the filesystem level, it's an atomic operation. So the client can't get an old file...

APC recommends doing this to prevent these very issues from cropping up...

Also note that you could use rsync to do it as well (since it basically does this behind the scenes)...

ircmaxell
A: 

Option 1: If you have a lot of users and this replacing is done not so frequent, you can set up a maintenance on the site (block access) and have no one log in after a certain time, and finally cut off everyone who is logged in when you're about to do the replacement.

Option 2: If the file replacing is done frequently (in which case you shouldn't do the maintenance every day), have it done by code. Have two of the same files (same folder if you want). Then, by code, when you're about to replace the file, have it just give the copy, while you replace the one you want. You can do it with a simple IF.

Pseudo-code:

if (replaceTime - 15 seconds <= currentTime <= replaceTime + 15 seconds){
    // allows 30 seconds for another script to bring in the new image into 'myImage.jpg'
    <img src="/myFiles/myOldImage.jpg" />
} else {
    <img src="/myFiles/myImage.jpg" />
}

No need to update any database or manually move/copy/rename a file.

After replaceTime + 15 has passed:

copyFileTo("myImage.jpg","myOldImage.jpg");
// Now you have the copy ready for the next time to replace
elcool
A: 

Thank you so much for all answers, guys. You are briliant.

@ircmaxell Your idea sounds great for me. I read what dudes from PHP.net wrote and I don't know if I understand all correctly.

So, tell me: If I do all steps you wrote and add apc.file_update_protection to my php.ini, there will be no way to get uncompleted file by user by any time? There will be always one, correct file? Are you sure at 100% ?

It is very important to me coz these replacements will be very often and there is big chance to request file during renaming.

InterGadget