Наши партнеры








Книги по Linux (с отзывами читателей)

Библиотека сайта rus-linux.net

Bourn-ый гений

52(223)/30.12.2002

Сергей ЯРЕМЧУК grinder@ua.fm

(Окончание, начало см. в МК 51 (222))

Но самое интересное, что возможности bash не ограничены тем, что было перечислено в предыдущей части статьи. В интерпретатор встроен мощный язык программирования, который можно использовать для самых разнообразных задач: от автоматизации часто повторяющихся команд до сложной обработки данных. Чтобы не быть голословным, напишем небольшой скрипт. Кто записывал диски под Linux согласятся со мной, что работать с командной строкой неудобно из-за необходимости постоянно помнить большое количество опций, к тому же и запись разбита на два этапа: создание образа и непосредственно запись (последнее я все же не считаю недостатком). И, естественно, хочется хоть как то проверить результат. Но кто пользовался различными фронт-эндами, отметит, что для их освоения также требуется некоторое время. Мне, например, проще ввести путь к нужному каталогу, чем искать путь с помощью менеджера. Итак, решено — будем автоматизировать. Нумерация строк приведена исключительно ради удобства, вводить номера не надо.

Вот такой получился скриптик. Недостатки, конечно, есть (о некоторых по ходу), но я специально убрал все лишнее, чтобы было понятно. Главное ведь — показать возможности и побудить интерес к творчеству. Выкладывать в Интернете для всеобщего обозрения его я бы не стал, уж слишком много параметров желательно проверить, но для личного использования, по-моему, больше и не надо. Сначала пару слов о безопасности. Если посмотреть внимательно на применяемые команды, то станет ясно, что использовать данный скрипт может только суперпользователь. Ведь монтировать/размонтировать файловую систему и выключать компьютер может только он. Но если не хотите каждый раз набирать su, то для домашнего использования можно установить права хоть chmod 4777, т.е. включить бит SUID, сделать владельцем root'a и потихоньку работать с данным скриптом. Но если вы сисадмин на какой-либо фирме, то сперва хорошенько подумайте, ведь тем самым вы фактически предоставляете доступ к любому каталогу. Иначе все файлы с отчетами или паролями в один прекрасный день уйдут к конкурентам (да еще и в удобной форме), и какие слова скажет после этого шеф — не напечатает ни один журнал. Но и в этом случае не все потеряно: можно изначально ограничить пользователя только его домашним каталогом.

Теперь немного разберем работу скрипта. Первая строка в большинстве случаев необязательна, но наличие ее считается хорошим тоном: она указывает на месторасположение программы, которая будет обрабатывать скрипт. Вторая начинает классический оператор цикла for. В данной случае его используем для того, чтобы перебрать все аргументы командной строки по очереди; при большом количестве параметров удобнее, как мне кажется, использовать селектор case.

Список аргументов, передаваемых скрипту, содержится в переменной $* одним массивом (к каждому можно обратиться и непосредственно, используя $1, $2 и т.д.), а и их общее количество — в $#. Обратите внимание: когда два разных оператора идут в одной строке, их необходимо разделить точкой с запятой.

В строке 3 встречаемся с оператором выбора if условие then действие fi. В нашем случае мы сравниваем значение первого введенного пользователем аргумента со строкой -h; если происходит совпадение, то выполняются операторы блока.

Несколько команд echo просто выводят на терминал справочное сообщение, а команда exit завершает выполнение скрипта. Нормальным (без ошибок) завершение программы считается, когда код возврата равен нулю (как в нашем скрипте), ненулевой указывает на определенную ошибку в программе. Определить код возврата последней выполненной программы можно, используя переменную $?.

В строках 13-19 ситуация аналогична, но здесь вдобавок выполняются определенные действия: появился оператор shift, предназначенный для сдвига позиций массива $# влево, а по-простому убирающий первый элемент, благо он нам в дальнейшем уже не нужен.

В строке 17 очищается содержимое CD-RW диска; подробности смотрите в статье mchno. Здесь можно было просто установить какой-нибудь флаг, как в строке 23, а само действие выполнить позже. И более того, саму очистку провести в фоне и уже непосредственно перед записью отследить состояние и код завершения с помощью функции wait. Однако быстрая очистка, применяемая в нашем случае, не займет много времени, а усложнять скрипт не хотелось бы. Узнать, что процесс завершился без ошибок (ведь если очистка не удалась, то дальнейшие действия бесполезны), позволит оператор логического ИЛИ — ||. Если кратко, когда первый операнд равен единице, то результат всего выражения фактически определяет второй операнд, а если первый равен нулю, то второй можно не проверять — общий результат однозначно будет нулевым. Т.е. если операция стирания завершилась удачно (0), то дальнейшие действия не производятся, а если что-то там не получилось, будет задействован оператор exit, т.е. скрипт просто завершит работу: здесь как раз использован код завершения последнего процесса (для разнообразия — в данном случае значение не играет никакой роли, но можно его обрабатывать и предпринимать определенные действия).

