ске или в другой смонтированной файловой системе. После того, как файл ско- пирован, выдается сообщение, которое говорит о том, какой файл и куда был передан. Удобно иметь в файле протокола эту информацию, поскольку мы имеем возможность проследить, куда были пересланы ваши скопированные файлы. Цикл find выполняется до тех пор, пока не скопируются все файлы в текущем сегменте дерева. Напомним, что команда find рекурсивная, поэто- му убедитесь, что вы указывали не больше деревьев, чем вы хотели. Если вы указали "копировать, начиная с корня (/)", то может быть передан каждый файл, имеющийся в системе. Когда цикл for выполнился, внешний цикл while идет к следующей итерации. Когда все входные данные обрабо- таны, программа завершается. Некоторые особенности uucp Когда используется uucp, в маршруте приемника должен быть установ- лен бит разрешения выполнения ("x") для группы "others" (остальные) для всех промежуточных каталогов, ведущих к файлу. Это будет выглядеть так: --------x Самый последний каталог должен иметь права доступа вида "wx", что- бы uucp могла писать файл в каталог. После этого владельцем файла счи- тается uucp. Если собственником файла хотите быть вы, скопируйте его (используя cp, а не mv) с другим именем и он будет вашей собствен- ностью. Если вы переименуете его командой mv, вы только измените имя, связанное с тем же индексным описателем файла (inode). Но если вы ско- пируете его командой cp, вы создадите новый отмеченный описатель файла. Этот новый описатель файла (созданный вами) имеет ваши идентификатор пользователя (uid) и идентификатор группы (gid), поэтому вы владеете им. Если вы находитесь в корне системы и копируете файл (используя cp, а не mv) поверх другого существующего файла, информация в описателе файла не изменяется, а меняются только данные, доступ к которым указывает описатель файла. Когда uucp устанавливает предшествующие права доступа к файлу на всех промежуточных каталогах такими, что все имеют право записи, последний каталог НЕ будет иметь защиты. Предоставление любому пользо- вателю права записи означает, что кто угодно может удалить или изменить файлы в этом каталоге. Не каждый хочет давать всем это право. Если же вы копируете файлы в обычную область команды uucp общего доступа (/usr/spool/uucppublic/$LOGNAME), то вы должны внимательно следить за ними. Многие системы имеют запускаемые с помощью cron программы, произ- водящие в данном каталоге поиск файлов, к которым не было доступа в те- чение определенного количества дней, и удаляют такие файлы - это вредит вашим копиям. Если период хранения больше, чем промежуток между вашим копированием, у вас может быть все в порядке. Как и многое другое, это зависит от ваших обстоятельств и требований безопасности. Усовершенствования В оригинале файл со списком маршрутов имеет аргумент TYPE в конце аргумента FROM, например /usr/russ/bin/*. Это представляет проблему (кроме того, что показывает, что ваш автор еще не является мастером!), потому что когда символ * будет выделен, он будет расширен в имена всех файлов вместо того, чтобы трактоваться как литеральный символ. Простое решение - использовать отдельные поля, что и было сделано. Мастерским решением является экранировать метасимвол для сохранения его как лите- рального символа. Как только символ * будет выделен из маршрутного име- ни, символ \ представит его в виде * вместо того, чтобы дать его на расширение. Например, можно написать так: TYPE=`basename \"$FROM"` Здесь символ * присваивается переменной TYPE, вместо того, чтобы присвоить TYPE список всех файлов, которые соответствуют метасимволу. Затем, когда будет вызвана команда find, переменная TYPE должна быть экранирована так, чтобы метасимвол интерпретировался не командным про- цессором, а самой командой find. 3.3.2. cpiobr - копирование и восстановление файлов в виде потока данных ------------------------------------------------------------------- Имя: cpiobr ____________________________________________________________________ cpiobr Копирование и восстановление в виде потока данных командой cpio НАЗНАЧЕНИЕ Обеспечивает интерфейс в виде меню с командой cpio и удобства при копировании и восстановлении файлов. Выходные данные на носитель копи- руются в виде потока данных. ФОРМАТ ВЫЗОВА cpiobr Пример вызова cpiobr Вызывает главное меню для копирования, восстановления или выдачи списка файлов Командный файл cpiobr 1 : 2 # @(#) cpiobr v1.0 Cpio stream backup and restore Author: Russ Sage 4 if [ "$#" -gt "0" ] 5 then echo "cpiobr: too many arguments" 6 exit 7 fi 9 while : 10 do 11 c 12 set `date` 13 echo " 15 $1, $2 $3 $4 17 Cpiobr Backup & Restore 18 ----------------------- 19 Backup to removable media 20 Restore from removable media 21 List files on media 22 Long list files on media 23 to exit 25 Press b,r,f,l or : \c" 27 read CMD 28 if [ "$CMD" = "" ] 29 then break 30 fi 32 ABORT=off 34 while : 35 do 36 echo " 38 Enter media type: 39 Raw System V floppy drive (/dev/rfp021) 40 Raw XENIX floppy drive (/dev/rfd0) 41 Tape drive (/dev/rmt0) 42 Any device (/dev/???) 43 to exit 45 Press s,x,t,a, or : \c" 47 read MEDIA 48 case $MEDIA in 49 s|S) DEV=/dev/rfp021 50 break;; 51 x|X) DEV=/dev/rfd0 52 break;; 53 t|T) DEV=/dev/rmt0 54 break;; 55 a|A) echo "enter full pathname (or <> to exit): \c" 56 read DEV 57 if [ "$DEV" = "" ] 58 then continue 59 else break 60 fi;; 61 "") ABORT=on 62 break;; 63 *) echo "cpiobr: invalid command \"$MEDIA\"";; 64 esac 65 done # while get media 67 if [ "$ABORT" = "on" ] 68 then continue 69 fi 71 case $CMD in 72 b|B) echo "\nEnter the source directory name: \c" 73 read SRC 74 cd $SRC 75 echo "\nPlace floppy in drive and hit ...\c" 76 read CMD 77 find . -print | sort | cpio -ocBv > $DEV 78 echo "\nhit \c" 79 read CMD 80 ;; 81 r|R) echo "\nEnter the destination directory name: \c" 82 read DEST 83 cd $DEST 84 echo "\nPlace floppy in drive and hit ...\c" 85 read CMD 86 cpio -icBvdmu < $DEV 87 echo "\nhit \c" 88 read CMD 89 ;; 90 f|F) cpio -icBt < $DEV 91 echo "\nhit \c" 92 read CMD 93 ;; 94 l|L) cpio -icBtv < $DEV 95 echo "\nhit \c" 96 read CMD 97 ;; 98 *) echo "cpiobr: invalid command \"$CMD\"" 99 ;; 100 esac 101 done Переменные среды выполнения ABORT Флаг, определяющий, делать ли аварийное прекращение CMD Команда, получаемая от пользователя DEST Каталог-приемник при восстановлении DEV Маршрутное имя устройства носителя MEDIA Хранит тип устройства, которое будет использоваться SRC Каталог-источник при копировании Описание Зачем нам нужен cpiobr? Мы уже получили представление об удобстве и управлении копировани- ем с помощью команды autobkp, но мы еще не имели дела с неструктуриро- ванными устройствами. Это такие устройства, которые не содержат файло- вую систему, а просто имеют данные, которые записаны на них в виде по- тока данных. В таком качестве используются магнитные ленты и иногда гибкие диски. Как указывалось ранее, у вас может отсутствовать дисковое пространство или размещенная в другом месте система для копирования в формате файловой системы. Вместо этого вам может потребоваться исполь- зовать комплект гибких дисков или магнитную ленту. Даже если у вас име- ются другие возможности для копирования, может наступить время, когда копия на магнитной ленте или гибких дисках может быть оправдана как до- полнительная мера предосторожности, поскольку впоследствии вы можете восстановить ленту или гибкие диски в другом месте. Проблема заключается в том, что имеется широкий набор версий син- таксиса команды cpio для такого копирования, которые зависят от формата и используемого устройства. Если вы переключаете устройства, вы должны запомнить (или должны посмотреть) соответствующий синтаксис. Одним из решений является прямое указание различных вариаций команды cpio в тексте программы и вызов их в ответ на меню, которое просто спрашивает пользователя, какого типа носитель должен быть использован. Это наш подход при написании cpiobr. Другое преимущество системы меню заключа- ется в том, что вы можете приспособить рутинную работу по выполнению такого рода копирования для неопытного оператора или канцелярского ра- ботника, которым требуется знать только лишь, как монтировать магнитную ленту или другой носитель и отвечать на вопросы меню. Что делает cpiobr? Cpiobr - это управляемая с помощью меню интерактивная утилита ко- пирования и восстановления. На самом деле это интерфейс с командой cpio системы UNIX. Функции, предоставляемые меню, включают копирование фай- лов с жесткого диска на гибкий диск, восстановление файлов с гибкого диска на жесткий диск, выдачу списка имен файлов, хранимых на гибком диске и выдачу списка файлов с необязательной дополнительной информаци- ей (подобно ls -l). Гибкий диск здесь является первичным устройством назначения, но могут использоваться и другие носители, такие как маг- нитная лента большой емкости или кассетная магнитная лента (streamer). После выбора типа операции, которая должна быть выполнена, нужно выбрать тип используемого устройства. Утилита Cpiobr может быть исполь- зована на устройствах системы UNIX фирмы AT&T (/dev/fp021), устройствах системы XENIX фирмы IBM (/dev/fd0), стримерной ленте (/dev/rmt0) или любом другом устройстве по вашему желанию (/dev/???). Обычно имя уст- ройства определяет тип используемого носителя. Поскольку эта утилита предназначена для всех машин UNIX, некоторые из вариантов могут отсутствовать в вашей машине, поэтому вы имеете право выбрать любое имя устройства, которое вам необходимо. Как только имя устройства выбрано и, если вы выполняете копирова- ние или восстановление, вам задается вопрос, что является катало- гом-источником или каталогом-приемником. Укажите имена каталогов, начи- ная с вашего текущего каталога или абсолютное полное имя, начиная с корня (/.), после чего cpiobr переходит в этот каталог и затем исполь- зует относительные полные имена с этого места. Тем самым исключаются любые проблемы, связанные с тем, что абсолютное полное имя становится частью самой копии. Если вы даете относительное полное имя, убедитесь в том, что оно начинается от вашего текущего каталога, чтобы cpiobr начал работать с нужного места в дереве файлов. Когда файлы копируются на желаемый носитель, маршрутное имя, пере- данное cpio, начинается с "/.". Это означает, что никакого префикса имени каталога на гибком диске нет. Поэтому при восстановлении файлов обязательно нужно дать полное маршрутное имя. Все файлы, поступающие с гибкого диска, будут помещены прямо в каталог-приемник, который вы ука- зали cpiobr. Примеры (Здесь приводятся ответы на запросы главного меню, подменю и до- полнительная информация, появляющиеся в таком порядке.) 1. b x $HOME Копирует файлы на гибкий диск системы XENIX, начиная с каталога $HOME. 2. r a /dev/rmt0 $HOME Восстанавливает файлы с устройства, выбранного мной (/dev/rmt0, магнитная лента), и помещает файлы в мой регистрационный каталог. 3. l s Выдает в широком формате информацию обо всех файлах, размещенных на гибких дисках системы UNIX машины типа PC. Пояснения В строках 4-7 производится проверка на наличие ошибок условий вы- полнения. Единственная ошибка условий выполнения - это когда вы указали какие-либо аргументы cpiobr. Поскольку это управляемая с помощью меню утилита, никаких аргументов передавать не нужно. Для того, чтобы получить общее представление о том, как эта утили- та работает, давайте подумаем над тем, что необходимо сделать. Во-пер- вых, мы должны определить, какое действие должно быть выполнено. Полу- чив эту информацию, нам необходимо узнать, какое устройство должно использоваться. Что, если пользователь введет неверный выбор? Нам необ- ходимо ожидать в цикле до тех пор, пока не будет введено правильное значение. После получения этих двух порций информации, нам нужно определить, где искать или куда помещать файлы. После этого мы можем выполнять cpio. Для выполнения этого сценария нам нужно всего два цикла: по одному для каждой стадии ввода. В данном случае мы используем два цикла типа "вечный цикл while". Для выхода из циклов мы используем команду команд- ного процессора break, которая выводит нас из текущего цикла. Немного позже мы увидим наличие проблемы при таком подходе. Основной, самый внешний управляющий цикл начинается со строки 6 и заканчивается в последней строке программы - строке 87. Целью этого внешнего цикла является управление выполнением программы в целом, полу- чение опций меню от пользователя и окончательный выход, когда пользова- тель сообщает, что он закончил работу. Конечно, вы можете по-прежнему выйти из программы при помощи обычного символа прерывания, но само меню имеет ключ выхода (CR). Гораздо лучше представлять явный ключ, особенно для неопытных пользователей. Начиная со строки 11, мы устанавливаем экран для главного меню. Командой здесь является "c", что будет пояснено позже в этой книге. Она соответствует "очистке экрана" и может быть заменена стандартной коман- дой очистки системы UNIX, которую вы можете использовать в этом месте, если хотите. Строка 12 устанавливает в позиционные параметры выходные данные команды date системы UNIX. Такой синтаксис достаточно редко встреча- ется, но тем не менее очень полезен. Если бы мы не хотели делать это таким образом, мы бы должны были перехватить все выходные данные коман- ды date в одной переменной, затем разделить их на мелкие порции и по- местить каждую порцию в отдельную переменную. Это потребовало бы намно- го больше команд и переменных в программе. Используя наш синтаксис, мы заставляем первый позиционный параметр быть первым полем выходных дан- ных команды date, второй позиционный параметр быть вторым полем и так далее. Для получения любого указанного поля мы используем запись вида $n, где n есть номер позиционного параметра. Строки 13-25 - это один огромный оператор echo, который печатает главное меню. Выдача всего необходимого одним оператором echo предпоч- тительнее, поскольку это минимизирует накладные расходы, с которыми приходится сталкиваться при выполнении большого числа операторов. Такой путь быстрее. Если бы мы использовали оператор echo для каждой строки главного меню, то оно печаталось бы очень медленно и прерывисто. Коман- да UNIX cat также могла бы быть применена для этого случая, используя здесь документы (вставленный текст). В качестве примера этого может служить следующее: cat <<-EOF Main Menu Information EOF Однако главная проблема возникает, когда вы печатаете приглашение. Для того, чтобы курсор ожидал ввода в конце строки приглашения, необхо- димо выдать на терминал символ "\c", а cat не может сделать этого. Вы выводите на экран меню с помощью cat, и echo печатает приглашение, ко- торое направляется на другую сдвинутую строку полностью заполненного экрана. Постоянство и скорость - вот чего мы добиваемся. Обучение таким трюкам еще больше поможет вам при написании программ большого размера, которые используют множество меню и другие текстовые выводы на экран. Использование оператора echo в таком виде имеет некоторые не- достатки, но они совершенно тривиальные. Во-первых, тело оператора echo должно содержать все, что вы хотите вывести на экран, и это требует абсолютного позиционирования внутри оператора echo для получения симво- лов пробела в нужных местах. Обычно при таком позиционировании имеется сдвиг строк в тексте программы, поэтому визуально в том месте командно- го файла, где выводится меню, появляется этот сдвиг, но после меню строки снова идут ровно. Это может немного смущать при чтении текста программы. Другой несущественной деталью является то, что оператор echo не любит выводить символы табуляции. Если же вы вставили символ табуляции внутри кавычек оператора echo, он обычно выводится как пробел. Для то- го, чтобы заставить echo выводить символы табуляции, вы должны сказать это оператору echo на его собственном языке с помощью символов "\t" или \\t, если без кавычек. Поэтому меню в cpiobr заполнено символами пробе- ла. Это также позволяет легко сдвигать меню влево и вправо при помощи небольшого количества пробелов для соответствующего позиционирования на экране. Одним из спорных вопросов является место, где меню должны поя- виться на экране. Глобальное выравнивание по левому краю выглядит ужасно, но центрирование нарушается при выдаче на экран какого-либо сообщения (например, от cpio). В данном случае сделано выравнивание не по центру, а по левому краю. Неплохим компромиссом может быть отступ на три-пять позиций от левого края. Как и в большинстве случаев, когда де- ло идет об эстетике, вы можете с этим не согласиться. Вернемся к нашему меню. Для того, чтобы сделать меню на экране и более эстетичным, и информативным, на экран выводятся дата и время. (Заметьте, что главное меню очищается каждый раз перед его использова- нием.) Пример вида экрана приведен ниже. --------------------------------------- | Среда, май 28 13:18:49 | | Cpio - Сохранение/восстановление файлов | --------------------- | Копирование данных | Восстановление данных | Список файлов на носителе | Полный список файлов на носителе | <ВК> для выхода | | Нажмите b,r,f,l, или <ВК>: В левом верхнем углу расположен день недели, месяц, день месяца. Это поля 1, 2 и 3 команды date. В правом верхнем углу расположено теку- щее время. Это поле 4 команды date. Все эти данные приводятся для того, чтобы меню на экране смотрелось красиво, было равномерно заполнено и информативно. После того, как меню выдано на экран, строка 27 читает команду пользователя. Заметим, что один из ключей вызывает завершение програм- мы, если был нажат только возврат каретки. Каким образом мы проверяем это? Мы заключаем в кавычки входную переменную таким образом, что про- верка распознает нулевое значение (см. строки 28-30). Если был введен ноль, мы выходим из текущего цикла while. Тем самым мы попадаем в конец программы, которая после этого завершает выполнение. Если входное зна- чение не было равно нулю, мы продолжаем и выполняем в следующей команде проверку на наличие ошибки. В строке 32 проводится инициализация переменной ABORT путем сбрасывания ее. Это будет детально пояснено позже. А сейчас мы только скажем, что эта переменная существует, поскольку имеется конфликт между тем, как выполняется команда break, и структурой данной программы (т.е. полностью управляемой с помощью меню утилиты). В строках 34-65 разместился вложенный цикл while, который обраба- тывает подменю. Причина, по которой мы использовали циклы типа "вечный while" заключается в том, что они выполняются, пока не получат нужное входное значение. Как только получены правильные входные данные, мы вы- ходим из цикла. Это очень простой способ обработки меню. В строках 36-45 мы снова используем оператор echo для выдачи на экран полного подменю. Это меню запрашивает имя устройства, которое используется в командах копирования/восстановления. Строка 47 читает входные данные от пользователя в переменную MEDIA. Значение переменной MEDIA затем оценивается в операторе case. Обратите внимание, что шаблоны сравнения включают символы и в верхнем, и в нижнем регистре. Это облегчает жизнь пользователя и делает немного более логичным программирование, уменьшая число проверок на ошибки, ко- торое мы должны произвести. Также заметьте, что каждый образец заканчи- вается оператором break. Когда обнаружено допустимое входное значение, мы желаем продолжать выполнение после конца оператора while, что осу- ществляется оператором break. Переменная DEV теперь установлена как маршрут к выбранному устройству. Ключ "a" в строках 55-60 требует дальнейшей обработки. Пользова- тель запрашивается об имени устройства, которое он выбрал. Если пользо- ватель забыл имя или решил не использовать этот ключ, он может ввести возврат каретки, который распознается как нуль и приводит к выполнению оператора continue. Это вызывает выполнение следующей итерации текущего цикла, которая снова выводит подменю. Еще один возврат каретки после этого может использоваться для выхода из подменю и возврата в главное меню. В противном случае, если пользователь ввел ненулевое значение, выполняется оператор break, и цикл меню завершается, имея маршрут, ука- занный в переменной DEV. Если пользователь ввел неверное значение, печатается сообщение об ошибке и подменю выводится снова. Заметьте, что ввод только возврата каретки в подменю устанавливает переменную ABORT в "on". Почему это так? Теперь мы подошли к той части, где язык командного процессора неп- рименим для нашего случая. Сценарий выглядит примерно так. Мы находимся в подменю. Мы решаем, что не будем здесь производить выбор, поэтому мы хотим выйти из подменю и вернуться в главное меню (или в предыдущее ме- ню). Если мы выйдем из цикла while подменю, мы попадем во внешний цикл while и продолжим обработку запросами о каталоге-источнике и катало- ге-приемнике. Если мы попытаемся решить эту проблему путем использования опера- тора "break 2", мы выйдем из обоих циклов while (попадая в самый низ программы) и программа завершится, ничего не сделав для нас. Снова не то, что мы хотим. Что мы действительно хотим, так это выйти из текущего (внутреннего) цикла и продолжить следующую итерацию во внешнем цикле для получения главного меню. Нет никакой возможности сказать командному процессору об этом, поэтому мы создали переменную в качестве флага для имитации этого действия и назвали ее ABORT. Если мы устанавливаем пере- менную ABORT в состояние "да", то мы НЕ желаем продолжать работу с ко- мандой главного меню, а хотим прекратить ее и вернуться в главное меню. На самом деле это означает продолжить, поэтому в строках 67-69 проверя- ется именно это. Если флаг ABORT установлен, подменю принудительно за- вершается и оператор continue заставляет снова печатать главное меню вместо того, чтобы пытаться выполнить какую-то наполовину определенную операцию копирования. В строке 71 мы получаем для проверки команду главного меню и ин- формацию, необходимую для ее обработки. Четырьмя основными командами являются копирование, восстановление, выдача списка файлов и выдача списка файлов с полной информацией. Если введена какая-то другая коман- да, выдается сообщение об ошибке и главное меню снова выводится на эк- ран. Единственный способ выхода из главного меню - это нажать возврат каретки без какого либо-текста перед ним и строка 28 позволит выйти из цикла. Команды копирования и восстановления используют относительное име- нование. Сначала они требуют указать каталог, затем переходят в этот каталог. Оператор echo и "холостое" чтение переменной CMD просят поль- зователя вставить дискету (или смонтировать магнитную ленту или еще что-нибудь) и нажать возврат каретки, когда все готово. В случае копирования для поиска ВСЕХ файлов, размещенных в дереве файлов, начиная с текущего каталога, используется команда find. Опера- тор find выдает отсортированный список файлов, поэтому файлы на носите- ле с копией отсортированы. Затем отсортированный список файлов переда- ется по каналу команде cpio с опциями -ocBv. Это означает: "потоковый вывод, использовать символьные заголовки, блоки размером по 5K, с выда- чей сообщений". При этом печатаются имена файлов по мере того, как они копируются на носитель. В случае операции восстановления используются ключи -icBvdmu. Это значит "потоковый ввод, использовать символьные заголовки, блоки по 5К, с выдачей сообщений для печати имен файлов по мере их восстановления, создавать каталоги при необходимости, файлы сохраняют исходную дату мо- дификации, и все файлы безусловно копируются". Если должен быть выдан только список файлов, то ключами будут или -icBt для печати таблицы скопированных файлов (это соответствует записи команды cpio "ls"), или -icBtv для печати таблицы файлов с более под- робной информацией ("ls -l" в записи для cpio). В конце выполнения каждой команды главного меню выдается сообщение hit (Нажмите <ВК>) Это сделано по той причине, что когда печатается главное меню, оно очищает экран. Если бы вы хотели получить список файлов, как описано выше, и не завершить работу, то напечатался бы список, выполнение достигло бы внешнего оператора "done", внешний цикл снова стартовал бы и экран очистился бы перед новой выдачей на него главного меню. Уф, на- конец появился список, даже до того как Эвелин Вуд с высшим образовани- ем смогла прочитать это! Для того, чтобы задержать очистку экрана, мы ожидаем нажатие на клавишу. Что бы ни было введено, оно читается в пе- ременную и снова никогда не используется. Это просто холостая перемен- ная. Замечания по операции копирования Вы можете производить копирование файлов многими путями, но давай- те рассмотрим некоторые отличия между командами cpio и tar. Первона- чально командой копирования в UNIX была команда tar. Эта утилита созда- ния копии на магнитной ленте была предназначена для ведения архивов на магнитной ленте и выполнения самого копирования. Она работает, но имеет некоторые особенности. Во-первых, каждый файл, помещаемый на ленту (или какой-либо носитель, который вы используете), выравнивается на границу килобайта. Это означает, что если ваш файл состоит из одного байта, ко- манда tar выделяет минимум 1К вашему файлу, что может привести к значи- тельной растрате пространства, если у вас много небольших файлов и вы копируете их на магнитную ленту. Однако команда tar имеет также ряд неплохих аспектов. Например, вы можете сказать ей, какой множитель блокировки вы используете и насколько велик образ копии, так что вы можете разбить большие копируемые потоки данных на много мелких частей (например k=360 для гибких дисков низкой плотности в системе XENIX). Одним из странных аспектов команды tar является то, что копия является одним длинным и непрерывным потоком, а при восстановлении используется уникальный фор- мат для каждого носителя. Например, вы должны, скажем, скопировать 10M данных. Вам лучше иметь достаточно отформатированных гибких дисков и приготовить их до того, как вы начнете копировать командой tar. Когда дискета заполнится, вы должны прервать выполнение команды и затем снова продолжить. Пример такой команды мог бы выглядеть так: cd $HOME tar cvefbk /dev/fd048ds9 18 360 . Здесь указано, что требуется скопировать ВСЕ файлы (рекурсивно об- ходя дерево сверху вниз) из текущего каталога (.) в файл на указанном устройстве, со множителем блокировки 18 K и размером образа копии 360 Кбайт. Одним из интересных аспектов здесь является то, что когда коман- да tar рекурсивно проходит вниз по дереву, она получает имена файлов в порядке расположения описатель файла, что обычно НЕ совпадает с отсор- тированным порядком. Вы НЕ МОЖЕТЕ получить отсортированный список фай- лов для копирования командой tar, если только не сделаете еще одну точ- ную копию всех данных, которые вы хотите скопировать и не разместите описатель файла в отсортированном порядке. Как это сделать? Вот так: cd $HOME find . -print | sort | cpio -pdv /bkpsort При этом получится новая копия всех ваших данных и имена файлов разместятся в отсортированном порядке. Если после этого вы перейдете в каталог /bkpsort и выполните команду tar, файлы будут перенесены на носитель в отсортированном порядке. Предположим, что для выполнения копирования требуется 15 дискет. При восстановлении этого полного набора вы должны вводить приведенную ниже команду 15 раз, поскольку на каждом из гибких дисков располагается уникальный образ копии. tar xvf /dev/fd048ds9 Такие повторные вводы команды раздражают, но они могут облегчить жизнь, что мы вскоре и увидим. Команда cpio является следующим поколением команд копирования. Ее общие функции подобны функциям команды tar, но имеется несколько важных отличий. Во-первых, вы должны сгенерировать список файлов для cpio, что означает использование команды find для порождения списка. Поскольку мы можем конвейером пропустить список, полученный от команды find, через команду sort, нам нет необходимости делать еще одну копию всех наших файлов для получения отсортированного списка. Далее, команда cpio не выполняет выравнивание границу килобайта. Она пакует все данные непрерывно и имеет магическое число в заголовке для указания начала каждого нового файла. В команде cpio также нет ука- зания размера образа на носителе. Как она это узнает? Драйвер уст- ройства должен определить размер и послать соответствующий сигнал об- ратно команде cpio, которая после этого приостанавливается и предлагает вставить следующую дискету. Это все прекрасно до тех пор, пока вы не попадаете в систему, в которой драйверы ужасны, как в системе XENIX. Драйверы XENIX не распознают, когда нужно остановиться и продолжают вы- полнять работу и после того, как достигнут конец гибкого диска. Прог- рамма cpio должна была бы выполняться одинаково на всех системах, но она не работает корректно на машинах с системой XENIX. Одно существенное различие между командами cpio и tar заключается в получающемся образе копии. Поскольку cpio не различает границ между различными носителями (дискетами), файлы получаются разорванными между двумя гибкими дисками. Это значит, что когда вы пытаетесь копировать с этих 15 дискет, то они являются ОДНИМ непрерывным потоком входных дан- ных, точно так, как и последовательный поток выходных данных при созда- нии этой копии. Что произойдет, если дискета номер 2 повредится? ВСЕ ваши файлы после второй дискеты стали бесполезны. Вы просто потеряли весь ваш образ копии. Поскольку tar копирует в виде отдельных образов, когда дискета номер 2 потеряется, вы все равно можете копировать с дискет 3-15 без проблем. Еще один прекрасный аспект команды cpio заключается в том, что она может работать как в формате файловой системы, так и в потоковом форма- те. Формат файловой системы (опция -p) обращается к блочным уст- ройствам, таким как жесткий диск, а потоковый формат обращается к нест- руктурированным устройствам (опции -i и -o), таким как магнитная лента или гибкий диск с форматом низкого уровня. Cpio - это прекрасная утили- та для использования ее при копировании файловых деревьев системы на жестком диске. Как же управляется с этим система 4.2 BSD? В течение многих лет применялась команда tar для пересылки туда и обратно, как описано на страницах руководства по tar(1). Не самый элегантный подход, но рабо- тоспособный. Сейчас они имеют ключ -r (для рекурсивного обхода дерева сверху вниз) для обычной команды cp. Я же по-прежнему считаю, что ко- манда cpio лучше. 3.4. Средства проверки операций копирования 3.4.1. dsum - контрольные суммы двух катологов ------------------------------------------------------------- Имя: dsum _____________________________________________________________ dsum Контрольная сумма двух каталогов НАЗНАЧЕНИЕ Выдает на экран выходные данные команды sum системы UNIX для двух копий файлов из двух разных каталогов в одной строке. Это позволяет быстро визуально оценить, одинаково ли содержание файлов и может быть использовано для проверки копии. ФОРМАТ ВЫЗОВА dsum [-c|-o] control_dir backup_dir Пример вызова dsum $HOME/bin /mnt Просматривает, были ли какие-либо файлы изменены при копировании из моего регистрационного каталога на гибкий диск, смонтированный в ка- талоге /mnt. Командный файл dsum 1 : 2 # @(#) dsum v1.0 Dual directory sum Author: Russ Sage 4 if [ $# -lt 2 -o $# -gt 3 ] 5 then echo "dsum: invalid argument count" >&2 6 echo "usage: dsum [-c|-o] control_dir backup_dir" >&2 7 echo " -c = C source files, -o = object files" >&2 8 exit 1 9 fi 11 case $# in 12 2) FLIST=*;; 13 3) case $1 in 14 -c) FLIST=*.c;; 15 -o) FLIST=*.o;; 16 *) echo "dsum: invalid argument $1" >&2 17 echo "usage: dsum [-c|-o] control_dir bacup_dir" >&2 18 exit 1;; 19 esac 20 shift;; 21 esac 23 for FILE in $1/$FLIST 24 do 25 BASEF=`basename $FILE` 26 if [ `expr $BASEF : '.*'` -lt 7 ] 27 then echo "`$BASEF: \t'`sum $FILE | cut -d' ' -f1`\t\c" 28 else echo "$BASEF:\t`sum $FILE | cut -d' ' -f1`\t\c" 29 fi 30 sum $2/$BASEF | cut -d' ' -f1 31 done Переменные среды выполнения BASEF Содержит базовое имя файла из полного маршрутного имени FILE Содержит имя каждого проверяемого файла FLIST Содержит указание на тип проверяемых файлов Описание Зачем нам нужен dsum? В среде разработки программ всегда имеется масса файлов. Эти файлы содержат все: исходный код, перемещаемые модули, объектный код, данные, тексты. Другим аспектом среды разработки программ является то, что эти файлы обычно рассыпаны по многим различным машинам (или группам машин, может быть и такой случай). В этом случае всегда кажется, что имеется очень много перемещений файлов: эти файлы передаются из одной системы на другую, некоторые модифицируются, пересылаются обратно и так далее. Похоже на то, как в армии роют ямы: вы делаете это, потому что вам при- казано. Когда вы перемещаете много файлов, то какой путь является лучшим для того, чтобы гарантировать себе (или кому-либо еще), что выполненная вами копия является ТОЧНО такой, как и оригинал? Если вы внесли ошибку в первоначальную копию, затем распространили эту ошибку на многие копии или даже записали вместо оригинала модифицированную копию, то вы можете никогда не вернуться в первоначальное состояние. Одним из способов слежения за копиями является использование ко- манды sum. Эта команда читает данные и выводит число, являющееся разно- видностью контрольной суммы. Другими утилитами UNIX, которые делают что-то подобное, являются cmp для сравнения объектных файлов и diff для обнаружения различий в текстовых файлах. Автор привык думать, что sum будет сообщать об отличии даже в од- ном бите (своего рода циклическая избыточная проверка), но это оказа- лось совсем не так. Недавно имелся 35 Кбайтный файл, содержащий в виде длинного формата список файлов, которые должны были быть скопированы. В действительности, там были два файла, один из которых был отсортирован, а другой нет. Они были одного размера, и sum выдала одно и то же число для обоих файлов. Когда же cmp сравнила эти два файла, оказалось, что 39-е байты отличаются. Как мы можем объяснить тот факт, что sum рассматривала эти два файла как совершенно одинаковые? Возможно, sum свернула эти два файла таким образом, что контрольная сумма оказалась одинакова, даже хотя один из файлов был отсортирован, а другой нет. Это значит, что sum на самом деле не выполняет контрольную провер- ку каждого бита. Только проверка алгоритма работы программы в исходном модуле позволит убедиться в этом. Конечно, в большинстве случаев, если файл отличается от оригинала, то это не является простой перестановкой данных, так что sum все-таки полезна. Что