Rails class method in cron job not working in elastic beanstalk - mysql

I have a class method that I need to run every 15 min, I have the cron job
0,15,30,45 * * * * /bin/bash -l -c 'cd /var/app/current && sudo /opt/rubies/ruby-2.3.5/bin/bundle exec /opt/rubies/ruby-2.3.5/bin/rails runner -e production '\''Structure.check_parking'\'' >> /var/app/current/log/cron_log 2>&1'
Running in my elastic beanstsalk environment, but I keep getting an error of
/opt/rubies/ruby-2.3.5/lib/ruby/gems/2.3.0/gems/mysql2-0.4.4/lib/mysql2/client.rb:87:in `connect': Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)
I am using an RDS server in my production environment so it is strange that it's trying to connect to a local mysql server.
The rails app is connected to the database and I can do all normal functionality on it but when I try to run this class method I am getting this error.
My guess is that it's not running in production, but I'm really not sure, my database.yml file looks like
development:
adapter: mysql2
database: bddatabase
encoding: utf8
username: bduser
password: dbpass
host: 127.0.0.1
port: 3306
production:
adapter: mysql2
encoding: utf8
database: <%= ENV['RDS_DB_NAME'] %>
username: <%= ENV['RDS_USERNAME'] %>
password: <%= ENV['RDS_PASSWORD'] %>
host: <%= ENV['RDS_HOSTNAME'] %>
port: <%= ENV['RDS_PORT'] %>
Been trying to figure this out for a while now, any help is really appreciated!

I figured it out, turns out there was a problem with my cron task it's self. I think how I was referencing bundle and rails the way I did it wasn't pointing at my app which was causing the error. Changing the command to
0,15,30,45 * * * * /bin/bash -l -c 'cd /var/app/current && bundle exec rails runner -e production 'Structure.check_parking' >> /var/app/current/log/cron_log 2>&1'
Did the trick

Related

Cannot connect to local MySQL server using socket (2) in Elastic beanstalk using RDS database

I am creating a CI\CD for my Ruby on Rails application running in Elastic Beanstalk using code pipeline. My Code build succeeds but deployment to EBS provider fails with the below error
+ cd /var/app/ondeck
+ su -s /bin/bash -c 'bundle exec /opt/elasticbeanstalk/support/scripts/check-for-rake-task.rb db:migrate' webapp
`/home/webapp` is not a directory.
Bundler will use `/tmp/bundler20211229-11836-pzl6dq11836' as your home directory temporarily.
+ '[' false = true ']'
+ su -s /bin/bash -c 'leader_only bundle exec rake db:migrate' webapp
`/home/webapp` is not a directory.
Bundler will use `/tmp/bundler20211229-11840-9hxmcz11840' as your home directory temporarily.
rake aborted!
Mysql2::Error::ConnectionError: Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)
/opt/rubies/ruby-2.6.7/bin/bundle:23:in `load'
/opt/rubies/ruby-2.6.7/bin/bundle:23:in `<main>'
Tasks: TOP => db:migrate
(See full trace by running task with --trace) (Executor::NonZeroExitStatus)
I have
mysql --version
mysql Ver 14.14 Distrib 5.5.62, for Linux (x86_64) using readline 5.1
and could connect to External RDS MySQL Aurora database.
my Buildspec.yml:
version: 0.2
phases:
install:
runtime-versions:
ruby: 2.6
commands:
- echo Installing Bundler...
- gem install bundler
- bundle install
pre_build:
commands:
- echo Preparing database to run tests...
- bundle exec rails db:create --trace RAILS_ENV=production
build:
commands:
- echo Running tests...
- bundle exec rails test/test_helper.rb
artifacts:
files:
- '**/*'
My database.yml:
default: &default
adapter: mysql2
encoding: utf8mb4
collation: utf8mb4_unicode_ci
pool: 5
timeout: 5000
username: <%= ENV['DB_USER'] %>
password: <%= ENV['DB_PASSWORD'] %>
host: <%= ENV['DB_HOST'] %>
port: <%= ENV['DB_PORT'] %>
development:
<<: *default
database: <%= ENV['DB'] %>
test:
<<: *default
database: <%= ENV['DB_TEST'] %>
production:
<<: *default
database: <%= ENV['DB'] %>`
I found an answer for a similar problem connecting to a mysql server from Rails EB SSH that might still help you. Basically, Elastic Beanstalk was not successfully using my environment's envars to run my bundle exec rails console command in the eb ssh instance access.
I solved my issue by prepending all of the required envars explicitly to any rails commands I ran from within the eb ssh instance access. So for example, in order to run your su -s /bin/bash -c 'leader_only bundle exec rake db:migrate' webapp command, you may have to change that to run something like the following:
su -s /bin/bash -c 'leader_only RAILS_MASTER_KEY=xxxxxxx RAILS_ENV=production DB_HOST=xxxxxxx DB_PASSWORD=xxxxxxx DB_USER=xxxxxxx DB=xxxxxx AWS_REGION=xxxxxxx AWS_BUCKET=xxxxxxx bundle exec rake db:migrate' webapp
Replace the xxxxxxxs above with the values from the corresponding variables in your EB > Configuration > Software tab, and you should be able to connect to the remote database that way. After that, you will be able to run migration commands, rake tasks and other database-reliant functions. I'm not familiar with CI/CD but I hope the principles of this solution are adaptable to your project.
Thanks for your answers. But I faced the issue because of the master branch in git not updated properly.
After updating the master branch with proper application code, the CI\CD initiated as expected but got stuck in between because of env and credential file not in git.
I create a s3 bucket to store the env files and referred those file while packaging it for EBS deployment.
Hope this helps someone in future :)

