Используйте Ruby, чтобы определить, отвечает ли платформа на команду CLI

Я работаю над проектом Rails 4 с открытым исходным кодом, в котором используется набор инструментов PDF (жемчужина «pdf-forms») для автоматического заполнения форм PDF на основе информации, хранящейся в базе данных приложения. PDFtk требует установки двоичных файлов, а для созданной модели PDFtk требуется путь к двоичным файлам. Путь должен быть динамическим, чтобы он работал на Heroku, Mac OS X и Windows. Я могу найти путь на машине * nix с помощью команды «what». Но Windows не использует «какой», она использует «где».

Есть ли способ определить, отвечает ли платформа на команду, и если да, то выполнить команду?

Моя лучшая попытка — определить платформу с помощью RbConfig (см. ниже). Однако некоторые платформы Windows (например, Cygwin) реагируют на команды *nix. Как пользователь Mac, я не знаком со всеми платформами для Windows.

def pdftk
  # Use path stored in Heroku env vars or else get path to local binaries
  @pdftk ||= PdfForms.new(ENV['PDFTK_PATH'] || local_path) 
end

def local_path
  os = RbConfig::CONFIG['arch']
  if /mswin/ =~ os
    path = `where pdftk` # Get pdftk filepath, Windows equiv of *nix 'which' command
  else
    path = `which pdftk` # Get pdftk filepath on POSIX systems
  end

  path
end

person femmestem    schedule 19.03.2016    source источник
comment
Не могли бы вы уточнить, зачем вам нужен проект Rails для запуска на хостах Windows? Вы собираетесь отправить весь проект конечному пользователю? Независимо от того, согласен ли пользователь с установкой проекта rails, я бы выбрал обязательную настройку типа config.rb для пути со значением по умолчанию, установленным там, где эта библиотека установлена ​​«из коробки». (Или с настройкой env, как вы показали в ОП.)   -  person Aleksei Matiushkin    schedule 19.03.2016
comment
@mudasobwa Я удаленно сотрудничаю с разработчиками, использующими машины Windows, где некоторые не могут / не хотят использовать Cygwin или аналогичные. Использование config.rb с жестко заданными путями к файлам не решит проблему определения платформы.   -  person femmestem    schedule 19.03.2016
comment
Справедливо. Я не имел в виду жестко закодированные пути. Я имел в виду, что вы можете заставить соавторов изменить содержимое этого файла или установить переменную env. Ведь они разработчики, а не заказчики. И, ИМХО, это не кодовый элемент, который действительно нужно шлифовать. Обнаружение платформы, как вы показали, уже намного лучше, чем ничего.   -  person Aleksei Matiushkin    schedule 19.03.2016
comment
А, спасибо за разъяснение, это имеет смысл.   -  person femmestem    schedule 19.03.2016
comment
Примечание: все три вхождения path в источнике local_path избыточны. if в ruby ​​возвращает результат. Я бы просто удалил все, что начинается с if, и вместо этого использовал "#{/mswin/ =~ os ? 'where' : 'which'} pdftk". (Измените двойные кавычки на обратные кавычки.)   -  person Aleksei Matiushkin    schedule 19.03.2016
comment
Вам обязательно нужно знать полный путь к pdftk? Есть некоторые полурешения для Windows эквивалент команды unix which. Однако, почему бы вам просто не попробовать вызвать команду pdftk без каких-либо параметров и увидеть код выхода в $?? Если вы получаете ненулевой код выхода, скорее всего, программа не существует на платформе.   -  person BoraMa    schedule 19.03.2016
comment
Кажется, для такого рода вещей есть жемчужина, о которой говорилось здесь: stackoverflow.com/questions/11784109/   -  person JLB    schedule 19.03.2016
comment
Если вы создаете проект с открытым исходным кодом, конечно, вы хотите, чтобы он был как можно более независимым от платформы. @мудасобва   -  person Meier    schedule 19.03.2016
comment
Общие предложения @Meier редко являются абсолютной истиной. Один из самых известных проектов с открытым исходным кодом, Linux, вряд ли можно назвать кроссплатформенным. Я, конечно, не говорю, что надо хардкодить C:\ProgramFiles или типа того, но в данном случае, принимая во внимание, что я не предлагал избавиться от поддержки Windows, а сделать это изменением config файла, такой подход вполне приемлем.   -  person Aleksei Matiushkin    schedule 19.03.2016


Ответы (2)


Модуль stdlib mkmf имеет малоизвестную вспомогательную функцию find_executable(), которая должна дать вам то, что вы хотите.

require 'mkmf'
path = find_executable('cli-command')

Я лично не тестировал его в Windows, но полагаю, что он должен работать... http://ruby-doc.org/stdlib-2.3.0/libdoc/mkmf/rdoc/MakeMakefile.html#method-i-find_executable

person 10dot    schedule 19.03.2016

Команда where должна быть доступна как минимум с Windows 7.

Если вы используете jruby, команда RbConfig::CONFIG['arch'] даст вам идентификатор, связанный с java. В соответствии с этим вопросом вместо этого вы можете использовать host_os (проверено с jruby 9000 в Windows 7).

Вы также можете сделать код более удобным для своих коллег, проверив ошибки вызова команды what/where:

def local_path
  os = RbConfig::CONFIG['host_os']
  if /mswin/ =~ os
    path = `where pdftk` # Get pdftk filepath, Windows equiv of *nix 'which' command
  else
    path = `which pdftk` # Get pdftk filepath on POSIX systems
  end
  unless $?.success?
    log.error "failure to find the pdfkit excutable path"
    puts "Please set the PDFTK_PATH environment variable to point to the pdftkkit executable"
    path = ""  # maybe throw an exception here
  end
  path
end
person Meier    schedule 19.03.2016
comment
Трудно принять один правильный ответ между вашим и 10dot, потому что в итоге я использовал оба варианта в комбинации. Я принял ответ 10dot как правильный, потому что он был специфичен для того, чего я пытался достичь. Тем не менее, я также поддерживаю ваш ответ за в целом хороший совет о том, как переложить ответственность на других разработчиков, чтобы правильно настроить их среду и обеспечить ее соблюдение с помощью хороших сообщений об ошибках. - person femmestem; 22.03.2016