Выполнение команд bash из Rakefile [дубликат]



этот вопрос уже есть ответ здесь:




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

    20 ответов



Я хотел бы выполнить ряд bash команды Rakefile. Моя активная оболочка bash и я буду называть rake С bash.



я включил в мой Rakefile следующий



task :hello do
%{echo "World!"}
end


но при исполнении rake hello нет выхода?



Как выполнить команды bash из Rakefile?



Примечание:это не дубликат, так как он специально спрашивает, как выполнять команды bash из Rakefile.

640   4  

4 ответов:

Я думаю, что рейк хочет, чтобы это произошло с: http://rubydoc.info/gems/rake/FileUtils#sh-instance_method Пример:

task :test do
  sh "ls"
end

встроенная функция rake sh заботится о возвращаемом значении команды (задача не выполняется, если команда имеет возвращаемое значение, отличное от 0), а также выводит выходные данные команд.

Существует несколько способов выполнения команд оболочки в Ruby. Простой (и, вероятно, самый распространенный) - использовать обратные ходы:

task :hello do
  `echo "World!"`
end

Backticks имеют хороший эффект, когда стандартный вывод команды оболочки становится возвращаемым значением. Так, например, вы можете получить вывод ls делать

shell_dir_listing = `ls`

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

  • stdout = %x{cmd} - альтернативный синтаксис для backticks, за кулисами он делает то же самое

  • exec (cmd) - полностью заменить запущенный процесс с новым процессом cmd

  • успех = система (cmd) - запуск подпроцесса и возврат true / false на успех / неудачу (на основе выхода cmd статус)

  • IO#popen (cmd) {/io/} - запустите подпроцесс и подключите stdout и stderr to io

  • stdin, stdout, stderr = Open3.popen3 (cmd) - запуск подпроцесса и подключение ко всем трубам (вход, выход, ошибка)

%{echo "World!"} определяет строку. Я думаю, вы хотели %x{echo "World!"}.

%x{echo "World!"} выполняет команду и возвращает вывод (stdout). Вы не увидите результата. Но вы можете сделать:

puts %x{echo "World!"}

есть больше способов вызвать системную команду:

  • Backticks:'
  • system( cmd )
  • popen
  • Open3#popen3

учитывая, что консенсус, похоже, предпочитает рейка #sh метод, но OP явно запрашивает bash, этот ответ может иметь некоторое использование.

это актуально, так как Rake#sh использует Kernel#system вызов для выполнения команд оболочки. Рубин жестко кодирует это /bin/sh, игнорируя настроенную оболочку пользователя или $SHELL в среду.

вот обходной путь, который вызывает bash от /bin/sh, что позволяет по-прежнему использовать sh способ:

task :hello_world do
  sh <<-EOS.strip_heredoc, {verbose: false}
    /bin/bash -xeuo pipefail <<'BASH'
    echo "Hello, world!"
    BASH
  EOS
end

class String
  def strip_heredoc
    gsub(/^#{scan(/^[ \t]*(?=\S)/).min}/, ''.freeze)
  end
end

#strip_heredoc заимствовано из рельсов:

https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/string/strip.rb

вы, вероятно, могли бы получить его, требуя active_support, или, может быть, он загружается автоматически, когда вы находитесь в проекте rails, но я использовал этот внешний rails и поэтому должен был сам его защитить.

есть два heredocs, внешний с маркерами EOS и внутренний с маркерами BASH.

способ, которым это работает, заключается в подаче внутреннего heredoc между маркерами BASH в stdin bash. Обратите внимание, что он работает в контексте /bin/sh, так что это posix heredoc, а не ruby. Обычно для этого требуется, чтобы конечный маркер находился в столбце 1, Чего здесь нет из-за отступа.

однако, потому что он завернут в рубиновый heredoc,strip_heredoc метод применяется там деиндентирует его, помещая всю левую сторону внутренний heredoc в колонке 1 до /bin/sh видя его.

/bin/sh также обычно расширяются переменные в пределах heredoc, что может помешать скрипту. Одинарные кавычки вокруг маркера начала, 'BASH', tell /bin/sh не расширять ничего внутри heredoc, прежде чем он будет передан bash.

/bin/sh все еще применяет экранирование к строке перед ее передачей в bash. Это означает, что обратная косая черта побеги должны быть удвоены, чтобы сделать это через /bin/sh to Баш, т. е. \ становится \.

параметры bash -xeuo pipefail необязательны.

The -euo pipefail аргументы говорят bash работать в строгом режиме, который останавливает выполнение при любом сбое или ссылке на неопределенную переменную, даже команду в конвейере. Это вернет ошибку рейку, который остановит задачу рейка. Обычно это то, что вы хотите. Аргументы могут быть отброшены, если вы хотите нормальное поведение bash.

The -x возможность колотить и до #sh работать согласованно, так что грабли только печатает команды bash, которые на самом деле выполняются. Это полезно, если ваш скрипт не предназначен для запуска в полном объеме, например, если это был тест, который позволяет корректно завершить в начале скрипта.

будьте осторожны, чтобы не установить код выхода, отличный от 0, если вы не хотите, чтобы задача rake не удалась. Обычно это означает, что вы не хотите использовать || exit конструирует без установки кода выхода явно, т. е. || exit 0.

если вы столкнетесь с какой-либо странностью Баш по пути, выключите -o pipefail. Я видел немного багги, связанные с ним специально при конвейерной передаче в grep.

Comments

    Ничего не найдено.