Как вызывать команды оболочки из Ruby

ruby shell interop


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




Answer 1 Steve Willard


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

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

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

cmd = "echo 'hi'" # Sample string that can be used
  1. Kernel#` , обычно называемое backticks `cmd`

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

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

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

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

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

    Возвращает результат (т.е.стандартный вывод)команды оболочки,как и обратные ссылки.

    Документы: https://docs.ruby-lang.org/en/master/syntax/literals_rdoc.html#label-Percent+Strings

    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

Для более подробной информации смотрите:




Answer 2 Ian


Вот блок-схема, основанная на « Когда использовать каждый метод запуска подпроцесса в Ruby ». Смотрите также: « Обманите приложение, думая, что его стандартный вывод - это терминал, а не канал ».

enter image description here




Answer 3 cynicalman


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

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

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

directorylist.each do |filename|
  filename.chomp!
  # work with file
end



Answer 4 Mihai A


Вот лучшая на мой взгляд статья о запуске сценариев оболочки в Ruby: « 6 способов запуска команд оболочки в Ruby ».

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

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




Answer 5 anshul


Мой любимый это Open3

  require "open3"

  Open3.popen3('nroff -man') { |stdin, stdout, stderr| ... }