Unix при передаче команды переменной в сценарий оболочки? - PullRequest
1 голос
/ 31 марта 2010

Я пытаюсь настроить простой таймер, который запускается из приложения Rails. Этот таймер должен дождаться своей продолжительности, а затем запустить сценарий оболочки, который запустит ./script/runner и завершит начальный запрос. Мне нужен скрипт / бегун, потому что мне нужен доступ к ActiveRecord.

Вот мои тестовые строки в Rails

output = `at #{(Time.now + 60).strftime("%H:%M")} < #{Rails.root}/lib/parking_timer.sh STRING_VARIABLE`
return render :text => output

Тогда мой parking_timer.sh выглядит так

* +1007 *

Наконец, ParkingTimer.rb читает переданную переменную с

ARGV.each do|a|
   puts "Argument: #{a}"
end

Проблема в том, что команда Unix "at", похоже, не любит переменные и хочет иметь дело только с именами файлов. Я либо получаю одну из двух ошибок в зависимости от того, как я позиционирую "s

Если я поставлю кавычки вокруг правой стороны, вот так

... "~ / PATH_TO_APP / lib / parking_timer.sh STRING_VARIABLE"

Я понимаю,

-bash: ~ / PATH_TO_APP / lib / parking_timer.sh STRING_VARIABLE: Нет такого файла или каталога

Я оставляю цитаты, я получаю,

at: искаженное время

Все это происходит на Mac OS 10.6 с Rails 2.3 и Ruby 1.8.6

Я уже бездельничал с BackgrounDrb и решил, что это полная PITA. Мне нужно иметь возможность отменить работу в любое время до ее наступления.

1 Ответ

1 голос
/ 31 марта 2010

Немного поиграв с irb, вот что я нашел.

Оператор обратного вызова вызывает оболочку после того, как ruby ​​выполнил любую необходимую интерпретацию. Для моего тестового примера вывод strace выглядел примерно так:

execve("/bin/sh", ["sh", "-c", "echo at 12:57 < /etc/fstab"], [/* 67 vars */]) = 0   

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

/bin/sh -c "at 12:57 < RAILS_ROOT/lib/parking_timer.sh STRING_VARIABLE"

Это выглядит очень странно . Вы действительно хотите передать parking_timer.sh, скрипт, как ввод в команду at?

То, что вы, вероятно, в конечном итоге хотите, примерно так:

/bin/sh -c "RAILS_ROOT/lib/parking_timer.sh STRING_VARIABLE | at 12:57"

Таким образом, выходные данные команды parking_timer.sh станут входными данными для команды at.

Итак, попробуйте следующее:

 output = `#{Rails.root}/lib/parking_timer.sh STRING_VARIABLE | at #{(Time.now + 60).strftime("%H:%M")}`
return render :text => output

Вы всегда можете использовать strace или truss, чтобы увидеть, что происходит. Например:

strace -o strace.out -f -ff -p $IRB_PID

Затем grep '^exec' strace.out*, чтобы увидеть, где выполняется команда.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...