Подтвердить что ты не робот

Запуск другого рубина script из рубина script

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

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

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

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

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

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

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

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

4b9b3361

Ответ 1

Авди Гримм написал серию статей о Devver blog о различных способах запуска подпроцессов Ruby прошлым летом:

[Примечание: похоже, что часть 4 еще не опубликована.]

Ответ 2

require "b.rb"

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

a.rb:

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

b.rb:

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

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

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

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

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

Ответ 3

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

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

Чтобы убедиться, что рассматриваемый script не работает со временем выполнения вашего вызова script, и для защиты от вероятности, что он может вызвать 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.

Ответ 4

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

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

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

Ответ 6

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

/MyApp/script/main_script.rb


load rails 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")

Ответ 7

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

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