MySQL No database selected rails

I got something like this when i hit rake db:migrate
Im using figaro in my app, its my first time with this gem any mysql so I cant get what excatly is wrong.
Thanks in advance :)
Mysql2::Error: No database selected: CREATE TABLE schema_migrations (version varchar(255) PRIMARY KEY) ENGINE=InnoDB
database.yml
default: &default
adapter: mysql2
encoding: utf8
pool: 5
username: <%= ENV["DB_USER"] %>
password: <%= ENV["DB_PASSWORD"] %>
development:
<<: *default
database: <%= ENV["DB_DATABASE_DEV"] %>
test:
<<: *default
database: <%= ENV["DB_DATABSE_TEST"] %>
production:
<<: *default
database: <%= ENV['DB_DATABASE_PRODUCTION'] %>
application.yml
default: &default
adapter: mysql2
encoding: utf8
pool: 5
username: root
password: password
development:
<<: *default
database: dev
test:
<<: *default
database: test_db
I don't have enough point to ask in comment, but it seems you're trying to run migration without creating a schema first.
Run rails db:create to create the schema first. For example, if you don't have the a database named "dev" in your MySQL, this command will do so.
rails db:create
To set specific environment
rails db:create RAILS_ENV=test
Then you run canrails db:migrate.
To destroy a schema if you need one:
rails db:drop
You're Using ENV
Though it might not be related, have you set up your ENV properly before running the command?
For Windows, you can add those, for example, DB_USER to system environment
Just press Start and type system environment >> Environment Variables... >> New...
Variable Name: DB_USER
Variable Value: your_username
Note: You might have to restart your system for the environment to work.
Or if you don't have time, simply in your terminal you're running rails s:
C:\Sites\ProjectName> set DB_USER=your_username
C:\Sites\ProjectName> set DB_PASSWORD=your_username
C:\Sites\ProjectName> rails s
The same steps for Linux, but I don't know the specific command. Some prefer to use .env file.
I've run into this trouble a couple days ago, and it's very annoying because Rails tried to create dev and test db's when in dev environment. Nothing worked.
I ended up hard-coding database: into database.yml, and let Figaro manage credentials.
I runned the same issue today.
Ensure you have dotenv-rails gem installed and that "DB_DATABASE_DEV" has a value in your .env file.
Also, make sure your database has been created.
It happens when your database.yml does not include database: some_database part or when database name is empty. In your case you can use one of few options:
Option 1: run migrations with database name env variable included
DB_DATABASE_DEV=your_dev_db_name rails db:<task>
Option 2: use hard-coded db name in your database.yml file
# database.yml
development:
<<: *default
database: my_development_database
Option 3: make sure that env variables are correctly loaded
To do so in linux, simply write in terminal:
echo ${DB_DATABASE_DEV}
On windows terminal you need to write this:
echo %DB_DATABASE_DEV%
If you get no content then this env variable is not set

