Запуск другого сценария ruby ​​из сценария ruby - PullRequest
33 голосов
/ 14 апреля 2010

Можно ли указать в ruby ​​вызов другого сценария ruby ​​с использованием того же интерпретатора ruby, на котором выполняется исходный сценарий?

Например, если a.rb пару раз запускает b.rb, можно ли заменить

system("ruby", "b.rb", "foo", "bar")

с чем-то вроде

run_ruby("b.rb", "foo", "bar")

так что, если вы использовали ruby1.9.1 a.rb на оригинале, ruby1.9.1 будет использоваться на b.rb, но если вы просто использовали ruby a.rb на оригинале, ruby будет использоваться на b.rb?

Я бы предпочел не использовать шебанги, так как я хотел бы, чтобы он мог работать на разных компьютерах, некоторые из которых не имеют /usr/bin/env.

Редактировать: Я не имел в виду load или require и т.п., но порождал новые процессы (поэтому я могу использовать несколько процессоров).

Ответы [ 7 ]

21 голосов
/ 14 апреля 2010
require "b.rb"

выполнит содержимое b.rb (вы вызываете опцию ".rb", и есть путь поиска). В вашем случае вы, вероятно, сделали бы что-то вроде:

a.rb:

require "b.rb";
b("Hello", "world")

b.rb:

def b(first, second)
  puts first + ", " + second
end

Обратите внимание: если вы используете require , Ruby загрузит и выполнит файл только один раз (каждый раз, когда вы вызываете load , он будет перезагружен), но вы можете вызывать методы, определенные в файл столько раз, сколько вы хотите.

По мере того, как все усложняется, вам нужно перейти к объектно-ориентированному дизайну.

РЕДАКТИРОВАТЬ: В этом случае вы должны изучить Ruby Threading. Простой пример:

a.rb:

require "b";
t1 = Thread.new{b("Hello", "world");}
t2 = Thread.new{b("Hello", "galaxy");}
t1.join
t2.join

b.rb:

def b(first, second)
  10.times {
    puts first + ", " + second;
    sleep(0.1);
  }
end
11 голосов
/ 14 апреля 2010
7 голосов
/ 19 августа 2010

Требуется трюк require, если предположить, что рассматриваемый скрипт не захлебывается попыткой переопределения любых констант, которые вы могли установить, или вызывать методы для объектов, к которым у вас может быть исправлена ​​обезьяна времени выполнения, чтобы больше не выполнять их стандартные контракты.

В любом случае, проблема не в подходе, а в коде самих сценариев. Проявите хорошие манеры, поместите ваши константы в пространство имен и не дайте обезьяне патчить среду выполнения деструктивно.

Чтобы убедиться, что рассматриваемый скрипт не портит время выполнения вызывающего скрипта, и чтобы предотвратить вероятность того, что он может где-нибудь вызвать Kernel / Process.exit (), попробуйте следующее

pid=Process.fork do
    require 'script.rb'
    Process.exit
end
ignored, status = Process.waitpid2(pid, Process::WNOHANG)
puts "script.rb PID #{pid} exited, exit status: #{status.exitstatus}" 

Для более сложных вещей, таких как запись в поток stdin или чтение из потоков stdout или stderr, используйте гем Open4.

3 голосов
/ 08 ноября 2016

Если вы просто хотите запустить скрипт в контексте существующего процесса, вы также можете сделать это

eval File.read("/path/to/your/script.rb")

Не уверен, каков ваш вариант использования, но это может быть полезно, например, если у вас открыта консоль Rails и вы хотите выполнить некоторый код в пустом файле, но не хотите продолжать копировать весь блок код в вашу консоль.

1 голос
/ 02 августа 2012

Это то, что я использовал

/ MyApp / скрипт / main_script.rb

<ч /> загрузить рельсы env, только если вам нужно

ENV['RAILS_ENV'] = ARGV.first || ENV['RAILS_ENV'] || 'development'
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")

запустить другие подчиненные скрипты из main_script.rb

require File.expand_path(File.dirname(__FILE__) + "/../script/populate_wh_grape_varieties_table.rb")
1 голос
/ 19 августа 2010
0 голосов
/ 14 января 2011

Чарльз Наттер, известный из JRuby, предлагает метод Kernel#ruby для вызова сценария Ruby с использованием той же реализации Ruby, что и в настоящее время.

Редактировать : предложение было отклонено. Матц сказал, что MVM (несколько виртуальных машин) может обеспечить решение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...