How to run a cron script with gitlab-rails - ruby-on-rails

I have gitlab-rails with
GitLab 15.0.4
Rails version 6.1.4.7
Ruby version ruby 2.7.5
I want to run a gitlab-rails script from Cron. The gitlab-rails runner seems to be broken as it doesn't recognize the file argument and tries to run it as a script instead, which fails. So even if the shebang line suggested in gitlab-rails runner -h worked (which it doesn't on my system because args are not separated), gitlab-rails runner complains that the file path is not a valid script.
I could include the ruby script in a shell script, pipe it to gitlab-rails, but sacrifices .rb file syntax highlighting and intelisense in editors.
I could pipe the .rb script from within a shell script into gitlab-rails. That would solve the previous, but now I have two scripts and shell is not reliable when it comes to referencing related scripts unless I give it the library path explicitly. That seems convoluted.
Someone folks have suggested workarounds. It involves running ruby as usual and then re-executing the script with rails (gitlab-rails in my case). This still fails because of the broken gitlab-rails runner which treats the file argument as a rails command...

I've expanded on the workaround to pipe the script to gitlab-rails on standard input which does work:
#!/usr/bin/env ruby
#
# List GitLab projects
#
# Run this script with sudo
if not defined?(Rails) then
# Running in plain rubby, invoke rails runner and pipe the script into it, passing args
exec("/usr/bin/gitlab-rails", "runner", "-", *ARGV, :in=>[File.expand_path(__FILE__)])
end
# Do your GitLab work here. This is just a harmless trivial example.
Project.find_each do |project|
puts "#{project.full_path}"
end
After making this script executable chown a+x I can put it in a cron job conveniently:
00 * * * * root /path/to/my/script.rb

Related

How to run commands on ruby-on-rails console inside bash shell script?

I would like to know how to run ruby commands in ruby on rails console inside a shell script ?
To be clear: I have a shell script which will connect to ruby on rails console, but unable to run commands inside the rails console from shell script. Please see below code snippet.
I am successfully able to enter into rails console from shell script, but unable to provide ruby commands inside shell script itself.
This sample script is allowing me to enter into rails console:
#!/bin/bash
/usr/bin/helpkit-docker.sh --rails-console
But, when i extend the above script to run commands inside rails console using EOF, it throws error:
#!/bin/bash
/usr/bin/helpkit-docker.sh --rails-console <<EOF
Time.now.strftime("%d/%m/%Y %H:%M")
EOF
Error: the input device is not a TTY
I expect the time to be fetched from rails console and get displayed in shell terminal
I believe the best way is create a ruby script that run the ruby code that you want and then in your shell script you call it using rails runner, like this:
#!/bin/bash
rails runner script/myscript.rb
and in your script
puts Time.now.strftime("%d/%m/%Y %H:%M")

Command to know Rails project root from shell script

Is there any obvious command (be it a rails command, rake command, or other) that I can use to get the path to the root of a rails project from within a shell script?
Context:
I'm writing a shell script. I'm going to execute that script from an arbitrary directory inside a rails project, and the script needs to determine the absolute path of the rails project root.
So, for example, if the script were
#!/bin/bash
rails_root=# get the root somehow...
and given that the root directory of my project is
/home/myuser/projects/myrailsapp
then I should be able to place that script in
/home/myuser/projects/myrailsapp/scripts/myscript
and call it from elsewhere in the project
cd /home/myuser/projects/myrailsapp/app/assets
../../scripts/myscript
and the script should be able to know the path of the root directory.
I've come up with two different ways of solving this problem:
#!/bin/bash
rails_root=$(rake about | grep 'Application root' | sed 's/Application root[ ]*//')
#!/bin/bash
rails_root=$(rails c <<-EORUBY | grep ^rails_root_is | sed 's/rails_root_is//'
puts "rails_root_is#{Rails.root}"
EORUBY
)
But I feel like there should be a more obvious way to do this. I was expecting to use an existing command.
If you really need it to be in a shell, you could:
rails_root=rails runner -e development "puts Rails.root"|tail -1
Instead of a shell script you can use rake. Besides the simplicity of dealing with a high level language you also have full access to the rails environment and you don't have to deal with all the pitfalls and issues when dealing with shell scripts which should work across platforms and shells.
To generate a rake task from rails:
rails g task foo dosomething
Which would generate an a rakefile in lib/tasks/foo.rake. From the rake task you can access the Rails root directory though Rails.root.
namespace :foo do
desc "TODO"
task dosomething: :environment do
puts "Rails root is: #{ Rails.root }"
puts "Current working directory is: #{ Dir.pwd }"
# You can invoke the shell with backticks, exec or ...
puts "You are: " + `whoami`
end
end
A few good resources:
Jason Seifer: Rake Tutorial
6 Ways to Run Shell Commands in Ruby
Not as elegant as using rake, this is a recursive shell function that depends on identifying the Gemfile - kind of a hack but quite fast. There are several other ways to determine whether you have found the Rails root.
function rr () {
if test `pwd` = $HOME
then
echo not in Rails
elif test -f Gemfile && grep Rails Gemfile > /dev/null
then
pwd
else
(cd ..; rr)
fi
}