Connect Rails/Unicorn/Nginx container to MySQL container

Related to this thread, I am trying to create 2 containers: 1 with a rails app, and the other with a MySQL database but I keep getting the Mysql2::Error (Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' in my apps production.log file after I hit the container's IP http://192.168.59.103
When I start the rails container, I am attempting to link them and do get an error if I specify an incorrect MySQL name. What am I missing to successfully link the containers so the full app runs in containers?
Rails container command
docker run --name games-app --link test-mysql:mysql -p 8080 -d -e SECRET_KEY_BASE=test sample_rails_games_app
Here are my files:
Dockerfile
# Publish port 8080
EXPOSE 8080
CMD ["bundle", "exec","unicorn", "-p", "8080"]
CMD ["bunde", "exec", "rake", "db:migrate"]
Rails database.yml (dev and test are the same as production)
default: &default
adapter: mysql2
encoding: utf8
pool: 5
username: root
password: root
host: localhost
#socket: /tmp/mysql.sock
production:
<<: *default
database: weblog_production
7/31/15 Edit
The docker log shows the unicorn server running:
docker logs a13bf7851c6d
I, [2015-07-31T18:10:59.860203 #1] INFO -- : listening on addr=0.0.0.0:8080 fd=9
I, [2015-07-31T18:10:59.860583 #1] INFO -- : worker=0 spawning...
I, [2015-07-31T18:10:59.864143 #1] INFO -- : master process ready
I, [2015-07-31T18:10:59.864859 #7] INFO -- : worker=0 spawned pid=7
I, [2015-07-31T18:10:59.865097 #7] INFO -- : Refreshing Gem list
I, [2015-07-31T18:11:01.796690 #7] INFO -- : worker=0 ready
7/31/15 Solution Thanks to #Rico
db:migrate was having problems running so I ultimately ran it by hand in a docker run command. Make sure you do this after the container is already created, or during the creation process as it needs the linking to the DB container
This linking article helped me understand that my link was not being created so there was no way to communicate properly.
Once I understood how to accurately make the link, I did update my database.yml with the host and port values
Use this command to check the names of your env variables docker run --rm --name <unique-value> --link <db-name> <non-db-image> env.
Use this to see the value of the links in your app container docker inspect -f "{{ .HostConfig.Links }}" <app-name>
Actually your bundle exec unicorn -p 8080 CMD is superseding the bundle exec rake db:migrate as it doesn't return.
You should run your db:migrate first and you should run it with the RUN command as CMD is the primary command in docker.
But the other problem is with your database.yml file. You are pointing your db to a db server that runs on the same container as in the application. You should populate the values of your database.yml from the env variables created after you link your source container (application) to destination container (db server container). The env variables are created in the source container.
More info here: https://docs.docker.com/userguide/dockerlinks/
So for example:
$ docker run --rm --name web2 --link db:db training/webapp env
. . .
DB_NAME=/web2/db
DB_PORT=tcp://172.17.0.5:5432
DB_PORT_5432_TCP=tcp://172.17.0.5:5432
DB_PORT_5432_TCP_PROTO=tcp
DB_PORT_5432_TCP_PORT=5432
DB_PORT_5432_TCP_ADDR=172.17.0.5
Your database.yml should look something like this:
default: &default
adapter: mysql2
encoding: utf8
pool: 5
database: <%= ENV['DB_NAME'] %>
username: root
password: root
host: <%= ENV['DB_PORT_5432_TCP_ADDR'] %>
port: <%= ENV['DB_PORT_5432_TCP_PORT'] %>
You can't have 2 CMD commands in your Dockerfile, in fact only the last one is kept. The CMD command executed is `
CMD ["bunde", "exec", "rake", "db:migrate"]`
the other, the
CMD ["bundle", "exec","unicorn", "-p", "8080"]
is superseded.
See Supervisor
https://docs.docker.com/articles/using_supervisord/
if you want to run more than one rocess in your container, or run 2 differnet containers

Rails - Multiple development instances with a single source and database.yml file

Can we connect to multiple development instances with a single source and a single database.yml file? I mean, I need to have 4 development instances from same source which connects 4 different MySQL databases. Can I start the servers by using different PORT IDs?
example:
development:
adapter: mysql2
database: TEST1_development
host: localhost
username: root
password: password
encoding: utf8
pool: 30
development-2:
adapter: mysql2
database: TEST2_development
host: localhost
username: root
password: password
encoding: utf8
pool: 30
development-3:
adapter: mysql2
database: TEST3_development
host: localhost
username: root
password: password
encoding: utf8
pool: 30
development-4:
adapter: mysql2
database: TEST4_development
host: localhost
username: root
password: password
encoding: utf8
pool: 30
Then, then how we can start 4 different servers (at localhost) connecting these 4 databases simultaneously? (we normally use rails server for single instance in development.)
Thanks :)-
You are not limited to the default rails environments. You could just have development-2, development-3 environments. Read this post on the 37signals blog where DHH talks about that
database.yml can read environment variables.
development:
adapter: postgresql
host: localhost
database: <%= ENV['POSTGRES_DATABASE'] %>
username: <%= ENV['POSTGRES_USER'] %>
password: <%= ENV['POSTGRES_PASSWORD'] %>
then make sure these are set when you start your server.
It is super easy.
Just update your database.yml file as given in the question. Suppose our development instances are development, development-2, development-3 and development-4.
First you just create 3 copies of the environment file development.rb (can find insideconfig/environments/) and rename it to development-2.rb, development-3.rb and development-4.rb.
Then, just do run the below steps before starting the servers.
RAILS_ENV=development rake db:create (OR just rake db:create as it defaults to development)
RAILS_ENV=development-2 rake db:create
RAILS_ENV=development-3 rake db:create
RAILS_ENV=development-4 rake db:create
RAILS_ENV=development rake db:schema:load (OR just rake db:schema:load as it defaults to development)
RAILS_ENV=development-2 rake db:schema:load
RAILS_ENV=development-3 rake db:schema:load
RAILS_ENV=development-4 rake db:schema:load
RAILS_ENV=development rake db:seed (OR just rake db:seed as it defaults to development)
RAILS_ENV=development-2 rake db:seed
RAILS_ENV=development-3 rake db:seed
RAILS_ENV=development-4 rake db:seed
Then, start all instances with different server pid's as given below.
rails s -p 3000 -e development --pid tmp/pids/server.pid (OR rails s by default)
rails s -p 3002 -e development-2 --pid tmp/pids/server.2.pid
rails s -p 3003 -e development-3 --pid tmp/pids/server.3.pid
rails s -p 3004 -e development-4 --pid tmp/pids/server.4.pid
That will start all instances simultaneously from the same source and a single database.yml file. Thank you all for all your replies and help :)-

Rails make database mysql

I'm using Rails 3, and Ubuntu. I want to change the default Rails SQLite3 into a mysql database. I ran these commands:
sudo apt-get install mysql-server mysql-client libmysqlclient15-dev
sudo apt-get install libmysql-ruby1.8
These were successful. Then I did this in the gemfile
#gem 'sqlite3'
gem 'mysql'
This worked, now, what else should I do to complete the MySQL setup. I know for one the database.yml needs to change, but how does it need to look for Ubuntu and how do I fill in the parameters?
Your config/database.yml must look like :
base: &base
adapter: mysql
username: YourUserName
password: YourPassword
host: localhost
encoding: utf8
pool: 5
timeout: 5000
development:
database: YourApp_dev
<<: *base
test:
database: YourApp_test
<<: *base
production:
database: YourApp_prod
<<: *base
Is the database on the same host?
You need to log into mysql, set a user, create a database. If the database is on a database server, outside of the application server, then you will need to make accessible from the net.
http://www.slac.stanford.edu/BFROOT/www/Computing/Online/Databases/CfgDB/CfgDB-MySQL-Setup.html
After you're done setting up the database (not just installing it), then you're database.yml files need to be modified per the above.