Запуск команд командного рядка в сценарії Ruby


92

Чи є спосіб запускати команди командного рядка через Ruby? Я намагаюся створити маленьку маленьку програму Ruby, яка набирала б номер та отримувала / надсилала через програми командного рядка, такі як 'screen', 'rcsz' тощо.

Було б чудово, якби я зміг пов’язати все це з Ruby (серверний сервер MySQL тощо)


Відповіді:


209

Так. Є кілька способів:


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.


Бонус трюк: io = IO.popen 'cat > out.log', 'r+'; записує результати команди у "out.log"
Нарфанатор

1
Які плюси та мінуси у кожного. Як я можу вирішити, який використовувати? Як щодо використання FileUtils[ ruby-doc.org/stdlib-1.9.3/libdoc/fileutils/rdoc/FileUtils.html] ?
Ава

1
Я виконую команду SVN за допомогою exec. Я не хочу, щоб вихідні дані exec з'являлися на консолі. Я хочу перенаправити його, щоб я міг зберегти його як змінну і зробити деяку обробку з цього приводу. Як це зробити?
стек1

2
status.usccessful? більше не працює для мене на ruby ​​2.4, він змінився на status.success? :)
DanielG

14

Існує кілька способів запускати системні команди в 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метод, який конкретно пропонує цю можливість.


popen добре працює, якщо у вашому додатку лише стандартний вихід. Якщо вам потрібна більше взаємодії або ви хочете зробити щось інше за допомогою stdout, stdin і особливо stderr, ви також захочете вивчити open3: ruby-doc.org/core/classes/Open3.html
Пол Рубель

7
 folder = "/"
 list_all_files = "ls -al #{folder}"
 output = `#{list_all_files}`
 puts output

2

Так, це, безумовно, можливо, але спосіб реалізації відрізняється залежно від того, чи працює програма "командного рядка" у режимі "Повний екран" або в режимі командного рядка. Програми, написані для командного рядка, зазвичай читають STDIN і записують у STDOUT. Їх можна викликати безпосередньо в Ruby за допомогою стандартних методів зворотних посилань та / або системних / exec-викликів.

Якщо програма працює в режимі "На весь екран", як екран або vi, то підхід повинен бути іншим. Для таких програм слід шукати реалізацію Ruby бібліотеки "очікуй". Це дозволить вам створити сценарій того, що ви очікуєте побачити на екрані, і що надіслати, коли побачите, що ці конкретні рядки з’являються на екрані.

Це навряд чи буде найкращим підходом, і ви, мабуть, повинні поглянути на те, чого намагаєтесь досягти, і знайти відповідну бібліотеку / дорогоцінний камінь для цього, а не намагатися автоматизувати існуючий повноекранний додаток. Як приклад " Потрібна допомога у зв'язку з послідовним портом у Ruby " стосується зв'язку через послідовний порт, попереднього курсору до набору номера, якщо саме цього ви хочете досягти за допомогою конкретних програм, про які ви згадали.


Проста версія Expect доступна в Ruby за допомогою вбудованого модуля Pty .
Олов'яна людина,

0

Найбільш використовуваний метод - Використання 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.