Вызов команд оболочки из Ruby

Как мне вызывать команды оболочки внутри Ruby-программы? Как я могу получить выходные данные этих команд обратно в Ruby?

1010
задан 06.03.2015, 14:10

7 ответов

Это объяснение основано на прокомментированном сценарий Ruby от моего друга. Если Вы хотите улучшить сценарий, не стесняйтесь обновлять его в ссылке.

Первый, обратите внимание, что, когда Ruby обращается к оболочке, он обычно звонит /bin/sh, не Bash. Некоторый синтаксис Bash не поддерживается /bin/sh во всех системах.

Вот способы выполнить сценарий оболочки:

cmd = "echo 'hi'" # Sample string that can be used
  1. Kernel#`, обычно называемые обратные галочки †“`cmd`

    Это похоже на многие другие языки, включая Bash, PHP и Perl.

    Возвраты результат команды оболочки.

    Документы: http://ruby-doc.org/core/Kernel.html#method-i-60

    value = `echo 'hi'`
    value = `#{cmd}`
    
  2. Встроенный синтаксис, %x( cmd )

    После x символ является разделителем, который может быть любым символом. Если разделитель является одним из символов (, [, {, или <, литерал состоит из символов до соответствия заключительный разделитель, принимая во внимание вложенных пар разделителя. Для всех других разделителей литерал включает символы до следующего возникновения символа-разделителя. Строковая интерполяция #{ ... } позволяется.

    Возвраты результат команды оболочки, точно так же, как обратные галочки.

    Документы: http://www.ruby-doc.org/docs/ProgrammingRuby/html/language.html

    value = %x( echo 'hi' )
    value = %x[ #{cmd} ]
    
  3. Kernel#system

    Выполняет данную команду в подоболочке.

    Возвраты true, если команда была найдена и выполнена успешно, false иначе.

    Документы: http://ruby-doc.org/core/Kernel.html#method-i-system

    wasGood = system( "echo 'hi'" )
    wasGood = system( cmd )
    
  4. Kernel#exec

    Замены текущий процесс путем выполнения данной внешней команды.

    Возвраты ни один, текущий процесс заменяется и никогда не продолжается.

    Документы: http://ruby-doc.org/core/Kernel.html#method-i-exec

    exec( "echo 'hi'" )
    exec( cmd ) # Note: this will never be reached because of the line above
    

Вот некоторый дополнительный совет: $?, то, которое совпадает с $CHILD_STATUS, получает доступ к состоянию выполняемой команды последней системы, если Вы используете обратные галочки, system() или %x{}. Можно тогда получить доступ exitstatus и pid свойства:

$?.exitstatus

Для большего количества чтения см.:

1265
ответ дан 04.10.2019, 11:02
  • 1
    Я должен зарегистрировать выводы своего исполняемого файла на рабочем сервере, но не нашел пути. Я использовал, помещает #{cmd} и logger.info (#{cmd}). Там какой-либо путь состоит в том, чтобы зарегистрировать их выводы в производство? – Omer Aslam 02.10.2012, 07:37
  • 2
    И IO#popen () и Open3#popen3 (). mentalized.net/journal/2010/03/08/… – hughdbrown 07.02.2013, 12:20
  • 3
    Ради полноты (поскольку я сначала думал, что это также будет командой Ruby): Грабли имеют sh, который делает " Выполните системную команду cmd. Если нескольким аргументам дают, команда не выполняется с оболочкой (та же семантика как Ядро:: должностное лицо и Ядро:: система) ". – sschuberth 16.02.2013, 05:19
  • 4
    Обратные галочки don' t получают STDERR по умолчанию. Добавьте '2> & 1', чтобы управлять, хотите ли Вы получить – Andrei Botalov 18.02.2013, 11:19

Можно также использовать операторы обратной галочки ('), подобный Perl:

directoryListing = `ls /`
puts directoryListing # prints the contents of the root directory

Удобный, если Вам нужно что-то простое.

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

9
ответ дан 04.10.2019, 11:02

Я - определенно не эксперт Ruby, но я дам ему выстрел:

$ irb 
system "echo Hi"
Hi
=> true

необходимо также быть в состоянии сделать вещи как:

cmd = 'ls'
system(cmd)
22
ответ дан 04.10.2019, 11:02

Некоторые вещи думать о при выборе между этими механизмами:

  1. Вы просто хотите stdout, или Вам нужен stderr также? или даже выделенный?
  2. , Насколько большой Ваш вывод? Вы хотите держать весь результат в памяти?
  3. Вы хотите считать часть своего вывода, в то время как подпроцесс все еще работает?
  4. Вы должны закончиться коды?
  5. Вам нужен рубиновый объект, который представляет процесс и позволяет Вам уничтожить его по требованию?

Вам, возможно, понадобится что-либо от простых обратных галочек (''), система (), и IO.popen к полноценному Kernel.fork / Kernel.exec с IO.pipe и IO.select.

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

, К сожалению, это очень зависит .

26
ответ дан 04.10.2019, 11:02

Мой фаворит Open3

  require "open3"

  Open3.popen3('nroff -man') { |stdin, stdout, stderr| ... }
35
ответ дан 04.10.2019, 11:02

Вот лучшая статья, по-моему, о выполнении сценариев оболочки в Ruby: " 6 Способов Выполнить Команды Shell в Ruby".

, Если только необходимо получить выходные обратные галочки использования.

мне был нужен более усовершенствованный материал как STDOUT и STDERR, таким образом, я использовал драгоценный камень Open4. У Вас есть все методы, объясненные там.

63
ответ дан 04.10.2019, 11:02
  • 1
    Сообщение, описанное здесь doesn' t обсуждают %x опция синтаксиса. – Mei 23.11.2011, 06:58
  • 2
    +1 для Open4. Я уже начал пытаться реализовать свою собственную версию spawn метод, когда я нашел это. – Brandan 20.11.2012, 11:02
  • 3
    Ну, это все еще оставляет меня в темноте относительно того, как другой код, который я получил из книги когда-либо, работал. – Jonathan Wood 03.11.2019, 07:54

Путем мне нравится делать, это использует %x литерал, который облегчает (и читаемый!) для использования кавычек в команде, как так:

directorylist = %x[find . -name '*test.rb' | sort]

, Который, в этом случае, заполнит список файлов со всеми тестовыми файлами под текущим каталогом, который можно обработать как ожидалось:

directorylist.each do |filename|
  filename.chomp!
  # work with file
end
158
ответ дан 04.10.2019, 11:02
  • 1
    %x[ cmd ] возвраты массив Вам? – x-yuri 03.06.2014, 03:24
  • 2
    Кроме того, если anyone' s заинтересованный, установка StatusCode к 404 автоматически наборы StatusDescription к " Не found". Однако it' s трудно для знания то, что точные правила (и будет в будущем), потому что это так очень плохо документируется. Установка и StatusCode и StatusDescription может быть лучшим подходом. – Jonathan Wood 03.11.2019, 07:54

Теги

Похожие вопросы