Deploying While Application is Running

We often get:
Copying package contents to '…'
Error 14:04:51
Unable to copy the package to the specified directory ‘…’. One or more files in the directory may be locked by another process. You could use a PreDeploy.ps1 script to stop any processes that may be locking the file. Error details follow.
The process cannot access the file ‘…\app.exe’ because it is being used by another process.
System.IO.IOException: The process cannot access the file ‘…\app.exe’ because it is being used by another process.

We could run a script to kill the app beforehand, but we don’t want to. Oftentimes we want the existing run to finish (sort of like a dirty read) while deploying, yet we don’t want Octopus to have to wait until the app is done to deploy.

We’ve devised a script, based on a thread that I’ve posted at http://stackoverflow.com/q/30649848/1378356 regarding this very issue which moves the app into another folder and it continues to run even though it was moved, since it’s already in RAM. However, we still get the above Octopus error. Apparently, Octoups is trying to overwrite the entire folder, not merely its contents, and that’s something that Windows will not allow to be done while the app is running (even though the app is no longer in that folder, since it was there at the time the app was invoked).

Suggestions were made to create a table in SQL Server which dictates when an app should be running, or which folder it should be running from. However, all these ideas are workarounds which add a big level of complexity which shouldn’t really be needed. Frankly, we can also just copy and paste the files over SMB or RDP, but we purchased Octopus so that we can streamline the deployment process, not complicate it.

Is there a solution you’d recommend which would allow us to just copy over files, not the folder itself, or perhaps you have an alternate way of deploying to running applications?

Thanks so much for your time,

Hi,

Thanks for getting in touch! You’re right, we do want Octopus to make deployments simpler and more reliable. Can I confirm your specific situation? From reading the StackOverflow post it appears you are using Octopus to deploy executables that get run as SQL Server Agent jobs, potentially on a schedule or some other trigger. Given that is the case I can understand you want the job to run through to completion! I also understand it may seem convenient to deploy to the same location on disk since you don’t have to reconfigure your SQL Server Agent job to point to a new location. Here are some recommendations that I hope will help you.

I would personally avoid updating any files that belong to a running process, even if they aren’t locked. Depending on the circumstances you may inadvertently replace a file with a newer version that hasn’t been loaded by the running process, which may have unexpected side-effects. So I’d avoid finding a work-around to the locked file problem you mentioned.

Instead I would recommend leaving the previous version intact and let it run to completion, allow Octopus to deploy the next version intact and complete into a new location and use a Deploy.ps1 script to update your SQL Server Agent job with the new location of your executable.

Out of the box this is what Octopus does for IIS hosted ASP.NET Web Sites (even though files aren’t locked because they are shadow-copied) and Windows Services (where files are locked), and we do this because this method has many advantages giving you the best chance at always having successful deployments with minimum downtime.

For IIS hosted ASP.NET Web Sites we leave the previous version intact and complete, deploy the next version to a new location on disk, and finally update the IIS configuration to the new location on disk.

For Windows Services we leave the previous version intact and complete, deploy the next version to a new location on disk, stop the Windows Service, reconfigure it to use the new location on disk, and start the Windows Service again.

To round this conversation out, my recommended process would be:

  1. Allow Octopus to deploy your code to its default location, which by convention creates a new folder for each deployment
  2. Add a Deploy.ps1 script to your package that executes a SQL Script to update your SQL Server Agent Job step(s) using the sp_update_jobstep with the @job_id and @command parameters.
  3. Allow Octopus to clean up old versions using Retention Policies

This means your current version can complete its run successfully, and the very next time the job is executed it will use the new version.

Some links that may be helpful:

Hope that helps!

Mike

Wow! I wasn’t expecting such a thorough answer. Thanks! I’ll look into the pattern you suggested.

Mike,

What do you mean when you say that Octopus deploys to another folder? For IIS deployments I always see it go to the same folder.

Hi,

Thanks for getting back to us! Are you specifying the CustomInstallationDirectory variable? I would have assumed so since you are trying to replace the existing files.

Take a look here for more information: http://docs.octopusdeploy.com/display/OD/Custom+Installation+Directory

As mentioned in that article we always unpack your packages into a working directory like this: C:\Octopus\Applications\[Environment name]\[Package name]\[Package version]\

Hope that helps!

Mike

Hi,

I haven’t heard from you in a while. I’m hoping you’re having success with your deployments now!

Feel free to get in touch again if we can help you further!
Mike