Использование приложения Ruby on Rails для управления консольным приложением - PullRequest
0 голосов
/ 20 января 2012

Консольное приложение, которым я хотел бы управлять: Bluesoleil .Это программное обеспечение / драйвер Bluetooth, но я думаю, что детали программного обеспечения не так важны.По сути, я хочу набрать консольные команды в терминальной среде Windows или Linux с помощью веб-браузера, в котором запущено приложение Ruby on Rails.

Таким образом, высокоуровневый дизайн приложения Ruby on Rails может выглядеть примерно так.

  • Веб-браузер, отображающий страницу с пользовательским интерфейсом для Bluesoleil
  • Приложение Ruby on Rails отображает страницу для пользовательского интерфейса, принимает команды от пользователя и отображает результаты через веб-браузер, как обычный Ruby onПриложение Rails
  • На сервере Ruby on Rails вводит команды в консоли, на которой запущен Bluesoleil.Ruby on Rails получает результат, показанный в консоли, как строку.

Возможно ли что-то подобное с Ruby on Rails?

Просто чтобы устранить возможную путаницу, когда я говорю здесь консоль и консольное приложение, я не имею в виду консоль Rails или консоль Ruby.Консоль здесь - это просто терминальная среда, в которой выполняются консольные приложения и т. Д.

Спасибо.

1 Ответ

2 голосов
/ 20 января 2012

Если вам нужно всего лишь выполнить однократную команду, просто используйте галочки. Если вам нужно поддерживать длительный фоновый процесс, который принимает команды и возвращает ответы, вы можете сделать что-то вроде этого (некоторые детали были отредактированы, поскольку этот код взят из проприетарного приложения):

class Backend
  def initialize
    @running = false
    @server  = nil
    # if we forget to call "stop", make sure to close down background process on exit
    ObjectSpace.define_finalizer(self,lambda { stop if @running })
  end

  def start
    stop if @running
    @server = IO.popen("backend","w+")
    @running = true
  end

  def stop
    return if not @running
    @server << "exit\n"
    @server.flush
    @running = false
 end

 def query(*args)
   raise "backend not running" if not @running
   @server << "details edited out\n"
   @server.flush
   loop do
     response = parse_response
     # handle response
     # break loop when backend is finished sending data
   end
 end

 private
   def parse_response
     # details edited out, uses c = @server.getc to read data from backend
     # getc will block if there is nothing to read,
     # so there needs to be an unambiguous terminator telling you where
     # to stop reading
   end
 end

конец

Вы можете адаптировать это к вашим собственным потребностям. Остерегайтесь ситуаций, когда фоновый процесс умирает, а основной процесс зависает.

Хотя это не относится к вашей ситуации, если вы разрабатываете фоновую программу самостоятельно: создайте фоновый процесс так, чтобы, если НИЧЕГО произойдет сбой, он отправлял однозначное сообщение типа «ПАНИКА» или что-то, что говорит основной либо завершите работу с сообщением об ошибке, либо попробуйте запустить другой фоновый процесс. Кроме того, убедитесь, что это абсолютно однозначно, где каждое «сообщение» начинается и заканчивается, и хорошо проверяйте координацию между основным / фоновым процессом - если есть ошибки на любом конце, очень легко получить ситуацию, когда оба процесса застряли ждем друг друга. Еще одна вещь: разработайте «протокол», в котором 2 процесса общаются друг с другом таким образом, чтобы упростить синхронизацию между 2.

...