07.10.2009Некоторые тонкости стыковки ruby и bash
Введение
Последнее время больше занимаюсь работой системного администратора нежели программиста. Прошлую неделю даже пропустил написание статьи. Это, конечно, не означает, что совсем нечего рассказать.
Поскольку для быстроты я обычно пишу большинство скриптов на руби, необходимо чтобы они следовали некоторым тонкостям работы с командной строкой.
Условное выполнение
В bash кроме разделителей команд «&» и «;», существует ещё и условное выполнение списка команд с помощью «&&» и «||». Их работа зависит от кода, с которым произошёл выход. exit0:
#!/usr/bin/env ruby
puts "Выход с кодом 0"
exit 0
exit1:
#!/usr/bin/env ruby
puts "Выход с кодом 1"
exit 1
Теперь если запустить скрипты в следующем сочетании:
./exit0 && ./exit0 && ./exit1 && ./exit0
То вывод будет следующий:
Выход с кодом 0
Выход с кодом 0
Выход с кодом 1
А если запустить скрипты в следующем сочетании:
./exit1 || ./exit1 || ./exit0 || ./exit1
То вывод будет следующий:
Выход с кодом 1
Выход с кодом 1
Выход с кодом 0
То есть, «&&» выполняет следующую команду, если предыдущая вышла с кодом 0, а «||» выполняет следующую команду, если предыдущая вернула ненулевой код. Условно говоря, первый список выполняется пока всё срабатывает, а второй -- пока не срабатывает.
Перенаправление вывода с помощью pipeline
Тут всё просто. Если в bash команды разделены с помощью «|», то вывод первой команды будет перенаправлен на вход второй.
Простая демонстрация из трёх файлов. show:
#!/usr/bin/env ruby
$KCODE = "utf8"
$stdout.puts "stdin содержит: #{$stdin.read.inspect}"
out:
#!/usr/bin/env ruby
$stdout.puts "Привет из stdout!"
err:
#!/usr/bin/env ruby
$stderr.puts "[*stderr*] Привет из stderr!"
$stdout.puts "Привет из stdout!"
Думаю, не составит труда выяснить, что выводят запущенные отдельно out и err, но вот, что из этого можно сделать с помощью pipeline:
./out | ./show
выводит
stdin содержит: "Привет из stdout!\n"
Когда же есть обращение к другому каналу вывода, то
./err | ./show
выводит
[*stderr*] Привет из stderr!
stdin содержит: "Привет из stdout!\n"
Вывод stderr можно перенаправить в stdout:
./err 2>&1 | ./show
выводит
stdin содержит: "[*stderr*] Привет из stderr!\nПривет из stdout!\n"