How to make run external shell command in non-blocking mode in Ruby on Rails 3

I should change to specific folder so that the output of the script can be exported into a file in that folder (123.txt in the example code below).
but this command, which I run from inside my ruby code
./iw2_broadcast.py
takes 5 minutes or more to complete. I try to append & to make it run in the background, but it seems it does not work.
Any ideas? Thanks
Dir.chdir(#iw2_dir)
` ./iw2_broadcast.py -f 123.txt & `
puts "123"
Create a shell script with the execution command
# py.sh
./iw2_broadcast.py
Execute the above shell script from ruby using system command
# ruby_script.rb
system("./py.sh")
Now your ruby code will be executed without waiting for the output
Adding & works with system(). You can easily test it with:
system("sleep 1 &")
So for this precise example:
system("./iw2_broadcast.py -f 123.txt &")

RVM isnt setting environment with cron

I'm having a rough time executing script/runner with a cron and RVM. I believe the issues lie with the rvm environment not being set before the runner is executed.
currently im throwing the error
/bin/sh: 1.sql: command not found
which is more than i've gotten earlier, so i guess that's good.
I've read this thread Need to set up rvm environment prior to every cron job but im still not really getting it. Part of the problem i think is the error reporting.
this is my runner thus far.
*/1 * * * * * /bin/bash -l -c 'rvm use 1.8.7-p352#2310; cd development/app/my_app2310 && script/runner -e development "Mailer.find_customer"'
as per the above link, i tried making a rvm_cron_runner.
i created a file and placed this in it:
#!/bin/sh
source "/Users/dude/.rvm/scripts/rvm"
exec $1
then i updated my crontab to this.
*/1 * * * * * /bin/bash -l -c '/Users/dude/development/app/my_app2310/rvm_cron_runner; rvm use 1.8.7-p352#2310; cd development/app/my_app2310 && script/runner -e development "Mailer.find_customer"'
This also has made no difference. i get no error. nothing.
Can anyone see what i'm doing incorrectly?
P.S i hope my code formatting worked.
Could you try to place the code you want to run in a separate script, and then use the rvm_cron_runner ?
So place your actions in a file called /path/cron_job
rvm use 1.8.7-p352#2310
cd development/app/my_app2310 && script/runner -e development "Mailer.find_customer"
and then in your crontab write
1 2 * * * /path/rvm_cron_runner /path/cron_job
The differences:
this does not start a separate shell
use the parameter of the rvm_cron_runner
If you would use an .rvmrc file, you could even drop the rvm use ... line, I think.
You don't need to write a second cron runner (following that logic, you might as well write a third cron runner runner). Please keep things simple. All you need to do is configure your cron job to launch a bash shell, and make that bash shell load your environment.
The shebang line in your script should not refer directly to a ruby executable, but to rvm's ruby:
#!/usr/bin/env ruby
This instructs the script to load the environment and run ruby as we would on the command line with rvm loaded.
On many UNIX derived systems, crontabs can have a configuration section before the actual lines that define the jobs to be run. If this is the case, you would then specify:
SHELL=/path/to/bash
This will ensure that the cron job will be spawned from bash. Still, your environment is missing, so to instruct bash to load your environment, you will want to add to the configuration section the following:
BASH_ENV=/path/to/environment (typically .bash_profile or .bashrc)
HOME is automatically derived from the /etc/passwd line of the crontab owner, but you can override it.
HOME=/path/to/home
After this, a cron job might look like this:
15 14 1 * * $HOME/rvm_script.rb
What if your crontab doesn't support the configuration section. Well, you will have to give all the environment directives in one line, with the job itself. For example,
15 14 1 * * export BASH_ENV=/path/to/environment && /full/path/to/bash -c '/full/path/to/rvm_script.rb'
Full blog post on the subject
You can use rvm wrappers:
/home/deploy/.rvm/wrappers/ruby-2.2.4/ruby
Source: https://rvm.io/deployment/cron#direct

Execute script with Ruby on Rails?

I want to start my daemon with my application.
In the command line, I can write something like lib/daemons/mydaemon_ctl start to start up my daemon, but I have to do this manually. I want the daemon to start when I start my server (i.e. when the initializer files are loaded).
Is there a ruby command for executing a command line?
Something like exec "lib/daemons/mydaemon_ctl start"?
Thanks!
Seems you just want to run shell commands in ruby code, well you can use system or backtick(`)
system 'ls' # will return ls output in *nix
`dir` # will return dir output in windows

Resources