Что такое Unix way?


Что такое "unix way"? Что кроется за этим словосочетанием? Почему идеология, рожденная десятилетия назад, до сих пор является актуальной и позволяет старикам юниксоидам козырять ей перед "оконным" молодняком? Эти вопросы беспокоили меня с первых дней моего знакомства с Linux. Пришла пора поделиться найденными ответами.

Статья состоит из двух частей: развлекательной - краткой истории Unix и изложения основ философии Unix, и практической. Практические примеры далеки от идеала, и призваны показать направление решения, а не предоставить готовый 100% ответ. В целом статья носит обзорный характер и не претендует на полноту освещения затронутых вопросов, что, впрочем, должно позволить не уснуть читателю до последнего абзаца. И так...



История UNIX

..все началось в 1969 году, когда в недрах компании AT&T. Силами ее подразделения Bell Labs была разработана первая UNIX система. Во главе сотрудников исследовательской группы Bell стояли Кен Томпсон (Ken Tompson) и Деннис Ритчи (Dennis Ritchie).

Интересны факт, первое название системы было UNICS (UNiplexed Information and Computing Service). Этот вариант был предложен сотрудником компании AT&T Брайаном Керниганом, и, уже несколько позднее, система обрела свое знаменитое и судьбоносное название UNIX.

Одним из важнейших результатов разработки UNIX можно смело назвать рождение бессмертного языка C. Дело в том, что первые версии системы писались на ассемблере, что, вместе с высокой производительностью, вносило некоторые ограничения в переносимость системы. Решение Томпсона переписать все на языке высоко уровня и привело к появлению нового языка, прародителем которого был язык BCPL. Теперь, для портирования системы на новую архитектуру, достаточно было написать для нее компилятор языка C.

Еще одним ключевым результатом разработки UNIX стали конвейеры. Конвейеры - это цепочка  программ, каждая из которых выполняет некоторое действие и передает результат на вход следующей в конвейере  программе. Таким образом, программы, выстраиваясь в цепочку, приводят к результату,  который ограничен только воображением пользователя. Именно конвейеры стали ключевым изобретением в UNIX, породившим понятие Unix way.

Философия UNIX

Идея философии заключается в написании небольших программ, решающих только одну определенную задачу и взаимодействующих между собой с помощью текстовых потоков.

Изобретатель каналов UNIX Дуг МакИлрой, обобщил философию пути UNIX следующим образом:
«Философия UNIX гласит:
  • Пишите программы, которые делают что-то одно и делают это хорошо.
  • Пишите программы, которые бы работали вместе.
  • Пишите программы, которые бы поддерживали текстовые потоки, поскольку это универсальный интерфейс».
А в 1994 году Майк Ганцарз, опираясь на свой опыт работы с UNIX и популярные, в кругах специалистов работающих с UNIX, высказывания выделил главные принципы философии:

  1. Красиво — небольшое.
  2. Пусть каждая программа делает что-то одно, но хорошо.
  3. Собирайте прототип как можно раньше.
  4. Предпочитайте переносимость эффективности.
  5. Храните данные в простых текстовых файлах.
  6. Используйте возможности программ для достижения цели.
  7. Используйте сценарии командной строки для улучшения функционала и переносимости.
  8. Избегайте пользовательских интерфейсов, ограничивающих возможности пользователя по взаимодействию с системой.
  9. Делайте каждую программу «фильтром».
Существует еще десяток принципов, не снискавших общего признания в качестве части философии, но, тем не менее, заслуживающих внимания:

  1. Позвольте пользователю настраивать окружение.
  2. Делайте ядра операционной системы маленькими и легковесными.
  3. Используйте нижний регистр и придерживайтесь кратких названий.
  4. Не храните тексты программ в виде распечаток («Спасите деревья!»).
  5. Не сообщайте пользователю об очевидном («Молчание — золото»).
  6. Разбивайте сложные задачи на несколько простых, выполняемых параллельно («Мыслите "параллельно"»).
  7. Объединённые части целого есть нечто большее, чем просто их сумма.
  8. Ищите 90-процентное решение.
  9. Если можно не добавлять новый функционал, не добавляйте его («Чем хуже, тем лучше»).
  10. Мыслите иерархически.
и снова спасибо вики за информацию

Потоки ввода/вывода и каналы.

Не смотря на огромное количество красивых заявлений в принципах философии UNIX, наиболее распространенное представление о UNIX way строится вокруг конвейеров.

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

В операционных системах существует минимум три стандартных потока:
  • поток ввода(в него помещается информация вводимая с клавиатуры), 
  • поток вывода(из него читается информация выводимая на экран)
  • поток ошибок(предназначенный для вывода отладочной информации и информации об ошибках)
Потоки можно переопределять. Например, можно переопределить поток вывода, перенаправив его в файл, после чего результат работы программы будет записан в указанный файл. Управление потоками осуществляется с помощью команд >, >>, <.

команда < файл
Изменяет поток ввода, использует указанный файл как источник данных для стандартного потока ввода.

команда > файл
Направляет стандартный поток вывода в файл. Если файл не существует, он будет создан; если существует — перезаписан сверху.

команда >> файл
Направляет стандартный поток вывода в файл. Аналогично предыдущей команде, создает файл в случае его отсутствия, но если файл существует, не затирает его, а дописывает новую информацию в конец файла.

