brewster
brewster

Reputation: 4502

how do i run an asynchronous loop in ruby?

I need to execute a process that runs several admin system commands. I want to keep the sudo timestamp current while it runs in case the process run too long.

i have the following code, but it does not seem to work.

sudo_keep_alive = Thread.start do
  def sudo
    sleep 5.minutes
    `sudo -v`
    sudo
  end
  sudo
end

at_exit do
  sudo_keep_alive.kill
end

Is there a convention for this?

UPDATE

The reason i cannot run the script has root, is there are other system commands the script runs that cannot run as root. Each command needs to be responsible for running it's own admin commands. The script can potentially take a considerable amount of time to run, so i simply wanted to keep the sudo timestamp fresh in the event a command needs it.

Upvotes: 1

Views: 2855

Answers (2)

user513951
user513951

Reputation: 13770

To answer your other question, there is a better way to run an asynchronous loop.

By using head-tail recursion (def sudo; do_something; sudo; end) you risk running into a SystemStackError at around 10000 calls (see How does your favorite language handle deep recursion? ).

Instead, just use a regular old ruby loop.

Thread::new do
  loop do
    sleep 300 # 5.minutes is not base ruby, it comes from ActiveSupport
    call_my_function
  end
end

As mentioned by David Unric, there is no need to kill the thread using at_exit, as your main process will automatically kill any active threads when it finishes.

Upvotes: 2

user513951
user513951

Reputation: 13770

Scrap all this and execute your ruby script as root instead.

$ sudo ruby myscript.rb

Upvotes: 1

Related Questions