LE Blog

Инженер с поэтической душой

07.10.2009 firtree_right Некоторые тонкости стыковки 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"

Материалы для самостоятельного изучения

Документация по bash