It takes too long to prepare for running rake
in a Ruby on Rails application after logging in to the host, so let's combine it into one command, ʻappdo`.
If you put Ruby in rbenv or rvm, you will not be able to find ruby
when executing commands with sudo
or cron
. Well, you should read ~ / .bashrc
etc. every time, but doing so complicates the command. If the number of places where such processing is performed increases, correction omissions are likely to occur. It's packed.
When running a Ruby on Rails application, neither bundle exec rake
nor bin / rails runner
can be executed without further cd $ RAILS_ROOT
. As a result, operational commands become longer and longer, making crontab
and config / deploy.rb
difficult to maintain. It's packed.
** Anyway, the same host prepares the same thing, so I should have such a setting on the host **, so I made such a command.
I created a ʻappdo command to execute a command in the context of an app. You can [
pip install`](https://pypi.python.org/pypi/appdo).
pip install appdo
With ʻappdo, the
rails c` that used to run like this ...
$ su - web #Log in first ...
$ cd my-awesome-app #There was this directory
$ cd current #Oh, it was under the control of capistrano
$ export RAILS_ENV=production #Set environment variables
$ export RACK_ENV=production #(Something different)
$ bundle exec rails c #Hoi
That's all you need to do.
$ sudo -iu web appdo rails c #rails c within the web user's app
Write the configuration file in $ HOME / .appdo.conf
as follows. The format is TOML.
# /home/web/.appdo.conf
#
##If you do sudo, the sudo destination user.appdo.conf applies
[default]
cd = "~/my-awesome-app/current"
source = ["/etc/profile", "~/.bashrc"]
prefix = "bundle exec"
[default.env]
RAILS_ENV = production
RACK_ENV = production
As you can see, it does cd
, source
, sets environment variables, and then bundle exec
s the command.
If you do it every time, it's not a job that humans should do. It makes people happier to put it in a configuration file and provision and manage that file.
crontab
RAILS_ROOT=/home/web/my-awesome-app/current
BASHRC=/home/web/.bashrc
RAILS_ENV=production
30 3 * * * bash -c "cd $RAILS_ROOT; source $BASHRC; bundle exec rails runner MyAwesomeApp::MyCron.run()"
30 4 * * * bash -c "cd $RAILS_ROOT; source $BASHRC; bundle exec rails runner MyAwesomeApp::MyCron2.run()"
30 5 * * * bash -c "cd $RAILS_ROOT; source $BASHRC; bundle exec rails runner MyAwesomeApp::MyCron3.run()"
30 3 * * * appdo rails runner MyAwesomeApp::MyCron.run()
30 4 * * * appdo rails runner MyAwesomeApp::MyCron2.run()
30 5 * * * appdo rails runner MyAwesomeApp::MyCron3.run()
Since there is no need to set environment variables (appdo absorbs them), crontab becomes super simple. You can see what command you are typing with appdo. I can see it
ssh my.server.example.com sudo -u web bash -c "cd /home/web/my-awesome-app/current; source ~/.bashrc; RAILS_ENV=production bundle exec rake assets:precompile"
ssh my.server.example.com sudo -iu web appdo rake assets:precompile
This is as simple as crontab
.
Simplifying ssh has the big advantage of simplifying config / deploy.rb
. Separation is better because you don't have to put host-specific information (paths, environment variables, etc.) in your app code.
Imagine all cd / source
move out of the document
Wow
For example, even if the app path is different or ruby is in a mixed environment of rvm / rbenv
, the configuration file on each host can absorb this difference. As a result, sequential migration may be much easier, as the deployment script does not need to be modified.
# /root/.appdo.conf
[apache]
cd = "/etc/apache2"
[bind]
cd = "/var/bind/etc/bind"
It may be convenient to specify only the cd
destination and share only the management command of the configuration file.
# appdo --app=apache -- ls sites-available
# appdo --app=apache -- ln -s sites-available/99-default sites-enabled
# appdo --app=bind -- co -l master/my.example.com
# appdo --app=bind -- vim master/my.example.com
# appdo --app=bind -- ci -u master/my.example.com
--Use appdo to execute commands in "app context" --Use appdo to drop the "app context" into your config file --Use appdo to clean up breaks between apps and infrastructure
It's a script that I just made myself and isn't bullet proof, but I decided to release it and hit the specs first. We look forward to your bug reports and requests.
Originally, I thought about this ʻappdo command because it was stressful that I couldn't use
rubyfrom
sudo when using
rvm / rbenv. The demands placed on infrastructure are changing again these days, but I think it's better to design the host to behave autonomously, whether it's docker, serf / consul, or autoscaling. Even in such a place, if you can create something like a "host layer" by using ʻappdo
and absorb various things, I think that you will be happy because you will have less head use.
The Python implementation is the so-called first prototyping guy. I haven't made a package in Python, so I used @ mkouhei's bootstrap-py for implementation. I think it would be better to move to Go when the requirements such as options are fixed.
e? Is Rust better? ...
Recommended Posts