I've deployed my Rails application to Heroku following https://devcenter.heroku.com/articles/rails3 and can open a website like http://severe-mountain-793.herokuapp.com
In my controller, I have a system command that downloads a file into the public directory with system('wget', ..., Rails.root.join('public/...')). Apparently, from checking the exit status of the command, I realize that the command fails. But I don't know why it fails, and I don't know how to show the output message of the command. What can I do?
I think heroku's filesystem is read-only, so you can't really save files using wget, except if you want to save them inside the '/tmp' folder, where they could be deleted anytime. Moreover, dynos have a 30 seconds timeout, so this would fail for every download which takes more than that interval.
Related
I am generating PDF document and storing it temporarily to the /tmp directory. Once the document is generated and stored in the directory (I am doing it as a background process with Sidekiq), then I upload it to Amazon S3 and delete it from the /tmp directory.
What I noticed is that when a user generate a document and I am deploying some new code to the server (with using Capistrano), the process of generating/uploading document is interrupted.
I was wondering if this might be related to Sidekiq? It's running as an Upstart service on Ubuntu, so I don't think so.
Then I thought the problem might be that I am storing the document in the /tmp directory. How the directory works? Is the whole content of the directory deleted when I do a new deployment with Capistrano?
EDIT:
The document generation takes usually takes 5-10 seconds, but the queue is default, so the process might fail because there's too many default processes in the queue?
The /tmp directory should be cleaned only during server boot (as #Зелёный already commented). But your PDF generation / upload might just take too long and the process might get killed. This is documented here and I quote from the docs:
sidekiqctl stop [pidfile] 60
This sends TERM, waits up to 60 seconds and then will kill -9 the Sidekiq process if it has not exited by then. Keep in mind the deadline timeout is the amount of time sidekiqctl will wait before running kill -9 on the Sidekiq process.
The details should be shown in the console output during the capistrano deployment, so if it's not the case of process getting killed, please add the output to the question.
I deployed "Harrys Prelauncher" on Heroku and try to do the teardown (currently just testing). See here: https://github.com/harrystech/prelaunchr#teardown
After running the rake task ...
heroku run rake prelaunchr:create_winner_csvs
... a csv file is created in "/lib/assets", but I dont know how to access the file (it works locally in development).
How can I download or access the file?
Heroku uses "ephemeral" filesystem that is not guaranteed to preserve changes made at runtime. Simply put, if it's not pushed to git (I assume you're using git with heroku), it's not guaranteed to exist in all the instances of your app. It may exist in one of them, but you may have no simple way of accessing that specific filesystem. And you shouldn't, really.
It's done like that so that multiple instances of the same app can be fired up seamlessly. Of course, that requires some discipline: storage of any meaningful state outside: in the database, on external disk, anywhere. The benefit of this is horizontal scalability: should you be short on resources, you can fire up another web dyno that would (normally) behave exactly the same way. New dynos are started from bundles that are packed on git push and thus do not contain any changes you may have made in another instance.
A workaround may be running heroku run bash, so that you end up in an interactive shell linked to another instance of your bundle.
Then you can make that file (by running your rake task) and access its contents in any way you deem reasonable. Text files can be echoed into the console with cat and copy-pasted anywhere else. That's a dirty way.
A much cleaner way would be rigging the app to send the file in question via email. and it's one of the few reasonable ways if that rake task is invoked by the Rails app itself.
I ran into this problem recently while developing the Prelaunchr campaign for a client. Assuming you have a local version of your app, you can "pull" your Heroku database down to your local machine, set that as your development database in database.yml, and run the rake task from your local app, which should now have the same database as your heroku version. Here is the command to pull the db (subbing out name_for_database & heroku_app_name with your own):
heroku pg:pull HEROKU_POSTGRESQL_COPPER_URL name_for_database --app heroku_app_name
Make sure to restart your local server to see the new database info populated.
I have a Redmine (www.redmine.org) installation pushed up onto Heroku (cedar stack). On my local instance of Redmine, the way file uploads work is that the database simply stores some data about the file including a name and the location of the file on disk, and the file itself is just stored on disk under [app-location]/files (Redmine is a ruby-on-rails application). When my Redmine project is pushed to Heroku, the files directory is nowhere to be found. From what I've read about Heroku's filesystem, this is no surprise. But what is surprising and confusing, is that file uploads still work and I didn't setup s3 which is the common recommendation for file uploads on Heroku. I checked the Heroku database to get the data about the file upload.
Here are the steps I took to locate the file.
heroku run rails c
and – to get the location of the most recent file – ran:
Attachment.last.diskfile
which returned:
=> "/app/files/2014/06/140610184025_Very-Basic-Globe-icon.png"
This path simply does not exist on the Heroku instance (using heroku run bash and listing directories or running a find). I also downloaded a dump of the Heroku database and imported it locally. The database data shows up on my local instance, but the file can't be found (no surprise).
So my questions are:
Where is the Heroku instance storing the files really?
Is there a way for me to back those files up locally without relying
on Amazon s3?
This app should remain fairly small, so I am not concerned about massive scalability, I just want to be able to get the file uploads if one day needed.
I know this question is a bit old, and you may have already found a solution, but just in case other people stumble on this question:
Heroku really is storing the files where it says it is. What's happening when you run heroku run bash is Heroku is spinning up a one-off dyno to run the command. This means that you will not be given a command prompt in the dyno that is actually running your app. This is why you are not able to find the file you're looking for.
There are currently no official addons that support backing up physical files (only databases), however you could write your own custom script to back up your data to where ever you choose (s3 or otherwise). To do so, you will likely need to use Heroku Scheduler to run your backup script in a cron-like way.
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
?
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.
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.
This is my first deployment. I did a cap deploy:setup which worked fine.
Then, when I try to execute cap deploy:update I run into error messages. Something along the lines of
rm: cannot remove `/var/www/app_name/current': Is a directory
Here is my capfile and directory permissions.
http://pastie.org/1189919
In general, what is the best practice as far as deployment user and permissions are concerned? Should I use root or create a different user. If a different user what exact permissions does it need?
Thanks
Did you create the directories within /var/www/app_name, or were they created by capistrano?
Regardless, the issue you have is that /var/www/app_name/current should not be a directory - it should be a symlink to the current release within /var/www/app_name/releases/. The failure is caused when capistrano has finished creating the new release folder within /var/www/app_name/releases/, and is trying to symlink /var/www/app_name/current to it.
You might be able to fix your issues by renaming /var/www/app_name/current (so you have a backup if things go wrong), and creating a symlink from /var/www/app_name/current to the most recent release within /var/www/app_name/releases/, and then doing a cap deploy. (Delete your backup of current if this works).
As far as best practice goes whatever you do, do not use root. Instead, set up a user (or use an existing user) that has only permissions to the required directories (didn't read your scripts closely, but probably just /var/www/app_name.
To deploy a new release you should invoke cap deploy or cap deploy:migrations, not cap deploy:update.
I also have had such errors. A totally normal task of updating source code and restarting the server always seems to have problems at various points of the simple script.
Sometimes it complains that a hash value at github doesn't match some expected value, sometimes it won't update a directory because it already exists, but mostly with it wanting to create things that exist.
Is there no way to force Capistrano and thus the shell commands to just DO IT ? I would at least appreciate it asking me what it should do should it encounter this type of error instead of just failing and rolling back. Especially when it's a simple file operation.
I end up having to delete things manually on the server so that the Capistrano script will run without failing. This is obviously not the way forward.