В строках 26-30 проводится проверка наличия оставшихся аргументов; если пользователь не указал каталог для записи, то необходимости в дальнейших действиях нет — пользователю выводится предупреждающее сообщение, и скрипт заканчивает свою работу. Это, кстати, позволяет использовать скрипт просто для очистки CD-RW диска.

Функция echo в строке с параметром -n выводит строку без завершающего знака перевода строки. Это нам нужно для наглядности, потому что в следующей, 33-й строке программа останавливается и ждет ввода с клавиатуры метки диска. Если есть желание, то можете переделать программу так, чтобы задавать метку прямо в командной строке — лично мне хотелось лишь показать взаимодействие с пользователем.

В строке 34 непосредственно создается образ указанных каталогов. Обратите внимание на использование переменной $*, которая на данный момент содержит только список каталогов, указанных пользователем (все остальное убрано при помощи shift), ее применение (а не $1) позволяет организовать запись в несколько каталогов.

Но я себе просто не мог отказать в удовольствии автоматически проверить результат предыдущей операции, что и происходит строках 36-47. Для чего монтируем созданный образ и сравниваем его с оригиналом. Но так как команда diff (флаги ar указывают на проверку каталогов и рекурсивный их обход) может работать только с двумя операндами, такая проверка возможна только в случае, когда указывается один исходный каталог для записи.

Строка 40 необходима для того чтобы сохранить результат предыдущей операции; если поставить ее после операции размонтирования, то переменная $? будет содержать уже другое значение, а для umount и вовсе места не найдется. Последнюю, конечно, можно использовать дважды — где-то в строке 44 в случае неудачного сравнения, или в 48-й при успехе. В крайнем случае придется размонтировать вручную по окончанию работы, что как-то некрасиво. Если все же есть необходимость в проверке, независимо от количества исходных каталогов можно просто предварительно скопировать для работы все в одну директорию (используя команду find и архивацию на лету —лучший способ бэкапить данные), а затем удалить по окончанию работы.

В строке 48 переменой size присваиваем результат выполнения команды du, с помощью которой узнаем размер полученного файла, который мы и выводим пользователю в следующей строке.

На основании этих данных в строках 50-55 решается, будет ли производится запись. Это позволяет использовать программу для создания и проверки образов каталогов — если размер образа либо слишком велик для записи, либо мал, то от дальнейших действий можно отказаться.

В строке 56 происходит непосредственно запись; здесь уже используется операция логического И, т.е. второе действие (в нашем случае удаление образа) происходит лишь в том случае, если удачно завершилось первое. Это позволит не проходить заново все пункты просто из-за того, что болванка оказалась порченая. Задавать все параметры необязательно, можно выставить большинство по умолчанию в файле /etc/cdrecord.conf.

Наконец, в последних 57-60 строках в случае установки флага, означающего выключение компьютера, производится требуемая операция. И это еще не все проверки, которые можно осуществить автоматически. Можно вычислить контрольную сумму созданного образа и сравнить ее с контрольной суммой записанной на болванку:

Могу сказать, что пользуюсь данным скриптом не один день — проблем меньше, да и удобство, понимаете. Но и это еще не все. Теперь открываем файл $HOME/.mc/menu и заносим в него следующие строки:

И теперь достаточно в Midnight Commander-е выделить необходимые файлы и каталоги, нажать F2 и W, и они тут же все отправятся на запись. На заре моего увлечения Linux я начал писать плагин к FAR — так вот, времени и трудов на это ушло намного больше, не говоря уже об опыте. А вот эту программулину наваял всего минут за пятнадцать. Почувствуйте разницу. Единственный минус программы — она не позволяет дозаписывать мультисессионные диски, но и это при необходимости можно исправить.

К сожалению (а скорее, к радости), в одной статье просто невозможно рассказать обо всех прелестях bash, но думаю, и этого достаточно, чтобы побудить к самостоятельным исследованиям. Тем более, как видите, совсем небольшое усилие спасает от кучи монотонной работы — лично мне этого так не хватало в Windows. Тем, кто интересуется системой всерьез, советую заглянуть по адресу http://linuxshop.ru/unix4all, где Алексей Федорчук начал довольно интересный проект с целью рассказать, как устроен Unix. Итак,

Linux forever!