Выполнение команд командной строки в скрипте Ruby - PullRequest
88 голосов
/ 01 июля 2010

Есть ли способ запуска команд командной строки через Ruby?Я пытаюсь создать небольшую маленькую Ruby-программу, которая будет набирать номер и получать / отправлять через программы командной строки, такие как 'screen', 'rcsz' и т. Д.

Было бы здорово, если бы я мог связать все этос Ruby (серверная часть MySQL и т. д.)

Ответы [ 5 ]

201 голосов
/ 01 июля 2010

Да. Есть несколько способов:


a. Используйте %x или '`':

%x(echo hi) #=> "hi\n"
%x(echo hi >&2) #=> "" (prints 'hi' to stderr)

`echo hi` #=> "hi\n"
`echo hi >&2` #=> "" (prints 'hi' to stderr)

Эти методы вернут stdout и перенаправят stderr в программу.


b. Использование system:

system 'echo hi' #=> true (prints 'hi')
system 'echo hi >&2' #=> true (prints 'hi' to stderr)
system 'exit 1' #=> nil

Этот метод возвращает true, если команда была успешной. Он перенаправляет весь вывод в программу.


c. Использование exec:

fork { exec 'sleep 60' } # you see a new process in top, "sleep", but no extra ruby process. 
exec 'echo hi' # prints 'hi'
# the code will never get here.

Это заменяет текущий процесс созданным командой.


d. (ruby 1.9) используйте spawn:

spawn 'sleep 1; echo one' #=> 430
spawn 'echo two' #=> 431
sleep 2
# This program will print "two\none".

Этот метод не ожидает завершения процесса и возвращает PID.


e. Использование IO.popen:

io = IO.popen 'cat', 'r+'
$stdout = io
puts 'hi'
$stdout = IO.new 0
p io.read(1)
io.close
# prints '"h"'.

Этот метод возвращает объект IO, который представляет ввод / вывод новых процессов. В настоящее время это также единственный способ, которым я знаю, дать ввод программы.


f. Использование Open3 (на 1.9.2 и выше)

require 'open3'

stdout,stderr,status = Open3.capture3(some_command)
STDERR.puts stderr
if status.successful?
  puts stdout
else
  STDERR.puts "OH NO!"
end

Open3 имеет несколько других функций для получения явного доступа к двум выходным потокам. Это похоже на popen, но дает вам доступ к stderr.

14 голосов
/ 01 июля 2010

Есть несколько способов запуска системных команд в Ruby.

irb(main):003:0> `date /t` # surround with backticks
=> "Thu 07/01/2010 \n"
irb(main):004:0> system("date /t") # system command (returns true/false)
Thu 07/01/2010
=> true
irb(main):005:0> %x{date /t} # %x{} wrapper
=> "Thu 07/01/2010 \n"

Но если вам действительно нужно выполнить ввод и вывод с помощью команды stdin / stdout, вам, вероятно, захочется взглянуть на IO::popen метод, который специально предлагает это средство.

7 голосов
/ 31 мая 2013
 folder = "/"
 list_all_files = "ls -al #{folder}"
 output = `#{list_all_files}`
 puts output
2 голосов
/ 01 июля 2010

Да, это, безусловно, выполнимо, но способ реализации зависит от того, работает ли рассматриваемая программа «командной строки» в «Полном экране» или в режиме командной строки.Программы, написанные для командной строки, имеют тенденцию читать STDIN и записывать в STDOUT.Они могут быть вызваны непосредственно в Ruby с использованием стандартных методов обратного вызова и / или системных вызовов / exec.

Если программа работает в полноэкранном режиме, например screen или vi, подход должен быть другим.Для программ, подобных этой, вы должны искать в Ruby реализацию библиотеки «ожидаемо».Это позволит вам написать сценарий того, что вы ожидаете увидеть на экране, и что отправлять, когда вы видите, что эти конкретные строки появляются на экране.

Это вряд ли будет лучшим подходом, и вам, вероятно, следует взглянуть на то, что вы есть.пытаясь достичь и найти соответствующую библиотеку / гем для этого, а не пытаться автоматизировать существующее полноэкранное приложение.Например, « Нужна помощь в обмене данными через последовательный порт в Ruby » относится к обмену данными через последовательный порт, который является предварительным курсором для набора номера, если это то, чего вы хотите добиться с помощью конкретных программ, которые вы упомянули.

0 голосов
/ 19 декабря 2017

Наиболее используемый метод - это использование Open3. Вот версия моего кода, отредактированная моим кодом, с некоторыми исправлениями:

require 'open3'
puts"Enter the command for execution"
some_command=gets
stdout,stderr,status = Open3.capture3(some_command)
STDERR.puts stderr
if status.success?
  puts stdout
else
  STDERR.puts "ERRRR"
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...