-->

Rails.root points to the wrong directory in produc

2019-06-17 01:46发布

问题:

I have two jobs that are queued simulataneously and one worker runs them in succession. Both jobs copy some files from the builds/ directory in the root of my Rails project and place them into a temporary folder.

The first job always succeeds, never have a problem - it doesn't matter which job runs first either. The first one will work.

The second one receives this error when trying to copy the files:

No such file or directory - /Users/apps/Sites/my-site/releases/20130829065128/builds/foo

That releases folder is two weeks old and should not still be on the server. It is empty, housing only a public/uploads directory and nothing else. I have killed all of my workers and restarted them multiple times, and have redeployed the Rails app multiple times. When I delete that releases directory, it makes it again.

I don't know what to do at this point. Why would this worker always create/look in this old releases directory? Why would only the second worker do this? I am getting the path by using:

Rails.root.join('builds') - Rails.root is apparently a 2 week old capistrano release? I should also mention this only happens in the production environment. What can I do ?

回答1:

Rescue is not being restarted (stopped and started) on deployments which is causing old versions of the code to be run. Each worker continues to service the queue resulting in strange errors or behaviors.

Based on the path name it looks like you are using Capistrano for deploying.

Are you using the capistrano-resque gem? If not, you should give that a look.



回答2:

I had exactly the same problem and here is how I solved it:

In my case the problem was how capistrano is handling the PID-files, which specify which workers currently exist. These files are normally stored in tmp/pids/. You need to tell capistrano NOT to store them in each release folder, but in shared/tmp/pids/. Otherwise resque does not know which workers are currently running, after you make a new deployment. It looks into the new release's pids-folder and finds no file. Therefore it assumes that no workers exist, which need to be shut down. Resque just creates new workers. And all the other workers still exist, but you cannot see them in the Resque-Dashboard. You can only see them, if you check the processes on the server.

Here is what you need to do:

Add the following lines in your deploy.rb (btw, I am using Capistrano 3.5)

append :linked_dirs, ".bundle", "tmp/pids"
set :resque_pid_path, -> { File.join(shared_path, 'tmp', 'pids') }

On the server, run htop in the terminal to start htop and then press T, to see all the processes which are currently running. It is easy to spot all those resque-worker-processes. You can also see the release-folder's name attached to them.

You need to kill all worker-processes by hand. Get out of htop and type the following command to kill all resque-processes (I like to have it completely clean):

sudo kill -9  `ps aux | grep [r]esque | grep -v grep | cut -c 10-16`

Now you can make a new deploy. You also need to start the resque-scheduler again.

I hope that helps.