Чтобы понять, зачем такие сложности, приведу бытовой пример. Вы, как уважающий себя любитель музыки, скачали  любимый музыкальный альбом в формате .flac к которому прилагается файл .cue с описанием треков альбома. Но автор раздачи при создании .cue файла использовал кодировку, отличающуюся от вашей(пользователям линукс такое точно знакомо) и теперь плеер, вместо внятной информации о треке, показывает крякозябры. Чтобы изменить кодировку файла, можно воспользоваться утилитой iconv:
$ iconv -f cp1251 -t utf8 < album_cp1251.cue > album_utf8.cue
Утилита iconv преобразует содержимое потока ввода из одной кодировки (указанной в параметре -f) в другую(указанную в параметре -t). Содержимое изначального файла выводится в поток ввода, а поток вывода перенаправляется в новый файл. Что делать после этого с файлом в старой кодировке решать Вам :)

 Потоки можно перенаправлять не только в файл, но и в программы. Для этого существует команда | . Ее вызов эквивалентен следующей последовательности команд:
команда_1 > temp.txt
команда_2 < temp.txt
rm temp.txt
Это называется каналом(англ. pipe). Каналы позволяют с легкостью объединять программы в конвейеры и добиваться удивительных результатов.

Чтобы показать всю мощь и гибкость каналов, вернемся к "музыкальному" примеру. Как правило, вместе с .cue файлом идет большой файл .flac, содержащий в себе весь альбом описываемый .cue файлом. На сегодня далеко не все музыкальные плееры способны понимать, исходя из информации в .cue, что во .flac несколько треков. Это приносит серьезные неудобства. Как вариант решения проблемы, можно единый .flac разбить на кучу маленьких, содержащих ровно по одному треку, файлов. Для этого можно воспользоваться следующими утилитами:

  • cuebreakpoints - выводит время окончания треков из CUE или TOC файлов.
  • shnsplit - разбивает .flac файл на несколько маленьких в соответствии с временными отметками, поданными на вход программы.
  • cuetag - записывает теги на основе информации в .cue файле
Объединив первые две в конвейер, получим нарезанные .flac файлы.
$ cuebreakpoints "Pink Floyd - Animals.cue" | shnsplit -o flac "Pink Floyd - Animals.flac"
По умолчанию, имена файлов генерируются как split-track<номер>.flac. Чтобы изменить часть имени перед номером, существует ключ -n. Подробнее о нем в man странице.
Чтобы добавить в получившиеся файлы описание тегов, надо вызвать cuetag:
$ cuetag "Pink Floyd - Animals.cue" split-track*.flac
Главное, не забыть изменить кодировку .cue файла перед присваиванием тегов ;)

Вообще, проблема кодировки тегов присуща не только .flac файлам. Любители музыки в mp3 наверняка это хорошо знают. Следующий конвейер команд находит все Mp3 файлы в указанной директории и меняет кодировку их тегов, а также удаляет устаревшие теги:
$ find /home/music -iname "*.mp3" -print0 | xargs -0 mid3iconv -e CP1251 --remove-v1
Разве не прелесть? А если вынести адрес директории в параметр, да повесить на такой конвейер псевдоним, то вообще красота!

И так, мы подошли к инструменту, который делает подход unix не просто интересным и местами удобным, а по настоящему мощным инструментом в решении повседневных задач. Я говорю о скриптах - последовательности команд, записанных в файл и выполняемых как одна единая команда.

Для примера воплотим в жизнь идею, о совершенствовании решения по исправлению mp3 тегов. Для это необходимо создать текстовый файл и записать в него следующее содержимое:
#!/bin/sh
if [ $# == 0 ]; then 
        echo "Не указана директория"
        exit -1
fi
find $1 -iname "*.mp3" -print0 | xargs -0 mid3iconv -e CP1251 --remove-v1

Чтобы сделать файл исполняемым, выполните
$ chmod +x <файл со скриптом>

Приведенный скрипт подставляет первый аргумент вызова в качестве директории в команду find. Обратите внимание на конструкции $# и $1. Первая - это переменная, возвращающая количество аргументов вызова скрипта, вторая переменная возвращает первый аргумент вызова. Скрипт проверяет количество аргументов и, если аргументы не были указаны, сообщает об этом и завершает свою работу. Скрипт далек от идеала и не решает многих нюансов с передачей директорий в качестве параметра, но аккуратно записанный полный путь  вполне должен дать скрипту корректно отработать.

Итоги

В повседневности, возможности unix подхода к решению задач ограничивается только воображением и знанием команд. Последнее, к сожалению, является серьезным препятствием для популяризации unix way среди обывателей. Хоть и законно, но не заслуженно. Знание даже самых базовых команд и понимания принципа их взаимодействия может серьезно упростить Вам жизнь и избавить от повседневной рутины.


Что еще почитать:

  1. История компьютерного андеграунда
  2. История OC UNIX
  3. Философия UNIX
  4. Стандартные потоки ввода/вывода
  5. Искусство программирования на языке сценариев командной оболочки

4 комментария:

Анонимный комментирует...

Хорошо изложено, спасибо.

Владимир Попов комментирует...

Приятно знать, что писал не зря.

Unknown комментирует...

Очень хорошо написано, благодаря этой статье многое стало ясным и понятным

Unknown комментирует...

Супер) Спасибо. UNIX рулит