Данное руководство не предполагает наличие у читателя познаний в области программирования на языке сценариев, однако, быстро восполняет этот недостаток . . . постепенно, шаг за шагом раскрывая мудрость и красоту Unix™. Это руководство может рассматриваться как учебник, предназначенный для самостоятельного изучения или как справочник по программированию на shell. Руководство снабжено серией хорошо прокомментированных примеров, поскольку лучший путь к изучению языка сценариев -- это написание сценариев.
Кроме того, эта книга может служить в качестве учебного пособия по основам програмирования вообще.
Последнюю версию документа, в виде .bz2 архива, содержащем исходные тексты в формате SGML, HTML и PDF, вы найдете ниже в прикрепленных файлах.
Посвящается Аните -- источнику очарования
| Прикрепленный файл | Размер |
|---|---|
| abs-guide-2.5-flat.tar.gz | 415.56 кб |
| abs-guide-2.5-sgml.tar.gz | 426.64 кб |
| Advanced-Bash-Scripting-Guide.pdf | 12.42 Мб |
Shell — это командная оболочка. Но это не просто промежуточное звено между пользователем и операционой системой, это еще и мощный язык программирования. Программы на языке shell называют сценариями, или скриптами. Фактически, из скриптов доступен полный набор команд, утилит и программ Unix. Если этого недостаточно, то к вашим услугам внутренние команды shell — условные операторы, операторы циклов и пр., которые увеличивают мощь и гибкость сценариев. Shell-скрипты исключительно хороши при программировании задач администрирования системы и др., которые не требуют для своего создания полновесных языков программирования.
Знание языка командной оболочки является залогом успешного решения задач администрирования системы. Даже если вы не предполагаете заниматься написанием своих сценариев. Во время загрузки Linux выполняется целый ряд сценариев из /etc/rc.d, которые настраивают конфигурацию операционной системы и запускают различные сервисы, поэтому очень важно четко понимать эти скрипты и иметь достаточно знаний, чтобы вносить в них какие либо изменения.
Язык сценариев легок в изучении, в нем не так много специфических операторов и конструкций. [1] Синтаксис языка достаточно прост и прямолинеен, он очень напоминает команды, которые приходится вводить в командной строке. Короткие скрипты практически не нуждаются в отладке, и даже отладка больших скриптов отнимает весьма незначительное время.
Shell-скрипты очень хорошо подходят для быстрого создания прототипов сложных приложений, даже не смотря на ограниченный набор языковых конструкций и определенную "медлительность". Такая метода позволяет детально проработать структуру будущего приложения, обнаружить возможные "ловушки" и лишь затем приступить к кодированию на C, C++, Java, или Perl.
Скрипты возвращают нас к классической философии Unix — "разделяй и влавствуй" т.е. разделение сложного проекта на ряд простых подзадач. Многие считают такой подход наилучшим или, по меньшей мере, наиболее эстетичным способом решения возникающих проблем, нежели использование нового поколения языков — "все-в-одном", таких как Perl.
Для каких задач неприменимы скрипты
для ресурсоемких задач, особенно когда важна скорость исполнения (поиск, сортировка и т.п.)
для задач, связанных с выполнением математических вычислений, особенно это касается вычислений с плавающей запятой, вычислений с повышенной точностью, комплексных чисел (для таких задач лучше использовать C++ или FORTRAN)
для кросс-платформенного программирования (для этого лучше подходит язык C)
для сложных приложений, когда структурирование является жизненной необходимостью (контроль за типами переменных, прототипами функций и т.п.)
для целевых задач, от которых может зависеть успех предприятия.
когда во главу угла поставлена безопасность системы, когда необходимо обеспечить целостность системы и защитить ее от вторжения, взлома и вандализма.
для проектов, содержащих компоненты, очень тесно взаимодействующие между собой.
для задач, выполняющих огромный объем работ с файлами
для задач, работающих с многомерными массивами
когда необходимо работать со структурами данных, такими как связанные списки или деревья
когда необходимо предоставить графический интерфейс с пользователем (GUI)
когда необходим прямой доступ к аппаратуре компьютера
когда необходимо выполнять обмен через порты ввода-вывода или сокеты
когда необходимо использовать внешние библиотеки
для проприетарных, "закрытых" программ (скрипты представляют из себя исходные тексты программ, доступные для всеобщего обозрения)
Если выполняется хотя бы одно из вышеперечисленных условий, то вам лучше обратиться к более мощным скриптовым языкам программирования, например Perl, Tcl, Python, Ruby или к высокоуровневым компилирующим языкам — C, C++ или Java. Но даже в этом случае, создание прототипа приложения на языке shell может существенно облегчить разработку.
Название BASH — это аббревиатура от "Bourne-Again Shell" и игра слов от, ставшего уже классикой, "Bourne Shell" Стефена Бурна (Stephen Bourne). В последние годы BASH достиг такой популярности, что стал стандартной командной оболочкой de facto для многих разновидностей Unix. Большинство принципов программирования на BASH одинаково хорошо применимы и в других командных оболочках, таких как Korn Shell (ksh), от которой Bash позаимствовал некоторые особенности, [2] и C Shell и его производных. (Примечательно, что C Shell не рекомендуется к использованию из-за отдельных проблем, отмеченных Томом Кристиансеном (Tom Christiansen) в октябре 1993 года на Usenet post
Далее, в тексте документа вы найдете большое количество примеров скриптов, иллюстрирующих возможности shell. Все примеры — работающие. Они были протестированы, причем некоторые из них могут пригодиться в повседневной работе. Уважаемый читатель можеть "поиграть" с рабочим кодом скриптов, сохраняя их в файлы, с именами scriptname.sh. [3] Не забудьте выдать этим файлам право на исполнение (chmod u+rx scriptname), после чего сценарии можно будет запустить на исполнение и проверить результат их работы. Вам следует помнить, что описание некоторых примеров следует после исходного кода этого примера, поэтому, прежде чем запустить сценарий у себя — ознакомьтесь с его описанием.
Скрипты были написаны автором книги, если не оговаривается иное.
[1] Их так же называют встроенными конструкциями языка командной оболочки shell.
[2] Многие особенности ksh88 и даже ksh93 перекочевали в Bash.
[3] В соответствии с соглашениями, имена файлов с shell-скриптами, такими как Bourne shell и совместимыми, имеют расширение .sh. Все стартовые скрипты, которые вы найдете в /etc/rc.d, следуют этому соглашению.
В простейшем случае, скрипт — это ни что иное, как простой список команд системы, записанный в файл. Создание скриптов поможет сохранить ваше время и силы, которые тратятся на ввод последовательности команд всякий раз, когда необходимо их выполнить.
Пример 2-1. cleanup: Сценарий очистки лог-файлов в /var/log
Здесь нет ничего необычного, это простая последовательность команд, которая может быть набрана в командной строке с консоли или в xterm. Преимущество размещения последовательности команд в скрипте состоит в том, что вам не придется всякий раз набирать эту последовательность вручную. Кроме того, скрипты легко могут быть модифицированы или обобщены для разных применений.
Пример 2-2. cleanup: Расширенная версия предыдущего сценария.
Если вы не желаете полностью вычищать системные логи, то выше представлена улучшенная версия предыдущего сценария. Здесь сохраняются последние несколько строк (по-умолчанию — 50).
Если файл сценария начинается с последовательности #!, которая в мире Unix называется sha-bang, то это указывает системе какой интерпретатор следует использовать для исполнения сценария. Это двухбайтовая последовательность, или [4] — специальный маркер, определяющий тип сценария, в данном случае — сценарий командной оболочки (см. man magic). Более точно, sha-bang определяет интерпретатор, который вызывается для исполнения сценария, это может быть командная оболочка (shell), иной интерпретатор или утилита. [5]
Каждая, из приведенных выше сигнатур, приводит к вызову различных интерпретаторов, будь то /bin/sh — командный интерпретатор по-умолчанию (bash для Linux-систем), либо иной. [6] При переносе сценариев с сигнатурой #!/bin/sh на другие Unix системы, где в качестве командного интерпретатора задан другой shell, вы можете лишиться некоторых особенностей, присущих bash. Поэтому такие сценарии должны быть POSIX совместимыми. [7].
Обратите внимание на то, что сигнатура должна указывать правильный путь к интерпретатору, в противном случае вы получите сообщение об ошибке — как правило это "Command not found".
Сигнатура #! может быть опущена, если вы не используете специфичных команд. Во втором примере (см. выше) использование сигнатуры #! обязательно, поскольку сценарий использует специфичную конструкцию присваивания значения переменной lines=50. Еще раз замечу, что сигнатура #!/bin/sh вызывает командный интерпретатор по-умолчанию — /bin/bash в Linux-системах.
![]() |
В данном руководстве приветствуется модульный подход к построению сценариев. Записывайте, собирайте свою коллекцию участков кода, который может вам встретиться. В конечном итоге вы соберете свою "библиотеку" подпрограмм, которые затем сможете использовать при написании своих сценариев. Например, следующий отрывок сценария проверяет количество аргументов в командной строке:
|
[4] Некоторые разновидности Unix (основанные на 4.2BSD) требуют, чтобы эта последовательность состояла из 4-х байт, за счет добавления пробела после ! — #! /bin/sh.
[5] В shell-скриптах последовательность #! должна стоять самой первой и задает интерпретатор (sh или bash). Интерпретатор, в свою очередь, воспринимает эту строку как комментарий, поскольку она начинается с символа #.
[6] Эта особенность позволяет использовать различные хитрости.
[7] Portable Operating System Interface, попытка стандартизации UNIX-подобных операционных систем.
Запустить сценарий можно командой sh scriptname [8] или bash scriptname. (Не рекомендуется запуск сценария командой sh <scriptname, поскольку это запрещает использование устройства стандартного ввода stdin в скрипте). Более удобный вариант — сделать файл скрипта исполняемым, командой chmod.
chmod 555 scriptname (выдача прав на чтение/исполнение любому пользователю в системе) [9]
chmod +rx scriptname (выдача прав на чтение/исполнение любому пользователю в системе)
chmod u+rx scriptname (выдача прав на чтение/исполнение только "владельцу" скрипта)
После того, как вы сделаете файл сценария исполняемым, вы можете запустить его примерно такой командой ./scriptname. [10] Если, при этом, текст сценария начинается с корректной сигнатуры ("sha-bang"), то для его исполнения будет вызван соответствующий интерпретатор.
И наконец, завершив отладку сценария, вы можете поместить его в каталог /usr/local/bin (естественно, что для этого вы должны обладать правами root), чтобы сделать его доступным для себя и других пользователей системы. После этого сценарий можно вызвать, просто напечатав название файла в командной строке и нажав клавишу [ENTER].
[8] Внимание: вызов Bash-скрипта с помощью команды sh scriptname отключает специфичные для Bash расширения, что может привести к появлению ошибки и аварийному завершению работы сценария.
[9] Сценарий должен иметь как право на исполнение, так и право на чтение, поскольку shell должен иметь возможность прочитать скрипт.
[10] Почему бы не запустить сценарий просто набрав название файла scriptname, если сценарий находится в текущем каталоге? Дело в том, что из соображений безопасности, путь к текущему каталогу "." не включен в переменную окружения $PATH. Поэтому необходимо явно указывать путь к текущему каталогу, в котором находится сценарий, т.е. ./scriptname.
Системные администраторы часто создают скрипты для автоматизации своего труда. Подумайте, для выполнения каких задач могут быть написаны сценарии.
Напишите сценарий, который выводит дату, время, список зарегистрировавшихся пользователей, и uptime системы и сохраняет эту информацию в системном журнале.
Служебные символы, используемые в текстах сценариев.
Комментарии. Строки, начинающиеся с символа # (за исключением комбинации #!) — являются комментариями.
Комментарии могут располагаться и в конце строки с исполняемым кодом.
Комментариям могут предшествовать пробелы (пробел, табуляция).
![]() |
Исполняемые команды не могут следовать за комментарием в той же самой строке. Пока что еще не существует способа отделения комментария от "исполняемого кода", следующего за комментарием в той же строке. |
![]() |
Само собой разумеется, экранированный символ # в операторе echo не воспринимается как начало комментария. Более того, он может использоваться в операциях подстановки параметров и в константных числовых выражениях.
|
В операциях поиска по шаблону символ # так же не воспринимается как начало комментария.
Разделитель команд. [Точка-с-запятой] Позволяет записывать две и более команд в одной строке.
Следует отметить, что символ ";" иногда так же как и # необходимо экранировать.
Ограничитель в операторе выбора case . [Двойная-точка-с-запятой]
команда "точка". Эквивалент команды source (см. Пример 11-19). Это встроенная команда bash.
"точка" может являться частью имени файла . Если имя файла начинается с точки, то это "скрытый" файл, т.е. команда ls при обычных условиях его не отображает.
Если подразумевается имя каталога, то одна точка означает текущий каталог и две точки — каталог уровнем выше, или родительский каталог.
Символ точка довольно часто используется для обозначения каталога назначения в операциях копирования/перемещения файлов.
Символ "точка" в операциях поиска. При выполнении поиска по шаблону , в регулярных выражениях, символ "точка" обозначает одиночный символ.
Двойные кавычки . В строке "STRING", ограниченной двойными кавычками не выполняется интерпретация большинства служебных символов, которые могут находиться в строке. см. Глава 5.
Одинарные кавычки . [Одинарные кавычки] 'STRING' экранирует все служебные символы в строке STRING. Это более строгая форма экранирования. Смотрите так же Глава 5.
Запятая . Оператор запятая используется для вычисления серии арифметических выражений. Вычисляются все выражения, но возвращается результат последнего выражения.
escape. [обратный слэш] Комбинация \X "экранирует" символ X. Аналогичный эффект имеет комбинация с "одинарными кавычками", т.е. 'X'. Символ \ может использоваться для экранирования кавычек " и '.
Более детальному рассмотрению темы экранирования посвящена Глава 5.
Разделитель, используемый в указании пути к каталогам и файлам. [слэш] Отделяет элементы пути к каталогам и файлам (например /home/bozo/projects/Makefile).
В арифметических операциях — это оператор деления.
Подстановка команд. [обратные кавычки] Обратные кавычки могут использоваться для записи в переменную команды `command`.
пустая команда. [двоеточие] Это эквивалент операции "NOP" (no op, нет операции). Может рассматриваться как синоним встроенной команды true. Команда ":" так же является встроенной командой Bash, которая всегда возвращает "true" (0).
Бесконечный цикл:
Символ-заполнитель в условном операторе if/then:
Как символ-заполнитель в операциях, которые предполагают наличие двух операндов, см. Пример 8-2 и параметры по-умолчанию.
Как символ-заполнитель для оператора вложенного документа. См. Пример 17-10.
В операциях с подстановкой параметров (см. Пример 9-13).
В операциях замены подстроки с подстановкой значений переменных.
В комбинации с оператором > (оператор перенаправления вывода), усекает длину файла до нуля. Если указан несуществующий файл — то он создается.
В комбинации с оператором >> — если задано имя существующего файла, то эта комбинация на него никак не влияет (: >> target_file). Если задано имя несуществующего файла, то он создается.
![]() |
Вышеизложенное применимо только к обычным файлам и неприменимо к конвейерам, символическим ссылкам и другим специальным файлам. |
Символ : может использоваться для создания комментариев, хотя и не рекомендуется. Если строка комментария начинается с символа #, то такая строка не проверяется интерпретатором на наличие ошибок. Однако в случае оператора : это не так.
Символ ":" может использоваться как разделитель полей в /etc/passwd и переменной $PATH.
инверсия (или логическое отрицание) используемое в условных операторах. Оператор ! инвертирует код завершения команды, к которой он применен. (см. Пример 6-2). Так же используется для логического отрицания в операциях сравнения, например, операция сравнения "равно" ( = ), при использовании оператора отрицания, преобразуется в операцию сравнения — "не равно" ( != ). Символ ! является зарезервированным ключевым словом BASH.
В некоторых случаях символ ! используется для косвенного обращения к переменным.
Кроме того, из командной строки оператор ! запускает механизм историй Bash (см. Приложение H). Примечательно, что этот механизм недоступен из сценариев (т.е. исключительно из командной строки).
символ-шаблон. [звездочка] Символ * служит "шаблоном" для подстановки в имена файлов. Одиночный символ * означает любое имя файла в заданном каталоге.
В регулярных выражениях токен * представляет любое количество (в том числе и 0) символов.
арифметический оператор. В арифметических выражениях символ * обозначает операцию умножения.
Двойная звездочка (два символа звездочки, следующих подряд друг за другом — **), обозначает операцию возведения в степень.
Оператор проверки условия. В некоторых выражениях символ ? служит для проверки выполнения условия.
В конструкциях с двойными скобками, символ ? подобен трехместному оператору языка C. См. Пример 9-29.
В выражениях с подстановкой параметра, символ ? проверяет — установлена ли переменная.
сивол-шаблон. Символ ? обозначает одиночный символ при подстановке в имена файлов. В регулярных выражениях служит для обозначения одиночного символа.
Символ $, предшествующий имени переменной, указывает на то, что будет получено значение переменной.
end-of-line (конец строки). В регулярных выражениях, символ "$" обозначает конец строки.
код завершения. Переменная $? хранит код завершения последней выполненной команды, функции или сценария.
id процесса. Переменная $$ хранит id процесса сценария.
группа команд.
![]() |
Команды, заключенные в круглые скобки исполняются в дочернем процессе — subshell-е. Переменные, создаваемые в дочернем процессе не видны в "родительском" сценарии. Родительский процесс-сценарий, не может обращаться к переменным, создаваемым в дочернем процессе.
|
инициализация массивов.
Фигурные скобки.
Команда интерпретируется как список команд, разделенных точкой с запятой, с вариациями, представленными в фигурных скобках. [11] При интерпретации имен файлов (подстановка) используются параметры, заключенные в фигурные скобки.
![]() |
Использование неэкранированных или неокавыченных пробелов внутри фигурных скобок недопустимо. echo {file1,file2}\ :{\ A," B",' C'} file1 : A file1 : B file1 : C file2 : A file2 : B file2 : C |
Блок кода. [фигурные скобки] Известен так же как "вложенный блок", эта конструкция, фактически, создает анонимную функцию. Однако, в отличии от обычных функций, переменные, создаваемые во вложенных блоках кода, доступны объемлющему сценарию.
Код, заключенный в фигурные скобки, может выполнять перенаправление ввода-вывода.
Пример 3-1. Вложенные блоки и перенаправление ввода-вывода
Пример 3-2. Сохранение результата исполнения вложенного блока в файл
pathname — полное имя файла (т.е. путь к файлу и его имя). Чаще всего используется совместно с командой find.
![]() |
Обратите внимание на то, что символ ";", которым завершается ключ -exec команды find, экранируется обратным слэшем. Это необходимо, чтобы предотвратить его интерпретацию. |
test.
Проверка истинности выражения, заключенного в квадратные скобки [ ]. Примечательно, что [ является частью встроенной команды test (и ее синонимом), И не имеет никакого отношения к "внешней" утилите /usr/bin/test.
test.
Проверка истинности выражения, заключенного между [[ ]] (зарезервированное слово интерпретатора).
См. описание конструкции [[ ... ]] ниже.
элемент массива.
При работе с массивами в квадратных скобках указывается порядковый номер того элемента массива, к которому производится обращение.
диапазон символов.
В регулярных выражениях, в квадратных скобках задается диапазон искомых символов.
двойные круглые скобки.
Вычисляется целочисленное выражение, заключенное между двойными круглыми скобками (( )).
См. обсуждение, посвященное конструкции (( ... )) .
Конструкция scriptname >filename перенаправляет вывод scriptname в файл filename. Если файл filename уже существовал, то его прежнее содержимое будет утеряно.
Конструкция command &>filename перенаправляет вывод команды command, как со stdout, так и с stderr, в файл filename.
Конструкция command >&2 перенаправляет вывод со stdout на stderr.
Конструкция scriptname >>filename добавляет вывод scriptname к файлу filename. Если задано имя несуществующего файла, то он создается.
(command)>
<(command)
В операциях сравнения, символы "<" и ">" обозначают операции сравнения строк .
А так же — операции сравнения целых чисел. См. так же Пример 12-9.
перенаправление ввода на встроенный документ.
bash$ grep '\<the\>' textfile
конвейер. Передает вывод предыдущей команды на ввод следующей или на вход командного интерпретатора shell. Этот метод часто используется для связывания последовательности команд в единую цепочку.
|
Конвейеры (еще их называют каналами) — это классический способ взаимодействия процессов, с помощью которого stdout одного процесса перенаправляется на stdin другого. Обычно используется совместно с командами вывода, такими как cat или echo, от которых поток данных поступает в "фильтр" (команда, которая на входе получает данные, преобразует их и обрабатывает). cat $filename | grep $search_word |
В конвейер могут объединяться и сценарии на языке командной оболочки.
![]() |
Выход stdout каждого процесса в конвейере должен читаться на входе stdin последующим, в конвейере, процессом. Если этого не делается, то поток данных блокируется, в результате конвейер будет работать не так как ожидается.
Конвейер исполняется в дочернем процессе, а посему — не имеет доступа к переменным сценария.
Если одна из команд в конвейере завершается аварийно, то это приводит к аварийному завершению работы всего конвейера. |
принудительное перенаправление, даже если установлен ключ noclobber option.
логическая операция OR (логическое ИЛИ). В опрециях проверки условий, оператор || возвращает 0 (success), если один из операндов имеет значение true (ИСТИНА).
Выполнение задачи в фоне. Команда, за которой стоит &, будет исполняться в фоновом режиме.
В сценариях команды, и даже циклы могут запускаться в фоновом режиме.
Пример 3-3. Запуск цикла в фоновом режиме
![]() |
Команда, исполняемая в пределах сценария в фоне, может подвесить сценарий, ожидая нажатия клавиши. К счастью, это легко "лечится". |
Логическая операция AND (логическое И). В операциях проверки условий, оператор && возвращает 0 (success) тогда, и только тогда, когда оба операнда имеют значение true (ИСТИНА).
префикс ключа. С этого символа начинаются опциональные ключи команд.
COMMAND -[Option1][Option2][...]
ls -al
sort -dfu $filename
set — $variable
Обратите внимание, что в этом контексте "-" - не самостоятельный оператор Bash, а скорее опция, распознаваемая некоторыми утилитами Unix (такими как tar, cat и т.п.), которые выводят результаты своей работы в stdout.
В случае, когда ожидается имя файла, тогда "-" перенаправляет вывод на stdout (вспомните пример с tar cf) или принимает ввод с stdin.
Добавим символ "-" и получим более полезный результат. Это заставит командный интерпретатор ожидать ввода от пользователя.
Используя передачу stdout по конвейеру другим командам, можно выполнять довольно эффектные трюки, например вставка строк в начало файла.
С помощью команды diff — находить различия между одним файлом и частью другого:
grep Linux file1 | diff file2 -
И наконец пример использования служебного символа "-" с командой tar.
Пример 3-4. Резервное архивирование всех файлов, которые были изменены в течение последних суток
![]() |
Могут возникнуть конфликтные ситуации между опреатором перенаправления "-" и именами файлов, начинающимися с символа "-". Поэтому сценарий должен проверять имена файлов и предаварять их префиксом пути, например, ./-FILENAME, $PWD/-FILENAME или $PATHNAME/-FILENAME. Если значение переменной начинается с символа "-", то это тоже может быть причиной появления ошибок.
|
предыдущий рабочий каталог. [дефис] Команда cd - выполнит переход в предыдущий рабочий каталог, путь к которому хранится в переменной окружения $OLDPWD .
![]() |
Не путайте оператор "-" (предыдущего рабочего каталога) с оператором "-" (переназначения). Еще раз напомню, что интерпретация символа "-" зависит от контекста, в котором он употребляется. |
Минус. Знак минус в арифметических операциях.
Символ "равно". Оператор присваивания
В зависимости от контекста применения, символ "=" может выступать в качестве оператора сравнения.
Плюс. Оператор сложения в арифметических операциях.
В зависимости от контекста применения, символ + может выступать как оператор регулярного выражения.
Ключ (опция). Дополнительный флаг для ключей (опций) команд.
Отдельные внешние и встроенные команды используют символ "+" для разрешения некоторой опции, а символ "-" — для запрещения.
модуль. Модуль (остаток от деления) — арифметическая операция.
В зависимости от контекста применения, символ % может выступать в качестве шаблона.
домашний каталог. [тильда] Соответствует содержимому внутренней переменной $HOME. ~bozo — домашний каталог пользователя bozo, а команда ls ~bozo выведет содержимое его домашнего каталога. ~/ — это домашний каталог текущего пользователя, а команда ls ~/ выведет содержимое домашнего каталога текущего пользователя.
текущий рабочий каталог. Соответствует содержимому внутренней переменной $PWD.
предыдущий рабочий каталог. Соответствует содержимому внутренней переменной $OLDPWD.
начало-строки. В регулярных выражениях символ "^" задает начало строки текста.
изменяет поведение терминала или управляет выводом текста. Управляющий символ набирается с клавиатуры как комбинация CONTROL + <клавиша>.
Ctl-B
Курсор — на одну позицию назад (без стирания символа).
Ctl-C
Прерывание выполнения процесса.
Ctl-D
Выход из командного интерпретатора (log out) (аналог команды exit).
"EOF" (признак конца файла). Этот символ может выступать в качестве завершающего при вводе с stdin.
Ctl-G
"BEL" (звуковой сигнал — "звонок").
Ctl-H
Backspace ("забой") — удаление предыдущего символа.
Ctl-I
Горизонтальная табуляция.
Ctl-J
Перевод строки.
Ctl-K
Вертикальная табуляция.
Ctl-L
Перевод формата (очистка экрана (окна) терминала). Аналогична команде clear.
Ctl-M
Возврат каретки.
Ctl-Q
Resume (XON).
Эта комбинация "восстанавливает" работу stdin терминала (см. ниже).
Ctl-S
Suspend (XOFF).
Эта комбинация "замораживает" stdin терминала. (Для восстановления "работоспособности" — используйте комбинацию Ctl-Q)
Ctl-U
Стирание строки ввода.
Ctl-Z
Приостановка процесса.
используется как разделитель команд или переменных. В качестве пробельного символа могут выступать — собственно пробел (space), символ табуляции, символ перевода строки, символ возврата каретки или комбинация из вышеперечисленных символов. В некоторых случаях, таких как присваивание значений переменным, использование пробельных символов недопустимо.
Пустые строки никак не обрабатываются командным интерпретатором и могут свободно использоваться для визуального выделения отдельных блоков сценария.
$IFS — переменная специального назначения. Содержит символы-разделители полей, используемые некоторыми командами. По-умолчанию — пробельные символы.
[11] Интерпретатор, встретив фигурные скобки, раскрывает их и возвращает полученный список команд, которые затем и исполняет.
[12] Исключение: блок кода, являющийся частью конвейера, может быть запущен в дочернем процессе (subshell-е).
Переменные — это одна из основ любого языка программирования. Они учавствуют в арифметических операциях, в синтаксическом анализе строк и совершенно необходимы для абстрагирования каких либо величин с помощью символических имен. Физически переменные представляют собой ни что иное как участки памяти, в которые записана некоторая информация.
Когда интерпретатор встречает в тексте сценария имя переменной, то он вместо него подставляет значение этой переменной. Поэтому ссылки на переменные называются подстановкой переменных.
Необходимо всегда помнить о различиях между именем переменной и ее значением. Если variable1 — это имя переменной, то $variable1 — это ссылка на ее значение. "Чистые" имена переменных, без префикса $, могут использоваться только при объявлении переменный, при присваивании переменной некоторого значения, при удалении (сбросе), при экспорте и в особых случаях — когда переменная представляет собой название сигнала (см. Пример 29-5). Присваивание может производится с помощью символа = (например: var1=27), инструкцией read и в заголовке цикла (for var2 in 1 2 3).
Заключение ссылки на переменную в двойные кавычки (" ") никак не сказывается на работе механизма подстановки. Этот случай называется "частичные кавычки", иногда можно встретить название "нестрогие кавычки". Одиночные кавычки (' ') заставляют интерпретатор воспринимать ссылку на переменную как простой набор символов, потому в одинарных кавычках операции подстановки не производятся. Этот случай называется "полные", или "строгие" кавычки. Дополнительную информацию вы найдете в Глава 5.
Примечательно, что написание $variable фактически является упрощенной формой написания ${variable}. Более строгая форма записи ${variable} может с успехом использоваться в тех случаях, когда применение упрощенной формы записи порождает сообщения о синтаксических ошибках (см. Section 9.3, ниже).
Пример 4-1. Присваивание значений переменным и подстановка значений переменных
![]() |
Неинициализированная переменная хранит "пустое" значение - не ноль!. Использование неинициализированных переменных может приводить к ошибкам разного рода в процессе исполнения. Не смотря на это в арифметических операциях допускается использовать неинициализированные переменные.
|
оператор присваивания (пробельные символы до и после оператора — недопустимы)
![]() |
Не путайте с операторами сравнения = и -eq! Обратите внимание: символ = может использоваться как в качестве оператора присваивания, так и в качестве оператора сравнения, конкретная интерпретация зависит от контекста применения. |
Пример 4-2. Простое присваивание
Пример 4-3. Присваивание значений переменным простое и замаскированное
Присваивание переменных с использованием $(...) (более современный метод, по сравнению с обратными кавычками)
В отличие от большинства других языков программирования, Bash не производит разделения переменных по "типам". По сути, переменные Bash являются строковыми переменными, но, в зависимости от контекста, Bash допускает целочисленную арифметику с переменными. Определяющим фактором здесь служит содержимое переменных.
Пример 4-4. Целое число или строка?
Отсутствие типов — это и благословение и проклятие. С одной стороны — отсутствие типов делает сценарии более гибкими (чтобы повеситься — достаточно иметь веревку!) и облегчает чтение кода. С другой — является источником потенциальных ошибок и поощряет привычку к "неряшливому" программированию.
Бремя отслеживания типа той или иной переменной полностью лежит на плечах программиста. Bash не будет делать это за вас!
переменные, область видимости которых ограничена блоком кода или телом функции (см так же локальные переменные в функциях)
переменные, которые затрагивают командную оболочку и порядок взаимодействия с пользователем
![]() |
В более общем контексте, каждый процесс имеет некоторое "окружение" (среду исполнения), т.е. набор переменных, к которым процесс может обращаться за получением определенной информации. В этом смысле командная оболочка подобна любому другому процессу. Каждый раз, когда запускается командный интерпретатор, для него создаются переменные, соответствующие переменным окружения. Изменение переменных или добавление новых переменных окружения заставляет оболочку обновить свои переменные, и все дочерние процессы (и команды, исполняемые ею) наследуют это окружение. |
![]() |
Пространство, выделяемое под переменные окружения, ограничено. Создание слишком большого количества переменных окружения или одной переменной, которая занимает слишком большое пространство, может привести к возникновению определенных проблем.
(Спасибо S. C. за вышеприведенный пример и пояснения.) |
Если сценарий изменяет переменные окружения, то они должны "экспортироваться", т.е передаваться окружению, локальному по отношению к сценарию. Эта функция возложена на команду export.
![]() |
Сценарий может экспортировать переменные только дочернему процессу, т.е. командам и процессам запускаемым из данного сценария. Сценарий, запускаемый из командной строки не может экспортировать переменные "на верх" командной оболочке. Дочерний процесс не может экспортировать переменные родительскому процессу. |
---
аргументы, передаваемые скрипту из командной строки — $0, $1, $2, $3..., где $0 — это название файла сценария, $1 — это первый аргумент, $2 — второй, $3 — третий и так далее. [13] Аргументы, следующие за $9, должны заключаться в фигурные скобки, например: ${10}, ${11}, ${12}.
Специальные переменные $* и $@ содержат все позиционные параметры (аргументы командной строки).
Пример 4-5. Позиционные параметры
Скобочная нотация позиционных параметров дает довольно простой способ обращения к последнему аргументу, переданному в сценарий из командной строки. Такой способ подразумевает использование косвенной адресации.
В сценарии можно предусмотреть различные варианты развития событий, в зависимости от имени сценария. Для этого сценарий должен проанализировать аргумент $0 — имя файла сценария. Это могут быть и имена символических ссылок на файл сценария. См. Пример 12-2.
![]() |
Если сценарий ожидает передачи аргументов в командной строке, то при их отсутствии он получит "пустые" переменные, что может вызвать нежелательный побочный эффект. Один из способов борьбы с подобными ошибками — добавить дополнительный символ в обеих частях операции присваивания, где используются аргументы командной строки. |
---
Пример 4-6. wh, whois выяснение имени домена
---
Команда shift "сдвигает" позиционные параметры, в результате чего парметры "сдвигаются" на одну позицию влево.
$1 <--- $2, $2 <--- $3, $3 <--- $4, и т.д.
Прежний аргумент $1 теряется, но аргумент $0 (имя файла сценария) остается без изменений. Если вашему сценарию передается большое количество входных аргументов, то команда shift позволит вам получить доступ к аргументам, с порядковым номером больше 9, без использования {фигурных скобок}.
Пример 4-7. Использование команды shift
![]() |
Команда shift может применяться и к входным аргументам функций. См. Пример 33-11. |
[13] Аргумент $0 устанавливается вызывающим процессом. В соответствии с соглашениями, этот параметр содержит имя файла скрипта. См. страницы руководства для execv (man execv).
Кавычки, ограничивающие строки с обеих сторон, служат для предотвращения интерпретации специальных символов, которые могут находиться в строке. (Символ называется "специальным", если он несет дополнительную смысловую нагрузку, например символ шаблона — *.)
![]() |
Некоторые программы и утилиты могут вызываться с дополнительными параметрами, содержащими специальными символы, поэтому очень важно предотвратить интерпретацию передаваемых параметров командной оболочкой, позволяя сделать это вызываемой программой.
Примечательно, что "не окавыченный" вариант команды grep [Пп]ервая *.txt будет правильно исполняться в Bash, но не в tcsh. |
Вообще, желательно использовать двойные кавычки (" ") при обращении к переменным. Это предотвратит интерпретацию специальных символов, которые могут содержаться в именах переменных, за исключением $, ` (обратная кавычка) и \ (escape — обратный слэш). [14] То, что символ $ попал в разряд исключений, позволяет выполнять обращение к переменным внутри строк, ограниченных двойными кавычками ("$variable"), т.е. выполнять подстановку значений переменных (см. Пример 4-1, выше).
Двойные кавычки могут быть использованы для предотвращения разбиения строки на слова. [15] Заключение строки в кавычки приводит к тому, что она передается как один аргумент, даже если она содержит пробельные символы - разделители.
![]() |
Заключение в кавычки аргументов команды echo необходимо только в том случае, когда разбиение на отдельные слова сопряжено с определенными трудностями. |
Пример 5-1. Вывод "причудливых" переменных
Одиночные кавычки (' ') схожи по своему действию с двойными кавычками, только не допускают обращение к переменным, поскольку специальный символ "$" внутри одинарных кавычек воспринимается как обычный символ. Внутри одиночных кавычек, любой специальный символ, за исключением ', интерпретируется как простой символ. Одиночные кавычки ("строгие, или полные кавычки") следует рассматривать как более строгий вариант чем двойные кавычки ("нестрогие, или неполные кавычки").
![]() |
Поскольку внутри одиночных кавычек даже экранирующий (\) символ воспринимается как обычный символ, попытка вывести одиночную кавычку внутри строки, ограниченной одинарными кавычками, не даст желаемого результата.
|
Экранирование — это способ заключения в кавычки одиночного символа. Экранирующий (escape) символ (\) сообщает интерпретатору, что следующий за ним символ должен восприниматься как обычный символ.
![]() |
С отдельными командами и утилитами, такими как echo и sed, экранирующий символ может применяться для получения обратного эффекта - когда обычные символы при экранировании приобретают специальное значение. |
Специальное назначение некоторых экранированных символов
перевод строки (новая строка)
перевод каретки
табуляция
вертикальная табуляция
забой (backspace)
"звонок" (сигнал)
ASCII-символ с кодом 0xx в восьмеричном виде)
Пример 5-2. Экранированные символы
Еще один пример использования конструкции $' ' вы найдете в Пример 34-1.
кавычки
символ доллара (если за комбинацией символов \$ следует имя переменной, то она не будет разыменована)
обратный слэш
![]() |
Поведение символа \ сильно зависит от того экранирован ли он, ограничен ли кавычками или находится внутри конструкции подстановки команды или во вложенном документе.
Отдельные символы в строке, которая записывается в переменную, могут быть экранированы, исключение составляет сам экранирующий символ.
|
Экранирование пробелов предотвращает разбиение списка аргументов командной строки на отдельные аргументы.
Кроме того, escape-символ позволяет писать многострочные команды. Обычно, каждая команда занимает одну строку, но escape-символ позволяет экранировать символ перевода строки, в результате чего одна команда может занимать несколько строк.
![]() |
Если строка сценария заканчивается символом создания конвейера |, то необходимость в применении символа \, для экранирования перевода строки, отпадает. Тем не менее, считается хорошим тоном, всегда использовать символ "\" в конце промежуточных строк многострочных команд. |
[14] Символ "!", помещенный в двойные кавычки, порождает сообщение об ошибке, если команда вводится с командной строки. Вероятно это связано с тем, что этот символ интерпретируется как попытка обращения к истории команд. Однако внутри сценариев такой прием проблем не вызывает.
[15] "Разбиение на слова", в данном случае это означает разделение строки символов на некоторое число аргументов.
|
...эта часть Bourne shell покрыта мраком, тем не менее все пользуются ею. |
|
| Chet Ramey |
Команда exit может использоваться для завершения работы сценария, точно так же как и в программах на языке C. Кроме того, она может возвращать некоторое значение, которое может быть проанализировано вызывающим процессом.
Каждая команда возвращает код завершения (иногда код завершения называют возвращаемым значением ). В случае успеха команда должна возвращать 0, а в случае ошибки — ненулевое значение, которое, как правило, интерпретируется как код ошибки. Практически все команды и утилиты Unix возвращают 0 в случае успешного завершения, но имеются и исключения из правил.
Аналогичным образом ведут себя функции, расположенные внутри сценария, и сам сценарий, возвращая код завершения. Код, возвращаемый функцией или сценарием, определяется кодом возврата последней команды. Команде exit можно явно указать код возврата, в виде: exit nnn, где nnn — это код возврата (число в диапазоне 0 - 255).
![]() |
Когда работа сценария завершается командой exit без параметров, то код возврата сценария определяется кодом завершения последней исполненной команды (не считая саму команду exit).
Эквивалентный вариант — exit $? или можно вообще опустить команду exit.
|
Код возврата последней команды хранится в специальной переменной $?. После исполнения кода функции, переменная $? хранит код завершения последней команды, исполненной в функции. Таким способом в Bash передается "значение, возвращаемое" функцией. После завершения работы сценария, код возврата можно получить, обратившись из командной строки к переменной $?, т.е. это будет код возврата последней команды, исполненной в сценарии.
Пример 6-1. завершение / код завершения
Переменная $? особенно полезна, когда необходимо проверить результат исполнения команды (см. Пример 12-30 и Пример 12-16).
![]() |
Символ !, может выступать как логическое "НЕ" для инверсии кода возврата. Пример 6-2. Использование символа ! для логической инверсии кода возврата
|
![]() |
В отдельных случаях коды возврата должны иметь предопределенные значения и не должны задаваться пользователем. |
практически любой язык программирования включает в себя условные операторы, предназначенные для проверки условий, чтобы выбрать тот или иной путь развития событий в зависимости от этих условий. В Bash, для проверки условий, имеется команда test, различного вида скобочные операторы и условный оператор if/then.
Оператор if/then проверяет — является ли код завершения списка команд 0 (поскольку 0 означает "успех"), и если это так, то выполняет одну, или более, команд, следующие за словом then.
Существует специальная команда — [ (левая квадратная скобка). Она является синонимом команды test, и является встроенной командой (т.е. более эффективной, в смысле производительности). Эта команда воспринимает свои аргументы как выражение сравнения или как файловую проверку и возвращает код завершения в соответствии с результатами проверки (0 — истина, 1 — ложь).
Начиная с версии 2.02, Bash предоставляет в распоряжение программиста конструкцию [[ ... ]] расширенный вариант команды test, которая выполняет сравнение способом более знакомым программистам, пишущим на других языках программирования. Обратите внимание: [[ — это зарезервированное слово, а не команда.
Bash исполняет [[ $a -lt $b ]] как один элемент, который имеет код возврата.
Круглые скобки (( ... )) и предложение let ... так же возвращают код 0, если результатом арифметического выражения является ненулевое значение. Таким образом, арифметические выражения могут учавствовать в операциях сравнения.
Условный оператор if проверяет код завершения любой команды, а не только результат выражения, заключенного в квадратные скобки.
Оператор if/then допускает наличие вложенных проверок.
Это детальное описание конструкции "if-test" любезно предоставлено Stephane Chazelas.
Пример 7-1. Что есть "истина"?
Упражнение. Объясните результаты, полученные в Пример 7-1.
![]() |
Когда if и then располагаются в одной строке, то конструкция if должна завершаться точкой с запятой. И if, и then — это зарезервированные слова. Зарезервированные слова начинают инструкцию, которая должна быть завершена прежде, чем в той же строке появится новая инструкция.
|
elif — это краткая форма записи конструкции else if. Применяется для построения многоярусных инструкций if/then.
Конструкция if test condition-true является точным эквивалентом конструкции if [ condition-true ], где левая квадратная скобка [ выполняет те же действия, что и команда test. Закрывающая правая квадратная скобка ] не является абсолютно необходимой, однако, более новые версии Bash требуют ее наличие.
![]() |
Команда test — это встроенная команда Bash, которая выполняет проверки файлов и производит сравнение строк. Таким образом, в Bash-скриптах, команда test не вызывает внешнюю (/usr/bin/test) утилиту, которая является частью пакета sh-utils. Аналогично, [ не производит вызов утилиты /usr/bin/[, которая является символической ссылкой на /usr/bin/test.
|
Пример 7-2. Эквиваленты команды test — /usr/bin/test, [ ], и /usr/bin/[
Конструкция [[ ]] более универсальна, по сравнению с [ ]. Этот расширенный вариант команды test перекочевал в Bash из ksh88.
![]() |
Внутри этой конструкции не производится никакой дополнительной интерпретации имен файлов и не производится разбиение аргументов на отдельные слова, но допускается подстановка параметров и команд. |
![]() |
Конструкция [[ ... ]] более предпочтительна, нежели [ ... ], поскольку поможет избежать некоторых логических ошибок. Например, операторы &&, ||, < и > внутри [[ ]] вполне допустимы, в то время как внутри [ ] порождают сообщения об ошибках. |
![]() |
Строго говоря, после оператора if, ни команда test, ни квадратные скобки ( [ ] или [[ ]] ) не являются обязательными.
Точно так же, условие, находящееся внутри квадратных скобок может быть проверено без использования оператора if.
|
Внутри (( )) производится вычисление арифметического выражения. Если результатом вычислений является ноль, то возвращается 1, или "ложь". Ненулевой результат дает код возврата 0, или "истина". То есть полная противоположность инструкциям test и [ ], обсуждавшимся выше.
Пример 7-3. Арифметические выражения внутри (( ))
файл существует
обычный файл (не каталог и не файл устройства)
ненулевой размер файла
файл является каталогом
файл является блочным устройством (floppy, cdrom и т.п.)
файл является символьным устройством (клавиатура, модем, звуковая карта и т.п.)
файл является каналом
файл является символической ссылкой
файл является символической ссылкой
файл является сокетом
файл (дескриптор) связан с терминальным устройством
Этот ключ может использоваться для проверки — является ли файл стандартным устройством ввода stdin ([ -t 0 ]) или стандартным устройством вывода stdout ([ -t 1 ]).
файл доступен для чтения (пользователю, запустившему сценарий)
файл доступен для записи (пользователю, запустившему сценарий)
файл доступен для исполнения (пользователю, запустившему сценарий)
set-group-id (sgid) флаг для файла или каталога установлен
Если для каталога установлен флаг sgid, то файлы, создаваемые в таком каталоге, наследуют идентификатор группы каталога, который может не совпадать с идентификатором группы, к которой принадлежит пользователь, создавший файл. Это может быть полезно для каталогов, в которых хранятся файлы, общедоступные для группы пользователей.
set-user-id (suid) флаг для файла установлен
Установленный флаг suid приводит к изменению привилегий запущенного процесса на привилегии владельца исполняемого файла. Исполняемые файлы, владельцем которых является root, с установленным флагом set-user-id запускаются с привилегиями root, даже если их запускает обычный пользователь. [16] Это может оказаться полезным для некоторых программ (таких как pppd и cdrecord), которые осуществляют доступ к аппаратной части компьютера. В случае отсутствия флага suid, программы не смогут быть запущены рядовым пользователем, не обладающим привилегиями root.
флаг sticky bit (бит фиксации) установлен
Общеизвестно, что флаг "sticky bit" — это специальный тип прав доступа к файлам. Программы с установленным флагом "sticky bit" остаются в системном кэше после своего завершения, обеспечивая тем самым более быстрый запуск программы. [17] Если флаг установлен для каталога, то это приводит к ограничению прав на запись. Установленный флаг "sticky bit" отображается в виде символа t в поле прав доступа.
вы являетесь владельцем файла
вы принадлежите к той же группе, что и файл
файл был модифицирован с момента последнего чтения
файл f1 более новый, чем f2
файл f1 более старый, чем f2
файлы f1 и f2 являются "жесткими" ссылками на один и тот же файл
"НЕ" — логическое отрицание (инверсия) результатов всех вышеприведенных проверок (возвращается true если условие отсутствует).
Пример 7-4. Проверка "битых" ссылок
Пример 28-1, Пример 10-7, Пример 10-3, Пример 28-3 и Пример A-2 так же иллюстрируют операции проверки файлов.
[16] С флагом suid, на двоичных исполняемых файлах, надо быть очень осторожным, поскольку это может быть небезопасным. Установка флага suid на файлы-сценарии не имеет никакого эффекта.
[17] В современных Unix-системах, "sticky bit" больше не используется для файлов, только для каталогов.
равно
if [ "$a" -eq "$b" ]
не равно
if [ "$a" -ne "$b" ]
больше
if [ "$a" -gt "$b" ]
больше или равно
if [ "$a" -ge "$b" ]
меньше
if [ "$a" -lt "$b" ]
меньше или равно
if [ "$a" -le "$b" ]
меньше (внутри двойных круглых скобок )
(("$a" < "$b"))
меньше или равно (внутри двойных круглых скобок)
(("$a" <= "$b"))
больше (внутри двойных круглых скобок)
(("$a" > "$b"))
больше или равно (внутри двойных круглых скобок)
(("$a" >= "$b"))
равно
if [ "$a" = "$b" ]
равно
if [ "$a" == "$b" ]
Синоним оператора =.
не равно
if [ "$a" != "$b" ]
Этот оператор используется при поиске по шаблону внутри [[ ... ]].
меньше, в смысле величины ASCII-кодов
if [[ "$a" < "$b" ]]
if [ "$a" \< "$b" ]
Обратите внимание! Символ "<" необходимо экранировать внутри [ ].
больше, в смысле величины ASCII-кодов
if [[ "$a" > "$b" ]]
if [ "$a" \> "$b" ]
Обратите внимание! Символ ">" необходимо экранировать внутри [ ].
См. Пример 25-11 относительно применения этого оператора сравнения.
строка "пустая", т.е. имеет нулевую длину
строка не "пустая".
![]() |
Оператор -n требует, чтобы строка была заключена в кавычки внутри квадратных скобок. Как правило, проверка строк, не заключенных в кавычки, оператором ! -z, или просто указание строки без кавычек внутри квадратных скобок (см. Пример 7-6), проходит нормально, однако это небезопасная, с точки зрения отказоустойчивости, практика. Всегда заключайте проверяемую строку в кавычки. [18] |
Пример 7-5. Операции сравнения
Пример 7-6. Проверка — является ли строка пустой
Пример 7-7. zmost
построение сложных условий проверки
логическое И (and)
exp1 -a exp2 возвращает true, если оба выражения, и exp1, и exp2 истинны.
логическое ИЛИ (or)
exp1 -o exp2 возвращает true, если хотябы одно из выражений, exp1 или exp2 истинно.
Они похожи на операторы Bash && и ||, употребляемые в двойных квадратных скобках.
Чтобы увидеть эти операторы в действии, смотрите Пример 8-3 и Пример 25-16.
[18] Как указывает S.C., даже заключение строки в кавычки, при построении сложных условий проверки, может оказаться недостаточным. [ -n "$string" -o "$a" = "$b" ] в некоторых версиях Bash такая проверка может вызвать сообщение об ошибке, если строка $string пустая. Безопаснее, в смысле отказоустойчивости, было бы добавить какой-либо символ к, возможно пустой, строке: [ "x$string" != x -o "x$a" = "x$b" ] (символ "x" не учитывается).
Операторы проверки условий if/then могут быть вложенными друг в друга. Конечный результат будет таким же как если бы результаты всех проверок были объединены оператором &&.
См. Пример 34-4 — пример использования вложенных операторов if/then.
Для запуска X-сервера может быть использован файл xinitrc. Этот файл содержит некоторое число операторов if/then. Ниже приводится отрывок из этого файла.
Объясните действия условных операторов в вышеприведенном отрывке, затем просмотрите файл /etc/X11/xinit/xinitrc и проанализируйте его. Возможно вам придется обратиться к разделам, посвященным grep, sed и регулярным выражениям.
Инициализация переменной или изменение ее значения
Универсальный оператор присваивания, пригоден как для сравнения целых чисел, так и для сравнения строк.
![]() |
Пусть вас не смущает, что оператор присваивания ("="), по своему внешнему виду, совпадает с оператором сравнения (=).
|
сложение
вычитание
умножение
деление
возведение в степень
модуль (деление по модулю), возвращает остаток от деления
Этот оператор может применяться в алгоритмах генерации псевдослучайных чисел в заданном диапазоне (см. Пример 9-23 и Пример 9-26), для форматирования вывода на экран (см. Пример 25-15 и Пример A-7), и даже для генерации простых чисел (см. Пример A-18). На удивление часто операцию деления по модулю можно встретить в различных численных алгоритмах.
Пример 8-1. Наибольший общий делитель
"плюс-равно" (увеличивает значение переменной на заданное число)
let "var += 5" значение переменной var будет увеличено на 5.
"минус-равно" (уменьшение значения переменной на заданное число)
"умножить-равно" (умножить значение переменной на заданное число, результат записать в переменную)
let "var *= 4" значение переменной var будет увеличено в 4 раза.
"слэш-равно" (уменьшение значения переменной в заданное число раз)
"процент-равно" (найти остаток от деления значения переменной на заданное число, результат записать в переменную)
Арифметические операторы очень часто используются совместно с командами expr и let.
Пример 8-2. Арифметические операции
![]() |
Целые числа в Bash фактически являются длинными целыми (32-бит) со знаком, с диапазоном изменений от -2147483648 до 2147483647. Если в результате какой либо операции эти пределы будут превышены, то результат получится ошибочным.
Версия Bash 2.05b, поддерживает 64-ьитные целые числа. |
![]() |
Bash ничего не знает о существовании чисел с плавающей запятой. Такие числа, из-за наличия символа десятичной точки, он воспринимает как строки.
|
битовые операции. Битовые операции очень редко используются в сценариях командного интерпретатора. Их главное назначение, на мой взгляд, установка и проверка некоторых значений, читаемых из портов ввода-вывода и сокетов. "Битовые операции" гораздо более уместны в компилирующих языках программирования, таких как C и C++.
сдвигает на 1 бит влево (умножение на 2)
"сдвиг-влево-равно"
let "var <<= 2" значение переменной var сдвигается влево на 2 бита (умножается на 4)
сдвиг вправо на 1 бит (деление на 2)
"сдвиг-вправо-равно" (имеет смысл обратный <<=)
по-битовое И (AND)
"по-битовое И-равно"
по-битовое ИЛИ (OR)
"по-битовое ИЛИ-равно"
по-битовая инверсия
По-битовое отрицание
по-битовое ИСКЛЮЧАЮЩЕЕ ИЛИ (XOR)
"по-битовое ИСКЛЮЧАЮЩЕЕ-ИЛИ-равно"
логическое И (and)
![]() |
оператор &&, в зависимости от контекста, может так же использоваться в И-списках для построения составных команд. |
логическое ИЛИ (or)
![]() |
Bash производит проверку кода возврата КАЖДОГО из операндов в логических выражениях. |
Пример 8-3. Построение сложных условий, использующих && и ||
Операторы && и || могут использоваться и в арифметических вычислениях.
запятая
С помощью оператора запятая можно связать несколько арифметических в одну последовательность. При разборе таких последовательностей, командный интерпретатор вычисляет все выражения (которые могут иметь побочные эффекты) в последовательности и возвращает результат последнего.
Оператор запятая чаще всего находит применение в циклах for. См. Пример 10-12.
Интерпретатор командной оболочки воспринимает числа как десятичные, в противном случае числу должен предшествовать специальный префикс, либо число должно быть записано в особой нотации. Числа, начинающиеся с символа 0, считаются восьмеричными. если числу предшествует префикс 0x, то число считается шестнадцатиричным. Число, в записи которого присутствует символ #, расценивается как запись числа с указанием основы счисления в виде ОСНОВА#ЧИСЛО.
Пример 8-4. Различные представления числовых констант
Правильное использование переменных может придать сценариям дополнительную мощь и гибкость, а для этого необходимо изучить все тонкости и нюансы.
путь к исполняемому файлу Bash
это массив, состоящий из 6 элементов, и содержащий информацию о версии Bash. Очень похожа на переменную $BASH_VERSION, описываемую ниже.
версия Bash, установленного в системе
Проверка переменной $BASH_VERSION — неплохой метод проверки типа командной оболочки, под которой исполняется скрипт. Переменная $SHELL не всегда дает правильный ответ.
содержимое вершины стека каталогов (который управляется командами pushd и popd)
Эта переменная соответствует команде dirs, за исключением того, что dirs показывает полное содержимое всего стека каталогов.
заданный по-умолчанию редактор, вызываемый скриптом, обычно vi или emacs.
"эффективный" идентификационный номер пользователя (Effective User ID)
Идентификационный номер пользователя, права которого были получены, возможно с помощью команды su.
![]() |
Значение переменной $EUID необязательно должно совпадать с содержимым переменной $UID. |
имя текущей функции
Перечень шаблонных символов, которые будут проигнорированы при выполнении подстановки имен файлов (globbing) .
группы, к которым принадлежит текущий пользователь
Это список групп (массив) идентификационных номеров групп для текущего пользователя, как эо записано в /etc/passwd.
домашний каталог пользователя, как правило это /home/username (см. Пример 9-13)
Сетевое имя хоста устанавливается командой hostname во время исполнения инициализирующих сценариев на загрузке системы. Внутренняя переменная $HOSTNAME Bash получает свое значение посредством вызова функции gethostname(). См. так же Пример 9-13.
тип машины
Подобно $MACHTYPE, идентифицирует аппаратную архитектуру.
разделитель полей во вводимой строке (IFS — Internal Field Separator)
Эта переменная управляет порядком выделения полей (задает символы-разделители) при разборе строки символов.
По-умолчанию — пробельный символ (пробел, табуляция и перевод строки), но может быть изменен, например, для разбора строк, в которых отдельные поля разделены запятыми. Обратите внимание: при составлении содержимого переменной $*, Bash использует первый символ из $IFS для разделения аргументов. См. Пример 5-1.
(Спасибо S. C., за разъяснения и примеры.)
Чаще всего устанавливается в .bashrc или /etc/profile, эта переменная задает порядок сортировки символов, в операциях подстановки имен файлов и в поиске по шаблону. При неверной настройке переменной LC_COLLATE можно получить весьма неожиданные результаты.
![]() |
Начиная с версии 2.05, Bash, в операциях подстановки имен файлов, не делает различий между символами верхнего и нижнего регистров, в диапазонах символов в квадратных скобках. Например,, ls [A-M]* выведет как File1.txt, так и file1.txt. Возврат к общепринятому стандарту поведения шаблонов в квадратных скобках выполняется установкой переменной LC_COLLATE в значение C командой export LC_COLLATE=C в файле /etc/profile и/или ~/.bashrc. |
Эта внутренняя переменная определяет кодировку символов. Используется в операциях подстановки и поиске по шаблону.
Номер строки исполняемого сценария. Эта переменная имеет смысл только внутри исполняемого сценария и чаще всего применяется в отладочных целях.
аппаратная архитектура
Идентификатор аппаратной архитектуры.
прежний рабочий каталог ("OLD-Print-Working-Directory")
тип операционной системы
путь поиска, как правило включает в себя каталоги /usr/bin/, /usr/X11R6/bin/, /usr/local/bin, и т.д.
Когда командный интерпретатор получает команду, то он автоматически пытается отыскать соответствующий исполняемый файл в указанном списке каталогов (в переменной $PATH). Каталоги, в указанном списке, должны отделяться друг от друга двоеточиями. Обычно, переменная $PATH инициализируется в /etc/profile и/или в ~/.bashrc (см. Глава 26).
Инструкция PATH=${PATH}:/opt/bin добавляет каталог /opt/bin в конец текущего пути поиска. Иногда может оказаться целесообразным, внутри сценария, временно добавить какой-либо каталог к пути поиска. По завершении работы скрипта, эти изменения будут утеряны (вспомните о том, что невозможно изменить переменные окружения вызывающего процесса).
![]() |
Текущий "рабочий каталог", ./, обычно не включается в $PATH из соображений безопасности. |
Код возврата канала (конвейера). Интересно, что это не то же самое, что код возврата последней исполненной команды.
![]() |
Переменная $PIPESTATUS может давать неверные значения при вызове из командной строки.
Если поместить эти строки в сценарий и исполнить его, то будут выведены верные значения 0 1 0. Спасибо Wayne Pollock за замечания и предоставленный пример. |
Переменная $PPID хранит PID (идентификатор) родительского процесса. [19]
Сравните с командой pidof.
Переменная хранит команду, которая используется непосредственно для вывода первичного приглашения к вводу — $PS1.
prompt, приглашение командной строки.
Вторичное приглашение командной строки, выводится тогда, когда от пользователя ожидается дополнительный ввод. Отображается как ">".
Третичное приглашение (prompt), выводится тогда, когда пользователь должен сделать выбор в операторе select (см. Пример 10-29).
Приглашение (prompt) четвертого уровня, выводится в начале каждой строки вывода тогда, когда сценарий вызывается с ключом -x. Отображается как "+".
рабочий (текущий) каталог
Аналог встроенной команды pwd.
переменная по-умолчанию, куда записывается ввод пользователя, выполненный с помощью команды read если явно не задана другая переменная. Так же может использоваться в операторе select, для построения меню выбора.
Время паботы сценария в секундах.
список допустимых опций интерпретатора shell. Переменная доступна только для чтения.
Уровень вложенности shell. Если в командной строке
Если переменная окружения $TMOUT содержит ненулевое значение, то интерпретатор будет ожидать ввод не более чем заданное число секунд, что, в первичном приглашении (см. описание PS1 выше), может привести к автоматическому завершению сеанса работы.
Начиная с версии 2.05b Bash, стало возможным использование $TMOUT в сценариях в комбинации с read.
Возможны и более сложные варианты организации организации ограничения времени ожидания ввода. Как один из вариантов, можно предложить организовать прерывание цикла ожидания по сигналу. Но это потребует написание функции обработки сигналов командой trap (см. Пример 29-5)
Пример 9-2. Ограничения времени ожидания ввода
В качестве альтернативы можно использовать stty.
Пример 9-3. Еще один пример ограничения времени ожидания ввода от пользователя
Возможно самый простой способ — использовать опцию -t команды read.
user id number
UID (идентификатор) текущего пользователя, в соответствии с /etc/passwd
Это реальный UID текущего пользователя, даже если он временно приобрел права другого пользователя с помощью su. Переменная $UID доступна только для чтения.
Пример 9-5. Я — root?
См. также Пример 2-2.
![]() |
Переменные $ENV, $LOGNAME, $MAIL, $TERM, $USER и $USERNAME, не являются встроенными переменными Bash. Тем не менее, они часто инициализируются как переменные окружения в одном из стартовых файлов Bash. Переменная $SHELL, командная оболочка пользователя, может задаваться в /etc/passwd или в сценарии "init" и она тоже не является встроенной переменной Bash.
|
Позиционные параметры (аргументы)
аргументы передаются... из командной строки в сценарий, функциям или команде set (см. Пример 4-5 и Пример 11-14)
количество аргументов командной строки [20], или позиционных параметров (см. Пример 33-2)
Все аргументы (позиционные параметры), в виде одной строки (слова)
![]() |
"$*" — необходимо заключать в кавычки. |
То же самое, что и $*, но при этом каждый параметр представлен как отдельная строка (слово), т.е. параметры не подвергаются какой либо интерпретации.
![]() |
"$@" — необходимо заключать в кавычки. |
Пример 9-6. arglist: Вывод списка аргументов с помощью переменных $* и $@
После команды shift (сдвиг), первый аргумент, в переменной $@, теряется, а остальные сдвигаются на одну позицию "вниз" (или "влево", если хотите).
Специальная переменная $@ может быть использована для выбора типа ввода в сценария. Команда cat "$@" позволяет выполнять ввод как со стандартного устройства ввода stdin, так и из файла, имя которого передается сценарию из командной строки. См. Пример 12-20 и Пример 12-21.
![]() |
Переменные $* и $@, в отдельных случаях, могут содержать противоречивую информацию! Это зависит от содержимого переменной $IFS. |
Пример 9-7. Противоречия в переменных $* и $@
![]() |
Различия между $@ и $* наблюдаются только тогда, когда они помещаются в двойные кавычки. |
Пример 9-8. Содержимое $* и $@, когда переменная $IFS — пуста
Прочие специальные переменные
Список флагов, переданных сценарию (командой set). См. Пример 11-14.
![]() |
Эта конструкция изначально была введена в ksh, откуда перекочевала в Bash и, похоже, работает в Bash не совсем надежно. Единственное возможное применение — проверка - запущен ли сценарий в интерактивном режиме. |
PID последнего, запущенного в фоне, процесса
Специальная переменная, содержит последний аргумент предыдущей команды.
Код возврата команды, функции или скрипта (см. Пример 22-6)
PID самого процесса-сценария. Переменная $$ часто используется при генерации "уникальных" имен для временных файлов (см. Пример A-14, Пример 29-6, Пример 12-26 и Пример 11-24). Обычно это проще чем вызов mktemp.
[19] PID текущего процесса хранится в переменной $$.
[20] Слова "аргумент" и "параметр" очень часто используются как синонимы. В тексте данного документа, они применяются для обозначения одного и того же понятия, будь то аргумент, передаваемый скрипту из командной строки или входной параметр функции.
Bash поддерживает на удивление большое количество операций над строками. К сожалению, этот раздел Bash испытывает недостаток унификации. Одни операции являются подмножеством операций подстановки параметров, а другие — совпадают с функциональностью команды Unix — expr. Это приводит к противоречиям в синтаксисе команд и перекрытию функциональных возможностей, не говоря уже о возникающей путанице.
Длина строки
Пример 9-10. Вставка пустых строк между параграфами в текстовом файле
Длина подстроки в строке (подсчет совпадающих символов ведется с начала строки)
где $substring — регулярное выражение.
где $substring — регулярное выражение.
Index
Номер позиции первого совпадения в $string c первым символом в $substring.
Эта функция довольно близка к функции strchr() в языке C.
Извлечение подстроки
Извлекает подстроку из $string, начиная с позиции $position.
Если строка $string — "*" или "@", то извлекается позиционный параметр (аргумент), [21] с номером $position.
Извлекает $length символов из $string, начиная с позиции $position.
Если $string — "*" или "@", то извлекается до $length позиционных параметров (аргументов), начиная с $position.
Извлекает $length символов из $string, начиная с позиции $position.
Находит и извлекает первое совпадение $substring в $string, где $substring — это регулярное выражение.
Находит и извлекает первое совпадение $substring в $string, где $substring — это регулярное выражение.
Находит и извлекает первое совпадение $substring в $string, где $substring — это регулярное выражение. Поиск начинается с конца $string.
Находит и извлекает первое совпадение $substring в $string, где $substring — это регулярное выражение. Поиск начинается с конца $string.
Удаление части строки
Удаление самой короткой, из найденых, подстроки $substring в строке $string. Поиск ведется с начала строки
Удаление самой длинной, из найденых, подстроки $substring в строке $string. Поиск ведется с начала строки
Удаление самой короткой, из найденых, подстроки $substring в строке $string. Поиск ведется с конца строки
Удаление самой длинной, из найденых, подстроки $substring в строке $string. Поиск ведется с конца строки
Пример 9-11. Преобразование графических файлов из одного формата в другой, с изменением имени файла
Замена подстроки
Замещает первое вхождение $substring строкой $replacement.
Замещает все вхождения $substring строкой $replacement.
Подстановка строки $replacement вместо $substring, если строка $string начинается найденым соответствием. Поиск ведется с начала строки $string.
Подстановка строки $replacement вместо $substring, если строка $string заканчивается найденым соответствием. Поиск ведется с конца строки $string.
В качестве альтернативы, Bash-скрипты могут использовать средства awk при работе со строками.
Пример 9-12. Альтернативный способ извлечения подстрок
Дополнительную информацию, по работе со строками, вы найдете в разделе Section 9.3 и в секции, посвященной команде expr. Примеры сценариев:
[21] Применяется к аргументам командной строки или входным параметрам функций.
Работа с переменными и/или подстановка их значений
То же самое, что и $parameter, т.е. значение переменной parameter. В отдельных случаях, при возникновении неоднозначности интерпретации, корректно будет работать только такая форма записи: ${parameter}.
Может использоваться для конкатенации (слияния) строковых переменных.
Если параметр отсутствует, то используется значение по-умолчанию.
![]() |
Формы записи ${parameter-default} и ${parameter:-default} в большинстве случаев можно считать эквивалентными. Дополнительный символ : имеет значение только тогда, когда parameter определен, но имеет "пустое" (null) значение. |
Параметры по-умолчанию очень часто находят применение в случаях, когда сценарию необходимы какие либо входные аргументы, передаваемые из командной строки, но такие аргументы не были переданы.
см. так же Пример 3-4, Пример 28-2 и Пример A-7.
Сравните этот подход с методом списков and list, для задания параметров командной строки по-умолчанию .
Если значения параметров не задананы явно, то они принимают значения по-умолчанию.
Оба метода задания значений по-умолчанию до определенной степени идентичны. Символ : имеет значение только когда $parameter был инициализирован "пустым" (null) значением, [22] как показано выше.
Если параметр имеет какое либо значение, то используется alt_value, иначе — null ("пустая" строка).
Оба варианта до определенной степени идентичны. Символ : имеет значение только если parameter объявлен и "пустой", см. ниже.
Если parameter инициализирован, то используется его значение, в противном случае — выводится err_msg.
Обе формы записи можно, до определенной степени, считать идентичными. Символ : имеет значение только когда parameter инициализирован "пустым" значением, см. ниже.
Пример 9-13. Подстановка параметров и сообщения об ошибках
Пример 9-14. Подстановка параметров и сообщение о "порядке использования"
Подстановка параметров и/или экспансия. Следующие выражения могут служить дополнениями оператора match команды expr, применяемой к строкам (см. Пример 12-9). Как правило, они используются при разборе имен файлов и каталогов.
Длина переменной / Удаление подстроки
String length (число символов в переменной $var). В случае массивов, команда ${#array} возвращает длину первого элемента массива.
![]() |
Исключения:
|
Пример 9-15. Длина переменной
Удаляет из переменной $var наименьшую/наибольшую подстроку, совпадающую с шаблоном $Pattern. Поиск ведется с начала строки $var.
Пример использования из Пример A-8:
Manfred Schwarb предложил более сложный вариант вышеприведенного кода:
Другой пример:
Удаляет из переменной $var наименьшую/наибольшую подстроку, совпадающую с шаблоном $Pattern. Поиск ведется с конца строки $var.
Bash версии 2 имеет ряд дополнительных возможностей.
Пример 9-16. Поиск по шаблону в подстановке параметров
Пример 9-17. Изменение расширений в именах файлов:
Подстановка значений переменных / Замена подстроки
Эти конструкции перекочевали в Bash из ksh.
Подстанавливается значение переменной var, начиная с позиции pos.
Подстанавливается значение переменной var, начиная с позиции pos, не более len символов. См. Пример A-16.
Первое совпадение с шаблоном Pattern, в переменной var замещается подстрокой Replacement.
Если подстрока Replacement отсутствует, то найденое совпадение будет удалено.
Глобальная замена. Все найденые совпадения с шаблоном Pattern, в переменной var, будут замещены подстрокой Replacement.
Как и в первом случае, если подстрока Replacement отсутствует, то все найденые совпадения будут удалены.
Пример 9-18. Поиск по шаблону при анализе произвольных строк
Если в переменной var найдено совпадение с Pattern, причем совпадающая подстрока расположена в начале строки (префикс), то оно заменяется на Replacement. Поиск ведется с начала строки
Если в переменной var найдено совпадение с Pattern, причем совпадающая подстрока расположена в конце строки (суффикс), то оно заменяется на Replacement. Поиск ведется с конца строки
Пример 9-19. Поиск префиксов и суффиксов с заменой по шаблону
Поиск по шаблону всех, ранее объявленных переменных, имена которых начинаются с varprefix.
[22] Если $parameter "пустой",в неинтерактивных сценариях, то это будет приводить к завершению с кодом возврата 127 ("command not found").
Инструкции declare и typeset являются встроенными инструкциями (они абсолютно идентичны друг другу и являются синонимами) и предназначена для наложения ограничений на переменные. Это очень слабая попытка контроля над типами, которая имеется во многих языках программирования. Инструкция declare появилась в Bash, начиная с версии 2. Кроме того, инструкция typeset может использоваться и в ksh-сценариях.
ключи инструкций declare/typeset
(declare -r var1 аналогично объявлению readonly var1)
Это грубый эквивалент констант (const) в языке C. Попытка изменения таких переменных завершается сообщением об ошибке.
Переменная indices объявляется массивом.
Инструкция declare -f, без аргументов, приводит к выводу списка ранее объявленных функций в сценарии.
Инструкция declare -f function_name выводит имя функции function_name, если она была объявлена ранее.
Эта инструкция объявляет переменную, как доступную для экспорта.
Инструкция declare допускает совмещение объявления и присваивания значения переменной одновременно.
Пример 9-20. Объявление переменных с помощью инструкции declare
Предположим, что значение одной переменной — есть имя второй переменной. Возможно ли получить значение второй переменной через обращение к первой? Например, Пусть a=letter_of_alphabet и letter_of_alphabet=z, тогда вопрос будет звучать так: "Возможно ли получить значение z, обратившись к переменной a?". В действительности это возможно и это называется косвенной ссылкой. Для этого необходимо прибегнуть к несколько необычной нотации eval var1=\$$var2.
Пример 9-21. Косвенные ссылки
Пример 9-22. Передача косвенных ссылок в awk
![]() |
Такой метод обращения к переменным имеет свои особенности. Если переменная, на которую делается ссылка, меняет свое значение, то переменная которая ссылается, должна быть должным образом разыменована, т.е. олжна быть выполнена операция получения ссылки, как это делается в примере выше. К счастью, нотация ${!variable}, введенная в Bash, начиная с версии 2 (см. Пример 34-2) позволяет выполнять косвенные ссылки более интуитивно понятным образом. |
$RANDOM — внутренняя функция Bash (не константа), которая возвращает псевдослучайные целые числа в диапазоне 0 - 32767. Функция $RANDOM не должна использоваться для генераци ключей шифрования.
Пример 9-23. Генерация случайных чисел
Пример 9-24. Выбор случайной карты из колоды
Насколько случайны числа, возвращаемые функцией $RANDOM? Лучший способ оценить "случайность" генерируемых чисел — это написать сценарий, который будет имитировать бросание игрального кубика достаточно большое число раз, а затем выведет количество выпадений каждой из граней...
Пример 9-26. Имитация бросания кубика с помощью RANDOM
Как видно из последнего примера, неплохо было бы производить переустановку начального числа генератора случайных чисел RANDOM перед тем, как начать работу с ним. Если используется одно и то же начальное число, то генератор RANDOM будет выдавать одну и ту же последовательность чисел. (Это совпадает с поведением функции random() в языке C.)
Пример 9-27. Переустановка RANDOM
![]() |
Системный генератор /dev/urandom дает последовательность псевдослучайных чисел с более равномерным распределением, чем $RANDOM. Команда dd if=/dev/urandom of=targetfile bs=1 count=XX создает файл, содержащий последовательность псевдослучайных чисел. Однако, эти числа требуют дополнительной обработки, например с помощью команды od (этот прием используется в примере выше) или dd (см. Пример 12-45). Есть и другие способы генерации псевдослучайных последовательностей в сценариях. Awk имеет для этого достаточно удобные средства. Пример 9-28. Получение псевдослучайных чисел с помощью awk
Кроме того, команда date так же может использоваться для генерации псевдослучайных целых чисел. |
Эта конструкция во многом похожа на инструкцию let, внутри ((...)) вычисляются арифметические выражения и возвращается их результат. В простейшем случае, конструкция a=$(( 5 + 3 )) присвоит переменной "a" значение выражения "5 + 3", или 8. Но, кроме того, двойные круглые скобки позволяют работать с переменными в стиле языка C.
Пример 9-29. Работа с переменными в стиле языка C
См. так же Пример 10-12.
Управление ходом исполнения — один из ключевых моментов структурной организации сценариев на языке командной оболочки. Циклы и преходы являются теми инструментальными средствами, которые обеспечивают управление порядком исполнения команд.
Цикл — это блок команд, который исполняется многократно до тех пор, пока не будет выполнено условие выхода из цикла.
Это одна из основных разновидностей циклов. И она значительно отличается от аналога в языке C.
for arg in [list]
do
команда(ы)...
done
![]() |
На каждом проходе цикла, переменная-аргумент цикла arg последовательно, одно за другим, принимает значения из списка list. |
Элементы списка могут включать в себя шаблонные символы.
Есл ключевое слово do находится в одной строке со словом for, то после списка аргументов (перед do) необходимо ставить точку с запятой.
for arg in [list] ; do
Пример 10-1. Простой цикл for
![]() |
Каждый из элементов [списка] может содержать несколько аргументов. Это бывает полезным при обработке групп параметров. В этом случае, для принудительного разбора каждого из аргументов в списке, необходимо использовать инструкцию set (см. Пример 11-14). |
Пример 10-2. Цикл for с двумя параметрами в каждом из элементов списка
В качестве списка, в цикле for, можно использовать переменную.
Пример 10-3. Fileinfo: обработка списка файлов, находящегося в переменной
В [списке] цикла for могут быть использованы имена файлов, которые в свою очередь могут содержать символы-шаблоны.
Пример 10-4. Обработка списка файлов в цикле for
Если [список] в цикле for не задан, то в качестве оного используется переменная $@ — список аргументов командной строки. Оень остроумно эта особенность проиллюстрирована в Пример A-18.
Пример 10-5. Цикл for без списка аргументов
При создании списка аргументов, в цикле for допускается пользоваться подстановкой команд. См. Пример 12-42, Пример 10-10 и Пример 12-36.
Пример 10-6. Создание списка аргументов в цикле for с помощью операции подстановки команд
Более сложный пример использования подстановки команд при создании списка аргументов цикла.
Пример 10-7. grep для бинарных файлов
Еще один пример.
Пример 10-8. Список всех пользователей системы
И заключительный пример использования подстановки команд при создании [списка].
Пример 10-9. Проверка авторства всех бинарных файлов в текущем каталоге
Результат работы цикла for может передаваться другим командам по конвейеру.
Пример 10-10. Список символических ссылок в каталоге
Вывод цикла может быть перенаправлен со stdout в файл, ниже приводится немного модифицированный вариант предыдущего примера, демонстрирующий эту возможность.
Пример 10-11. Список символических ссылок в каталоге, сохраняемый в файле
Оператор цикла for имеет и альтернативный синтаксис записи — очень похожий на синтаксис оператора for в языке C. Для этого используются двойные круглые скобки.
Пример 10-12. C-подобный синтаксис оператора цикла for
См. так же Пример 25-15, Пример 25-16 и Пример A-7.
---
А сейчас пример сценария, который может найти "реальное" применение.
Пример 10-13. Работа с командой efax в пакетном режиме
Оператор while проверяет условие перед началом каждой итерации и если условие истинно (если код возврата равен 0), то управление передается в тело цикла. В отличие от циклов for, циклы while используются в тех случаях, когда количество итераций заранее не известно.
while [condition]
do
command...
done
Как и в случае с циклами for/in, при размещении ключевого слова do в одной строке с объявлением цикла, необходимо вставлять символ ";" перед do.
while [condition] ; do
Обратите внимание: в отдельных случаях, таких как использование конструкции getopts совместно с оператором while, синтаксис несколько отличается от приводимого здесь.
Пример 10-14. Простой цикл while
Пример 10-15. Другой пример цикла while
Оператор while может иметь несколько условий. Но только последнее из них определяет возможность продолжения цикла. В этом случае синтаксис оператора цикла должен быть несколько иным.
Пример 10-16. Цикл while с несколькими условиями
Как и в случае с for, цикл while может быть записан в C-подобной нотации, с использованием двойных круглых скобок (см. так же Пример 9-29).
Пример 10-17. C-подобный синтаксис оформления цикла while
![]() |
Стандартное устройство ввода stdin, для цикла while, можно перенаправить на файл с помощью команды перенаправления < в конце цикла. |
Оператор цикла until проверяет условие в начале каждой итерации, но в отличие от while итерация возможна только в том случае, если условие ложно.
until [condition-is-true]
do
command...
done
Обратите внимание: оператор until проверяет условие завершения цикла ПЕРЕД очередной итерацией, а не после, как это принято в некоторых языках программирования.
Как и в случае с циклами for/in, при размещении ключевого слова do в одной строке с объявлением цикла, необходимо вставлять символ ";" перед do.
until [condition-is-true] ; do
Цикл называется вложенным, если он размещается внутри другого цикла. На первом проходе, внешний цикл вызывает внутренний, который исполняется до своего завершения, после чего управление передается в тело внешнего цикла. На втором проходе внешний цикл опять вызывает внутренний. И так до тех пор, пока не завершится внешний цикл. Само собой, как внешний, так и внутренний циклы могут быть прерваны командой break.
Пример 10-19. Вложенный цикл
Демонстрацию вложенных циклов "while" вы найдете в Пример 25-11, а вложение цикла "while" в "until" — в Пример 25-13.
Для управления ходом выполнения цикла служат команды break и continue [23] и точно соответствуют своим аналогам в других языках программирования. Команда break прерывает исполнение цикла, в то время как continue передает управление в начало цикло, минуя все последующие команды в теле цикла.
Пример 10-20. Команды break и continue в цикле
Команде break может быть передан необязательный параметр. Команда break без параметра прерывает тот цикл, в который она вставлена, а break N прерывает цикл, стоящий на N уровней выше (причем 1-й уровень — это уровень текущего цикла, прим. перев.).
Пример 10-21. Прерывание многоуровневых циклов
Команда continue, как и команда break, может иметь необязательный параметр. В простейшем случае, команда continue передает управление в начало текущего цикла, а команда continue N прерывает исполнение текущего цикла и передает управление в начало внешнего цикла, отстоящего от текущего на N уровней (причем 1-й уровень — это уровень текущего цикла, прим. перев.).
Пример 10-22. Передача управление в начало внешнего цикла
Пример 10-23. Живой пример использования "continue N"
![]() |
Конструкция continue N довольно сложна в понимании и применении, поэтому, вероятно лучше будет постараться избегать ее использования. |
[23] Эти команды являются встроенными командами языка сценариев командной оболочки (shell), в то время как while, case и т.п. — являются зарезервированными словами.
Инструкции case и select технически не являются циклами, поскольку не предусматривают многократное исполнение блока кода. Однако, они, как и циклы, управляют ходом исполнения программы, в зависимости от начальных или конечных условий.
Конструкция case эквивалентна конструкции switch в языке C/C++. Она позволяет выполнять тот или иной участок кода, в зависимости от результатов проверки условий. Она является, своего рода, краткой формой записи большого количества операторов if/then/else и может быть неплохим инструментом при создании разного рода меню.
case "$variable" in
"$condition1" )
command...
;;
"$condition2" )
command...
;;
esac
![]() |
|
Пример 10-24. Использование case
Пример 10-25. Создание меню с помощью case
Очень хороший пример использования case для анализа аргументов, переданных из командной строки.
Пример 10-26. Оператор case допускает использовать подстановку команд вместо анализируемой переменной
Оператор case допускает использование шаблонных конструкций.
Пример 10-27. Простой пример сравнения строк
Пример 10-28. Проверка ввода
Оператор select был заимствован из Korn Shell, и является еще одним инструментом, используемым при создании меню.
select variable [in list]
do
command...
break
done
Этот оператор предлагает пользователю выбрать один из представленных вариантов. Примечательно, что select по-умолчанию использует в качестве приглашения к вводу (prompt) — PS3 (#? ), который легко изменить.
Пример 10-29. Создание меню с помощью select
Если в операторе select список in list не задан, то в качестве списка будет использоваться список аргументов ($@), передаваемый сценарию или функции.
Сравните это с поведением оператора цикла
for variable [in list]
в котором не задан список аргументов.Пример 10-30. Создание меню с помощью select в функции
См. так же Пример 34-3.
Внутренняя команда — это команда, которая встроена непосредственно в Bash. Команды делаются встроенными либо из соображений производительности — встроенные команды исполняются быстрее, чем внешние, которые, как правило, запускаются в дочернем процессе, либо из-за необходимости прямого доступа к внутренним структурам командного интерпретатора.
Внутренние команды могут иметь внешние аналоги. Например, внутренняя команда Bash — echo имеет внешний аналог /bin/echo и их поведение практически идентично.
Ключевое слово (keyword) — это зарезервированное слово, синтаксический элемент (token) или оператор. Ключевые слова имеют специальное назначение для командного интерпретатора, и фактически являются элементами синтаксиса языка командной оболочки. В качестве примера можно привести "for", "while", "do", "!", которые являются ключевыми (или зарезервированными) словами. Подобно встроенным командам, ключевые слова жестко зашиты в Bash, но в отличие от встроенных команд, ключевые слова не являются командами как таковыми, хотя при этом могут являться их составной частью. [24]
выводит (на stdout) выражение или содержимое переменной (см. Пример 4-1).
Для вывода экранированных символов, echo требует наличие ключа -e. См. Пример 5-2.
Обычно, командв echo выводит в конце символ перевода строки. Подавить вывод это символа можно ключом -n.
![]() |
Команда echo может использоваться для передачи информации по конвейеру другим командам.
|
![]() |
Кроме того, команда echo, в комбинации с подстановкой команд может учавствовать в операции присвоения значения переменной. a=`echo "HELLO" | tr A-Z a-z` См. так же Пример 12-18, Пример 12-3, Пример 12-35 и Пример 12-36. |
Следует запомнить, что команда echo `command` удалит все символы перевода строки, которые будут выведены командой command.
Переменная $IFS обычно содержит символ перевода строки \n, как один из вариантов пробельного символа. Bash разобьет вывод команды command, по пробельным символам, на аргументы и передаст их команде echo, которая выведет эти аргументы, разделенные пробелами.
![]() |
Это встроенная команда Bash и имеет внешний аналог /bin/echo.
|
printf — команда форматированного вывода, расширенный вариант команды echo и ограниченный вариант библиотечной функции printf() в языке C, к тому же синтаксис их несколько отдичается друг от друга.
printf format-string... parameter...
Это встроенная команда Bash. Имеет внешний аналог /bin/printf или /usr/bin/printf. За более подробной информацией обращайтесь к страницам справочного руководства man 1 printf по системным командам.
![]() |
Старые версии Bash могут не поддерживать команду printf. |
Пример 11-1. printf в действии
Одно из полезных применений команды printf — форматированный вывод сообщений об ошибках
"Читает" значение переменной с устройства стандартного ввода — stdin, в интерактивном режиме это означает клавиатуру. Ключ -a позволяет записывать значения в массивы (см. Пример 25-6).
Пример 11-2. Ввод значений переменных с помощью read
Если команде read не была передано ни одной переменной, то ввод будет осуществлен в переменную $REPLY.
Пример 11-3. Пример использования команды read без указания переменной для ввода
Обычно, при вводе в окне терминала с помощью команды "read", символ \ служит для экранирования символа перевода строки. Ключ -r заставляет интерпретировать символ \ как обычный символ.
Пример 11-4. Ввод многострочного текста с помощью read
Команда read имеет ряд очень любопытных опций, которые позволяют выводить подсказку - приглашение ко вводу (prompt), и даже читать данные не дожидаясь нажатия на клавишу ENTER.
Ключ -n, кроме всего прочего, позволяет команде read обнаруживать нажатие курсорных и некоторых других служебных клавиш.
Пример 11-5. Обнаружение нажатия на курсорные клавиши
Ключ -t позволяет ограничивать время ожидания ввода командой read (см. Пример 9-4).
Команда read может считывать значения для переменных из файла, перенаправленного на stdin. Если файл содержит не одну строку, то переменной будет присвоена только первая строка. Если команде read будет передано несколько переменных, то первая строка файла будет разбита, по пробелам, на несколько подстрок, каждая из которых будет записана в свою переменную. Будьте осторожны!
Пример 11-6. Чтение командой read из файла через перенаправление
![]() |
Передача информации, выводимой командой echo, по конвейеру команде read, будет вызывать ошибку. Тем не менее, передача данных по конвейеру от cat, кажется срабатывает.
Не смотря на это, как указывает Bjon Eriksson: Пример 11-7. Проблемы чтения данных из канала (конвейера)
|
Уже знакомая нам команда cd, изменяющая текущий каталог, может быть использована в случаях, когда некоторую команду необходимо запустить только находясь в определенном каталоге.
Команда cd с ключом -P (physical) игнорирует символические ссылки.
Команда "cd -" выполняет переход в каталог $OLDPWD — предыдущий рабочий каталог.
![]() |
Неожиданным образом выполняется команда cd, если ей передать, в качестве каталога назначения, два слэша.
|
Выводит название текущего рабочего каталога (Print Working Directory) (см. Пример 11-8). Кроме того, имя текущего каталога хранится во внутренней переменной $PWD.
Этот набор команд является составной частью механизма "закладок" на каталоги и позволяет перемещаться по каталогам вперед и назад в заданном порядке. Для хранения имен каталогов используется стек (LIFO — "последний вошел, первый вышел").
pushd dir-name — помещает имя текущего каталога в стек и осуществляет переход в каталог dir-name.
popd — выталкивает, находящееся на вершине стека, имя каталога и одновременно осуществляет переход в каталог, оказавшийся на врешине стека.
dirs — выводит содержимое стека каталогов (сравните с переменной $DIRSTACK). В случае успеха, обе команды — pushd и popd автоматически вызывают dirs.
Эти команды могут оказаться весьма полезными, когда в сценарии нужно производить частую смену каталогов, но при этом не хочется жестко "зашивать" имена каталогов. Обратите внимание: содержимое стека каталогов постоянно хранится в переменной-массиве — $DIRSTACK.
Пример 11-8. Смена текущего каталога
Команда let производит арифметические операции над переменными. В большинстве случаев, ее можно считать упрощенным вариантом команды expr.
Пример 11-9. Команда let, арифметические операции.
eval arg1 [arg2] ... [argN]
Транслирует список аргументов, из списка, в команды.
Пример 11-10. Демонстрация команды eval
Пример 11-11. Принудительное завершение сеанса
Пример 11-12. Шифрование по алгоритму "rot13"
Rory Winston представил следующий пример, как образец практического использования команды eval.
Пример 11-13. Замена имени переменной на ее значение, в исходном тексте программы на языке Perl, с помощью eval
![]() |
Команда eval может быть небезопасна. Если существует приемлемая альтернатива, то желательно воздерживаться от использования eval. Так, eval $COMMANDS исполняет код, который записан в переменную COMMANDS, которая, в свою очередь, может содержать весьма неприятные сюрпризы, например rm -rf *. Использование команды eval, для исполнения кода неизвестного происхождения, крайне опасно. |
Команда set изменяет значения внутренних переменных сценария. Она может использоваться для переключения опций (ключей, флагов), определяющих поведение скрипта. Еще одно применение — сброс/установка позиционных параметров (аргументов), значения которых будут восприняты как результат работы команды (set `command`).
Пример 11-14. Установка значений аргументов с помощью команды set
Вызов set без параметров просто выводит список инициализированных переменных окружения.
Если команда set используется с ключом "--", после которого следует переменная, то значение переменной переносится в позиционные параметры (аргументы). Если имя переменной отсутствует, то эта команда приводит к сбросу позиционных параметров.
Пример 11-15. Изменение значений позиционных параметров (аргументов)
См. так же Пример 10-2 и Пример 12-43.
Команда unset удаляет переменную, фактически — устанавливает ее значение в null. Обратите внимание: эта команда не может сбрасывать позиционные параметры (аргументы).
Команда export экспортирует переменную, делая ее доступной дочерним процессам. К сожалению, невозможно экспортировать переменную родительскому процессу. В качестве примера использования команды export можно привести сценарии инициализации системы, вызываемые в процессе загрузки, которые инициализируют и экспортируют переменные окружения, делая их доступными для пользовательских процессов.
Пример 11-17. Передача переменных во вложенный сценарий awk, с помощью export
![]() |
Допускается объединение инициализации и экспорта переменной в одну инструкцию: export var1=xxx. Однако, как заметил Greg Keraunen, в некоторых ситуациях такая комбинация может давать иной результат, нежели раздельная инициализация и экспорт.
|
Команды declare и typeset задают и/или накладывают ограничения на переменные.
То же самое, что и declare -r, делает переменную доступной только для чтения, т.е. переменная становится подобна константе. При попытке изменить значение такой переменной выводится сообщение об ошибке. Эта команда может расцениваться как квалификатор типа const в языке C.
Мощный инструмент, используемый для разбора аргументов, передаваемых сценарию из командной строки. Это встроенная команда Bash, но имеется и ее "внешний" аналог /usr/bin/getopt, а так же программистам, пишущим на C, хорошо знакома похожая библиотечная функция getopt. Она позволяет обрабатывать серии опций, объединенных в один аргумент [25] и дополнительные аргументы, передаваемые сценарию (например, scriptname -abc -e /usr/local).
С командой getopts очень тесно взаимосвязаны скрытые переменные. $OPTIND — указатель на аргумент (OPTion INDex) и $OPTARG (OPTion ARGument) — дополнительный аргумент опции. Символ двоеточия, следующий за именем опции, указывает на то, что она имеет дополнительный аргумент.
Обычно getopts упаковывается в цикл while, в каждом проходе цикла извлекается очередная опция и ее аргумент (если он имеется), обрабатывается, затем уменьшается на 1 скрытая переменная $OPTIND и выполняется переход к началу новой итерации.
![]() |
|
Пример 11-18. Прием опций/аргументов, передаваемых сценарию, с помощью getopts
Когда эта команда вызывается из командной строки, то это приводит к запуску указанного сценария. Внутри сценария, команда source file-name загружает файл file-name. Таким образом она очень напоминает директиву препроцессора языка C/C++ — "#include". Может найти применение в ситуациях, когда несколько сценариев пользуются одним файлом с данными или библиотекой функций.
Пример 11-19. "Подключение" внешнего файла
Файл data-file для Пример 11-19, представленного выше, должен находиться в том же каталоге.
Сценарий может подключить даже самого себя, только этому едва ли можно найти какое либо практическое применение.
Пример 11-20. Пример (бесполезный) сценария, который подключает себя самого.
Безусловное завершение работы сценария. Команде exit можно передать целое число, которое будет возвращено вызывающему процессу как код завершения. Вообще, считается хорошей практикой завершать работу сценария, за исключением простейших случаев, командой exit 0, чтобы проинформировать родительский процесс об успешном завершении.
![]() |
Если сценарий завершается командой exit без аргументов, то в качестве кода завершения сценария принимается код завершения последней выполненной команды, не считая самой команды exit. |
Это встроенная команда интерпретатора shell, заменяет текущий процесс новым процессом, запускаемым командой exec. Обычно, когда командный интерпретатор встречает эту команду, то он порождает дочерний процесс, чтобы исполнить команду. При использовании встроенной команды exec, оболочка не порождает еще один процесс, а заменяет текущий процесс другим. Для сценария это означает его завершение сразу после исполнения команды exec. По этой причине, если вам встретится exec в сценарии, то, скорее всего это будет последняя команда в сценарии.
Пример 11-21. Команда exec
Пример 11-22. Сценарий, который запускает себя самого
Команда exec так же может использоваться для перенаправления. Так, команда exec <zzz-file заменит стандартное устройство ввода (stdin) файлом zzz-file (см. Пример 16-1).
![]() |
Ключ -exec команды find — это не то же самое, что встроенная команда exec. |
Эта команда позволяет изменять ключи (опции) оболочки на лету (см. Пример 23-1 и Пример 23-2). Ее часто можно встретить в стартовых файлах, но может использоваться и в обычных сценариях. Требует Bash версии 2 или выше.
Команда возвращает код завершения — ноль, или успешное завершение, и ничего больше.
Возвращает код завершения, свидетельствующий о неудаче, и ничего более.
Очень похожа на внешнюю команду which, type cmd выводит полный путь к "cmd". В отличие от which, type является внутренней командой Bash. С опцией -a не только различает ключевые слова и внутренние команды, но и определяет местоположение внешних команд с именами, идентичными внутренним.
Запоминает путь к заданной команде (в хэш-таблице командной оболочки), благодаря чему, при повторном обращении к ней, оболочка или сценарий уже не будет искать путь к команде в $PATH. При вызове команды hash без аргументов, просто выводит содержимое хэш-таблицы. С ключом -r — очищает хэш-таблицу.
help COMMAND — выводит краткую справку по использованию внутренней команды COMMAND. Аналог команды whatis, только для внутренних команд.
[24] Исключение из правил — команда time, которая в официальной документации к Bash называется ключевым словом.
[25] Опция — это аргумент, который управляет поведением сценария и может быть либо включен, либо выключен. Аргумент, который объединяет в себе несколько опций (ключей), определяет поведение сценария в соответствии с отдельными опциями, объединенными в данном аргументе..
Некоторые из нижеследующих команд принимают, в качестве аргумента, "идентификатор задания". См. таблицу в конце главы.
Выводит список заданий, исполняющихся в фоне. Команда ps более информативна.
![]() |
Задания и процессы легко спутать. Некоторые внутренние команды, такие как kill, disown и wait принимают в качестве параметра либо номер задания, либо номер процесса. Команды fg, bg и jobs принимают только номер задания.
"1" — это номер задания (управление заданиями осуществляет текущий командный интерпретатор), а "1384" — номер процесса (управление процессами осуществляется системой). Завершить задание/процесс ("прихлопнуть") можно либо командой kill %1, либо kill 1384. Спасибо S.C. |
Удаляет задание из таблицы активных заданий командной оболочки.
Команда fg переводит задание из фона на передний план. Команда bg перезапускает приостановленное задание в фоновом режиме. Если эти команды были вызваны без указания номера задания, то они воздействуют на текущее исполняющееся задание.
Останавливает работу сценария до тех пор пока не будут завершены все фоновые задания или пока не будет завершено задание/процесс с указанным номером задания/PID процесса. Возвращает код завершения указанного задания/процесса.
Вы можете использовать команду wait для предотвращения преждевременного завершения сценария до того, как завершит работу фоновое задание.
Пример 11-23. Ожидание завершения процесса перед тем как продолжить работу
Команда wait может принимать необязательный параметр — номер задания/процесса, например, wait %1 или wait $PPID. См. таблицу идентификации заданий.
![]() |
При запуске команды в фоне из сценария может возникнуть ситуация, когда сценарий приостанавливает свою работу до тех пор, пока не будет нажата клавиша ENTER. Это, кажется, происходит с командами, делающими вывод на stdout. Такое поведение может вызывать раздражение у пользователя.
Разместив команду wait, после запуска фонового задания, можно предотвратить такое поведение сценария.
|
Действует аналогично нажатию на комбинацию клавиш Control+-Z, за исключением того, что она приостанавливает работу командной оболочки.
Завершает сеанс работы командной оболочки, можно указать необязательный код завершения.
Выдает статистику исполнения команд в единицах системного времени, в следующем виде:
Принудительное завершение процесса путем передачи ему соответствующего сигнала (см. Пример 13-5).
Пример 11-24. Сценарий, завершающий себя сам с помощью команды kill
![]() |
Команда kill -l выведет список всех сигналов. Команда kill -9 — это "жесткий kill", она используется, как правило, для завершения зависших процессов, которые упорно отказываются "умирать", отвергая простой kill. Иногда достаточно подать команду kill -15. "Процессы-зомби", т.е. процессы, "родители" которых уже завершили работу, не могут быть "убиты" таким способом (невозможно "убить" "мертвого"), рано или поздно с ними "расправится" процесс init. |
Директива command COMMAND запрещает использование псевдонимов и функций с именем "COMMAND".
Конструкция builtin BUILTIN_COMMAND запускает внутреннюю команду "BUILTIN_COMMAND", на время запрещая использование функций и внешних системных команд с тем же именем.
Либо запрещает, либо разрешает вызов внутренних команд. Например, enable -n kill запрещает использование внутренней команды kill, в результате, когда интерпретатор встретит команду kill, то он вызовет внешнюю команду kill, т.е. /bin/kill.
Команда enable -a выведет список всех внутренних команд, указывая для каждой — действительно ли она разрешена. Команда enable -f filename загрузит внутренние команды как разделяемую библиотеку (DLL) из указанного объектного файла. [26].
Перенесена в Bash из ksh. Если функция объявлена как autoload, то она будет загружена из внешнего файла в момент первого вызова. [27] Такой прием помогает экономить системные ресурсы.
Обратите внимание: autoload не является частью ядра Bash. Ее необходимо загрузить с помощью команды enable -f (см. выше).
Таблица 11-1. Идентификация заданий
| Нотация | Описание |
|---|---|
| %N | Номер задания [N] |
| %S | Вызов (командная строка) задания, которая начинается со строки S |
| %?S | Вызов (командная строка) задания, которая содержит строку S |
| %% | "текущее" задание (последнее задание приостановленное на переднем плане или запущенное в фоне) |
| %+ | "текущее" задание (последнее задание приостановленное на переднем плане или запущенное в фоне) |
| %- | Последнее задание |
| $! | Последний фоновый процесс |
[26] Как правило, исходные тексты подобных библиотек, на языке C, располагаются в каталоге /usr/share/doc/bash-?.??/functions.
[27] Тот же эффект можно получить с помощью typeset -fu.
Благодаря стандартизации набора команд Unix-систем, сценарии, на языке командной оболочки, могут быть легко перенесены из системы в систему практически без изменений. Мощь сценариев складывется из наборв системных команд и директив командной оболочки с простыми программными конструкциями.
Первая команда, с которой сталкиваются новички
Команда вывода "списка" файлов. Многие недооценивают всю мощь этой скромной команды. Например, с ключом -R, рекурсивный обход дерева каталогов, командв ls выводит содержимое каталогов в виде древовидной структуры. Вот еще ряд любопытных ключей (опций) команды ls: -S — сортировка по размеру файлов, -t — сортировка по времени последней модификации файла и -i — выводит список файлов с их inode (см. Пример 12-4).
Пример 12-1. Создание оглавления диска для записи CDR, с помощью команды ls
cat — это акроним от concatenate, выводит содержимое списка файлов на stdout. Для объединения файлов в один файл может использоваться в комбинации с операциями перенаправления (> или >>).
см. также Пример 12-24 and Пример 12-20.
tac — выводит содержимое файлов в обратном порядке, от последней строки к первой.
выводит все строки файла задом наперед на stdout. Это не то же самое, что tac. Команда rev сохраняет порядок следования строк, но переворачивает каждую строку задом наперед.
Команда копирования файлов. cp file1 file2 скопирует file1 в file2, перезаписав file2 если он уже существовал (см. Пример 12-6).
![]() |
С флагами -a и -r, или -R выполняет копирование дерева каталогов. |
Команда перемещения файла. Эквивалентна комбинации команд cp и rm. Может использоваться для перемещения большого количества файлов или для переименования каталогов. Примеры использования команды mv вы найдете в Пример 9-17 и Пример A-3.
![]() |
При использовании в неинтерактивных сценариях, команде mv следует передавать ключ -f, чтобы подавить запрос подтверждения на перемещение. Если в качестве каталога назначения указан существующий каталог, то перемещаемый каталог становится подкаталогом каталога назначения..
|
Удаляет (remove) файл(ы). Ключ -f позволяет удалять даже файлы ТОЛЬКО-ДЛЯ-ЧТЕНИЯ и подавляет запрос подтверждения на удаление.
![]() |
При попытке удаления файлов, чьи имена начинаются с символа "-" (дефис), команда rm будет давать сообщение об ошибке.
Как вариант можно предложить предварять имена таких файлов точкой-со-слэшем — "./" (путь к файлу в текущем каталоге, прим. перев.) .
|
![]() |
С ключом -r, удалит все файлы в подкаталогах, начиная с текущего. |
Удаляет каталог. Удаляемый каталог не должен содержать файлов, включая "скрытые файлы", [28] иначе каталог не будет удален.
Создает новый каталог, например: mkdir -p project/programs/December создает каталог с заданным именем в требуемом каталоге. Ключ -p позволяет создавать промежуточные родительские каталоги.
Изменяет атрибуты существующего файла (см. Пример 11-11).
Изменяет атрибуты файла. Эта команда подобна команде chmod, за исключением синтаксиса вызова, и работает исключительно в файловой системе ext2.
Создает ссылку на существующий файл. Позволяет задавать несколько имен одному и тому же файлу и представляет из себя превосходную альтернативу "псевдонимам" (алиасам) (см. Пример 4-6).
Размер файла-ссылки, создаваемого командой ln, имеет длину всего в несколько байт.
Чаще всего команда ln используется с ключом -s, который служит для создания символической (symbolic), или "мягкой" ("soft") ссылки. Без этого флага, команда создает полноценную копию имени файла. С ключом — только ссылку, указывающую на заданный файл. Дополнительное преимущество ключа -s состоит в том, что он позволяет создавать ссылки на файлы, расположенные в других файловых системах.
Синтаксис команды достаточно прост. Например, команда: ln -s oldfile newfile создаст ссылку, с именем newfile, на существующий файл oldfile,
![]() |
Если файл с именем newfile уже существует, то он будет удален командой ln. |
Ссылки дают возможность запускать одну и ту же программу или сценарий, использую различные имена. В этом случае программист может предусмотреть свой вариант развития событий для каждого из имен.
Пример 12-2. Здравствуй или Прощай
Команды доступа к справочным и информационным страницам по системным командам и установленным программам и утилитам. Как правило, страницы info содержат более подробную информацию, чем man.
[28] Скрытыми считаются файлы, имена которых начинаются с точки, например, ~/.Xdefaults. Такие файлы не выводятся простой командой ls, и не могут быть удалены командой rm -rf *. Как правило, скрытыми делаются конфигурационные файлы в домашнем каталоге пользователя.
Команды для более опытных пользователей
-exec COMMAND \;
Для каждого найденого файла, соответствующего заданному шаблону поиска, выполняет команду COMMAND. Командная строка должна завершаться последовательностью символов \; (здесь символ ";" экранирован обратным слэшем, чтобы информировать командную оболочку о том, что символ ";" должен быть передан команде find как обычный символ). Если COMMAND содержит {}, то find подставляет полное имя найденого файла вместо "{}".
![]() |
Не следует путать опцию -exec команды find с внутренней командой Bash — exec. |
Пример 12-3. Badname, удаление файлов в текущем каталоге, имена которых содержат недопустимые символы и пробелы.
Пример 12-4. Удаление файла по его номеру inode
Дополнительные примеры по использованию команды find вы найдете в Пример 12-25, Пример 3-4 и Пример 10-9. В страницах справочного ркуоводства (man find) вы найдете более подробную информацию об этой достаточно сложной и мощной команде.
Команда передачи аргументов указанной команде. Она разбивает поток аргументов на отдельные составляющие и поочередно передает их заданной команде для обработки. Эта команда может рассматриваться как мощная замена обратным одиничным кавычкам. Зачастую, когда команды, заключенные в обратные одиночные кавычки, завершаются с ошибкой too many arguments (слишком много аргументов), использование xargs позволяет обойти это ограничение. Обычно, xargs считывает список аргументов со стандартного устройства ввода stdin или из канала (конвейера), но может считывать информацию и из файла.
Если команда не задана, то по-умолчанию выполняется echo. При передаче аргументов по конвейеру, xargs допускает наличие пробельных символов и символов перевода строки, которые затем автоматически отбрасываются.
ls | xargs -p -l gzip — упакует с помощью gzip все файлы в текущем каталоге, выводя запрос на подтверждение для каждого файла.
![]() |
xargs имеет очень любопытный ключ -n NN, который ограничивает количество передаваемых аргументов за один "присест" числом NN. ls | xargs -n 8 echo — выведет список файлов текущего каталога в 8 колонок. |
![]() |
Еще одна полезная опция — -0, в комбинации с find -print0 или grep -lZ позволяет обрабатывать аргументы, содержащие пробелы и кавычки. find / -type f -print0 | xargs -0 grep -liwZ GUI | xargs -0 rm -f grep -rliwZ GUI / | xargs -0 rm -f Обе вышеприведенные команды удалят все файлы, содержащие в своем имени комбинацию символов "GUI". (Спасибо S.C.) |
Пример 12-5. Использование команды xargs для мониторинга системного журнала
Пример 12-6. copydir, копирование файлов из текущего каталога в другое место.
Пример 12-7. Завершение работы процесса по его имени
Пример 12-8. Подсчет частоты встречаемости слов using xargs
Универсальный обработчик выражений: вычисляет заданное выражение (аргументы должны отделяться пробелами). Выражения могут быть арифметическими, логическими или строковыми.
возвратит 8
возвратит 2
возвратит 15
В арифметических выражениях, оператор умножения обязательно должен экранироваться обратным слэшем.
Операция инкремента переменной, то же самое, что и let y=y+1, или y=$(($y+1)). Пример подстановки арифметических выражений.
Извлекает подстроку длиной $length символов, начиная с позиции $position.
Пример 12-9. Пример работы с expr
![]() |
Вместо оператора match можно использовать оператор :. Например, команда b=`expr $a : [0-9]*` является точным эквивалентом для b=`expr match $a [0-9]*` в примере, рассмотренном выше.
|
Этот пример демонстрирует необходимость экранирования оператора группировки — \( ... \) в регулярных выражениях, при поиске по шаблону командой expr.
Perl, sed и awk имеют в своем распоряжении более мощный аппарат анализа строк. Коротенький скрипт на sed или awk, внутри сценария (см. Section 33.2) — значительно более привлекательная альтернатива использованию expr при анализе строк.
Дополнительные примеры, по обработке строк, вы найдете в Section 9.2.
Время/дата и измерение интервалов времени
Команда date без параметров выводит дату и время на стандартное устройство вывода stdout. Она становится гораздо интереснее при использовании дополнительных ключей форматирования вывода.
Пример 12-10. Команда date
Ключ -u дает UTC время (Universal Coordinated Time — время по Гринвичу).
Команда date имеет ряд дополнительных ключей форматирования вывода. Например, %N выводит долю наносекунд текущего времени. Этому ключу формата можно привести одно весьма любопытное применение — генерация шестизначных псевдослучайных целых чисел.
См. так же Пример 3-4.
Отображает время для указанной временной зоны.
Выводит подробную статистику по исполнению некоторой команды.
time ls -l / даст нечто подобное:
См. так же очень похожую команду times, обсуждавшуюся в предыдущем разделе.
![]() |
Начиная с версии 2.0 Bash, команда time стала зарезервированным словом интерпретатора, с несколько измененным поведением в конвейере. |
Утилита устанавливает время последнего обращения/изменения файла в текущее системное время или в заданное время, но так же может использоваться для создания нового пустого файла. Команда touch zzz создаст новый пустой файл с именем zzz, если перед этим файл zzz отсутствовал. Кроме того, такие пустые файлы могут использоваться для индикации, например, времени последнего изменения в проекте.
![]() |
Эквивалентом команды touch могут служить : >> newfile или >> newfile (для обычных файлов). |
Команда at — используется для запуска заданий в заданное время. В общих чертах она напоминает cron, однако, at используется для однократного запуска набора команд.
at 2pm January 15 — попросит ввести набор команд, которые необходимо запустить в указанное время. Эти команды должны быть совместимыми со сценариями командной оболочки. Ввод завершается нажатием комбинации клавиш Ctl-D.
Ключ -f или операция перенаправления ввода (<), заставляет at прочитать список команд из файла. Этот файл должен представлять из себя обычный сценарий, на языке командной оболочки и, само собой разумеется, такой сценарий должен быть неинтерактивным. Может использоваться совместно с командой run-parts для запуска различных наборов сценариев.
Команда batch, управляющая запуском заданий, напоминает команду at, но запускает список команд только тогда, когда загруженность системы упадет ниже .8. Подобно команде at, с ключом -f, может считывать набор команд из файла.
Выводит на stdout аккуратно отформатированный календарь на текущий месяц. Может выводить календарь за определенный год.
Приостанавливает исполнение сценария на заданное количество секунд, ничего не делая. Может использоваться для синхронизации процессов, запущенных в фоне, проверяя наступление ожидаемого события так часто, как это необходимо. Например, Пример 29-6.
![]() |
Команда sleep по-умолчанию принимает количество секунд, но ей можно передать и количество часов и минут и даже дней.
|
![]() |
Для запуска команд через заданные интервалы времени лучше использовать watch . |
Microsleep (здесь символ "u" должен читаться как буква греческого алфавита — "мю", или префикс микро). Это то же самое, что и sleep, только интервал времени задается в микросекундах. Может использоваться для очень тонкой синхронизации процессов.
Эта команда является частью пакета initscripts/rc-scripts в дистрибутиве Red Hat.
![]() |
Команда usleep не обеспечивает особую точность соблюдения интервалов, и поэтому она не подходит для применений, критичных ко времени. |
Команда hwclock используется для получения доступа или коррекции аппаратных часов компьютера. С некоторыми ключами требует наличия привилегий root. Сенарий /etc/rc.d/rc.sysinit использует команду hwclock для установки системного времени во время загрузки.
Команда clock — это синоним команды hwclock.
Сортирует содержимое файла, часто используется как промежуточный фильтр в конвейерах. Эта команда сортирует поток текста в порядке убывания или возрастания, в зависимости от заданных опций. Ключ -m используется для сортировки и объединения входных файлов. В странице info перечислено большое количество возможных вариантов ключей. См. Пример 10-9, Пример 10-10 и Пример A-9.
Топологическая сортировка, считывает пары строк, разделенных пробельными символами, и выполняет сортировку, в зависимости от заданного шаблона.
Удаляет повторяющиеся строки из отсортированного файла. Эту команду часто можно встретить в конвейере с командой sort.
Ключ -c выводит количество повторяющихся строк.
Команда sort INPUTFILE | uniq -c | sort -nr выводит статистику встречаемости строк в файле INPUTFILE (ключ -nr, в команде sort, означает сортировку в порядке убывания). Этот шаблон может с успехом использоваться при анализе файлов системного журнала, словарей и везде, где необходимо проанализировать лексическую структуру документа.
Пример 12-11. Частота встречаемости отдельных слов
Команда expand преобразует символы табуляции в пробелы. Часто используется в конвейерной обработке текста.
Команда unexpand преобразует пробелы в символы табуляции. Т.е. она является обратной по отношению к команде expand.
Предназначена для извлечения отдельных полей из текстовых файлов. Напоминает команду print $N в awk, но более ограничена в своих возможностях. В простейших случаях может быть неплохой заменой awk в сценариях. Особую значимость, для команды cut, представляют ключи -d (разделитель полей) и -f (номер(а) поля(ей)).
Использование команды cut для получения списка смонтированных файловых систем:
Использование команды cut для получения версии ОС и ядра:
Использование команды cut для извлечения заголовков сообщений из электронных писем:
Использование команды cut при разборе текстового файла:
cut -d ' ' -f2,3 filename эквивалентно awk -F'[ ]' '{ print $2, $3 }' filename
См. также Пример 12-36.
Используется для объединения нескольких файлов в один многоколоночный файл.
Может рассматриваться как команда, родственная команде paste. Эта мощная утилита позволяет объединять два файла по общему полю, что представляет собой упрощенную версию реляционной базы данных.
Команда join оперирует только двумя файлами и объедияет только те строки, которые имеют общее поле (обычно числовое), результат объединения выводится на stdout. Объединяемые файлы должны быть отсортированы по ключевому полю.
![]() |
На выходе ключевое поле встречается только один раз. |
Выводит начальные строки из файла на stdout (по-умолчанию — 10 строк, но это число можно задать иным). Эта команда имеет ряд интересных ключей.
Пример 12-12. Какие из файлов являются сценариями?
Пример 12-13. Генератор 10-значных случайных чисел
Выводит последние строки из файла на stdout (по-умолчанию — 10 строк). Обычно используется для мониторинга системных журналов. Ключ -f, позволяет вести непрерывное наблюдение за добавляемыми строками в файл.
Пример 12-14. Мониторинг системного журнала с помощью tail
См. также Пример 12-5, Пример 12-33 и Пример 29-6.
Многоцелевая поисковая утилита, использующая регулярные выражения. Изначально это была команда в древнем строчном редакторе ed, g/re/p, что означает — global - regular expression - print.
grep pattern [file...]
Поиск участков текста в файле(ах), соответствующих шаблону pattern, где pattern может быть как обычной строкой, так и регулярным выражением.Если файл(ы) для поиска не задан, то команда grep работает как фильтр для устройства stdout, например в конвейере.
-i — выполняется поиск без учета регистра символов.
-w — поиск совпадений целого слова.
-l — вывод только имен файлов, в которых найдены участки, совпадающие с заданным образцом/шаблоном, без вывода совпадающих строк.
-r — (рекурсивный поиск) поиск выполняется в текущем каталоге и всех вложенных подкаталогах.
The -n option lists the matching lines, together with line numbers.
-v (или --invert-match) — выводит только строки, не содержащие совпадений.
-c (--count) — выводит количество совпадений без вывода самих совпадений.
Если grep вызывается для поиска по группе файлов, то вывод будет содержать указание на имена файлов, в которых найдены совпадения.
![]() |
Для того, чтобы заставить grep выводить имя файла, когда поиск производится по одному-единственному файлу, достаточно указать устройство /dev/null в качестве второго файла.
|
Если совпадение было найдено, то grep возвращает код завершения — 0, это может оказаться полезным при выполнении поиска в условных операторах ( в таких случаях особый интерес может представлять ключ -q, который подавляет вывод).
Пример 29-6 — пример поиска заданного образца в системном журнале, с помощью grep.
Пример 12-15. Сценарий-эмулятор "grep"
![]() |
egrep — то же самое, что и grep -E. Эта команда использует несколько отличающийся, расширенный набор регулярных выражений, что позволяет выполнять поиск более гибко. fgrep — то же самое, что и grep -F. Эта команда выполняет поиск строк символов (не регулярных выражений), что несколько увеличивает скорость поиска. Утилита agrep имеет более широкие возможности поиска приблизительных совпадений. Образец поиска может отличаться от найденой строки на указанное число символов. |
![]() |
Для поиска по сжатым файлам следует использовать утилиты zgrep, zegrep или zfgrep. Они с успехом могут использоваться и для не сжатых файлов, но в этом случае они уступают в скорости обычным grep, egrep и fgrep. Они очень удобны при выполнении поиска по смешенному набору файлов — когда одни файлы сжаты, а другие нет. Для поиска по bzip-файлам используйте bzgrep. |
Команда look очень похожа на grep, и предназначена для поиска по "словарям" — отсортированным файлам. По-умолчанию, поиск выполняется в файле /usr/dict/words, но может быть указан и другой словарь.
Пример 12-16. Поиск слов в словаре
Скриптовые языки, специально разработанные для анализа текстовых данных.
Неинтерактивный "потоковый редактор". Широко используется в сценариях на языке командной оболочки.
Утилита контекстного поиска и преобразования текста, замечательный инструмент для извлечения и/или обработки полей (колонок) в структурированных текстовых файлах. Синтаксис awk напоминает язык C.
wc — "word count", счетчик слов в файле или в потоке:
wc -w подсчитывает только слова.
wc -l подсчитывает только строки.
wc -c подсчитывает только символы.
wc -L возвращает длину наибольшей строки.
Подсчет количества .txt-файлов в текущем каталоге с помощью wc:
Подсчет общего размера файлов, чьи имена начинаются с символов, в диапазоне d - h
От переводчика: в случае, если у вас локаль отлична от "C", то вышеприведенная команда может не дать результата, поскольку wc вернет не слово "total", в конце вывода, а "итого". Тогда можно попробовать несколько измененный вариант:
Использование wc для подсчета количества вхождений слова "Linux" в основной исходный файл с текстом этого руководства.
См. также Пример 12-33 и Пример 16-7.
Отдельные команды располагают функциональностью wc в виде своих ключей.
Замена одних символов на другие.
![]() |
В отдельных случаях символы необходимо заключать в кавычки и/или квадратные скобки. Кавычки предотвращают интерпретацию специальных символов командной оболочкой. Квадратные скобки должны заключаться в кавычки. |
Команда tr "A-Z" "*" <filename или tr A-Z \* <filename заменяет все символы верхнего регистра в filename на звездочки (вывод производится на stdout). В некоторых системах этот вариант может оказаться неработоспособным, тогда попробуйте tr A-Z '[**]'.
Ключ -d удаляет символы из заданного диапазона.
Ключ --squeeze-repeats (-s) удалит все повторяющиеся последовательности символов. Может использоваться для удаления лишних пробельных символов.
Ключ -c "complement" заменит символы в соответствии с шаблоном. Этот ключ воздействует только на те символы, которые НЕ соответствуют заданному шаблону.
Обратите внимание: команда tr корректно распознает символьные классы POSIX. [29]
Пример 12-17. toupper: Преобразование символов в верхний регистр.
Пример 12-18. lowercase: Изменение имен всех файлов в текущем каталоге в нижний регистр.
Пример 12-19. du: Преобразование текстового файла из формата DOS в формат Unix.
Пример 12-20. rot13: Сверхслабое шифрование по алгоритму rot13.
Пример 12-21. Более "сложный" шифр
Выравнивает текст по ширине, разрывая, если это необходимо, слова. Особый интерес представляет ключ -s, который производит перенос строк по пробелам, стараясь не разрывать слова. (см. Пример 12-22 и Пример A-2).
Очень простая утилита форматирования текста, чаще всего используемая как фильтр в конвейерах для того, чтобы выполнить "перенос" длинных строк текста.
Пример 12-22. Отформатированный список файлов.
См. также Пример 12-5.
![]() |
Очень мощной альтернативой утилите fmt, является утилита par (автор Kamil Toman), которую вы сможете найти на http://www.cs.berkeley.edu/~amc/Par/. |
Эта утилита с обманчивым названием удаляет из входного потока символы обратной подачи бумаги (код ESC 7). Она так же пытается заменить пробелы на табуляции. Основная область применения утилиты col — фильтрация вывода отдельных утилит обработки текста, таких как groff и tbl.
Форматирование по столбцам. Эта утилита преобразует текст, например какой либо список, в табличное, более "удобочитаемое", представление, вставляя символы табуляции по мере необходимости.
Пример 12-23. Пример форматирования списка файлов в каталоге
Утилита удаления колонок. Удаляет колонки (столбцы) сиволов из файла и выводит результат на stdout. colrm 2 4 <filename — удалит символы со 2-го по 4-й включительно, в каждой строке в файле filename.
![]() |
Если файл содержит символы табуляции или непечатаемые символы, то результат может получиться самым неожиданным. В таких случаях, как правило, утилиту colrm, в конвейере, окружают командами expand и unexpand. |
Нумерует строки в файле. nl filename — выведет файл filename на stdout, и в начале каждой строки вставит ее порядковый номер, счет начинается с первой непустой строки. Если файл не указывается, то принимается ввод со stdin.
Вывод команды nl очень напоминает cat -n, однако, по-умолчанию nl не нумерует пустые строки.
Пример 12-24. nl: Самонумерующийся сценарий.
Подготовка файла к печати. Утилита производит разбивку файла на страницы, приводя его в вид пригодный для печати или для вывода на экран. Разнообразные ключи позволяют выполнять различные манипуляции над строками и колонками, соединять строки, устанавливать поля, нумеровать строки, добавлять колонтитулы и многое, многое другое. Утилита pr соединяет в себе функциональность таких команд, как nl, paste, fold, column и expand.
pr -o 5 --width=65 fileZZZ | more — выдаст хорошо оформленное и разбитое на страницы содержимое файла fileZZZ.
Хочу особо отметить ключ -d, который выводит строки с двойным интервалом (тот же эффект, что и sed -G).
GNU утилита, предназначена для нужд локализации и перевода сообщений программ, выводимых на экран, на язык пользователя. Не смотря на то, что это актуально, прежде всего, для программ на языке C, тем не менее gettext с успехом может использоваться в сценариях командной оболочки для тех же целей. См. info page.
Эта утилита предназначена для создания двоичных файлов с переводом сообщений, выводимых перед пользователем. Используется для нужд локализации.
Утилита преобразования текста из одной кодировки в другую. В основном используется для нужд локализации.
Может рассматриваться как разновилность утилиты iconv, описанной выше. Универсальная утилита для преобразования текстовой информации в различные кодировки.
TeX и Postscript — языки разметки текста, используемые для подготовки текста к печати или выводу на экран.
TeX — это сложная система подготовки к печати, разработанная Дональдом Кнутом (Donald Knuth). Эту утилиту удобнее использовать внутри сценария, чем в командной строке, поскольку в сценарии проще один раз записать все необходимые параметры, передаваемые утилите, для получения необходимого результата.
Ghostscript (gs) — это GPL-версия интерпретатора Postscript.
groff — это еще один язык разметки текста и форматированного вывода. Является расширенной GNU-версией пакета roff/troff в Unix-системах.
tbl — утилита обработки таблиц, должна рассматриваться как составная часть groff, так как ее задачей является преобразование таблиц в команды groff.
eqn — утилита преобразования математических выражений в команды groff.
lex — утилита лексического разбора текста. В Linux-системах заменена на свободно распространяемую утилиту flex.
yacc — утилита для создания синтаксических анализаторов, на основе набора грамматик, задаваемых разработчиком. В Linux-системах, эта утилита заменена на свободно распространяемую утилиту bison.
[29] Это верно только для GNU-версии команды tr, поведение этой команды, в коммерческих Unix-системах, может несколько отличаться.
Стандартная, для Unix, утилита архивирования. Первоначально — это была программа Tape ARchiving, которая впоследствии переросла в универсальный пакет, который может работать с любыми типами устройств (см. Пример 3-4). В GNU-версию tar была добавлена возможность одновременно производить сжатие tar-архива, например команда tar czvf archive_name.tar.gz * создает tar-архив дерева подкаталогов и вызывает gzip для выполнения сжатия, исключение составляют скрытые файлы в текущем каталоге ($PWD). [30]
Некоторые, часто используемые, ключи команды tar:
-c — создать (create) новый архив
-x — извлечь (extract) файлы из архива
--delete — удалить (delete) файлы из архива
![]() |
Этот ключ игнорируется для накопителей на магнитной ленте. |
-r — добавить (append) файлы в существующий архив
-A — добавить (append) tar-файлы в существующий архив
-t — список файлов в архиве (содержимое архива)
-u — обновить (update) архив
-d — операция сравнения архива с заданной файловой системой
-z — обработка архива с помощью gzip
(Сжатие или разжатие, в зависимости от комбинации сопутствующих ключей -c или -x)
-j — обработка архива с помошью bzip2
![]() |
При восстановлении "битых" tar.gz архивов могут возникнуть определенные сложности, поэтому делайте несколько резервных копий. |
Утилита создания shell-архива. Архивируемые файлы объединяются в единый файл без выполнения сжатия, в результате получается архив — по сути полноценный сценарий на языке командной оболочки, начинающийся со строки #!/bin/sh, который содержит полный набор команд, необходимый для разархивирования. Такого рода архивы до сих пор можно найти в некоторых телеконференциях в Internet, но в последнее время они активно вытесняются связкой tar/gzip. Для распаковки shar-архивов предназначена команда unshar.
Утилита создания и обслуживания архивов, главным образом применяется к двоичным файлам библиотек.
Red Hat Package Manager, или rpm — набор утилит, предназначенных для построения и обслуживания пакетов программного обеспечения как в исходном коде, так и в собранном (откомпилированном) виде. Среди всего прочего, включает в себя утилиты, производящие установку ПО, проверку зависимостей пакетов и проверку их целостности.
Самый простой вариант установки ПО из rpm — выполнить команду rpm -i package_name.rpm.
![]() |
Команда rpm -qa выдаст полный список всех установленных rpm-пакетов в данной системе. Команда rpm -qa package_name выведет только пакет(ы) с именем, содержащим комбинацию символов package_name.
|
Специализированная утилита архивации и копирования (copy input and output). Используется все реже и реже, поскольку вытесняется более мощным архиватором tar/gzip. Наиболее употребительна для таких операций, как перемещение дерева каталогов.
Пример 12-25. Пример перемещения дерева каталогов с помощью cpio
Эта утилита конвертирует rpm-пакет в архив cpio.
Пример 12-26. Распаковка архива rpm
Стандартная GNU/Unix утилита сжатия, заменившая более слабую, и к тому же проприетарную, утилиту compress. Соответствующая утилита декомпрессии (разжатия) — gunzip, которая является эквивалентом команды gzip -d.
Для работы со сжатыми файлами в конвейере используется фильтр zcat, который выводит результат своей работы на stdout, допускает перенаправление вывода. Фактически это та же команда cat, только приспособленная для работы со сжатыми файлами (включая файлы, сжатые утилитой compress). Эквивалент команды zcat — gzip -dc.
![]() |
В некоторых коммерческих версиях Unix, команда zcat является синонимом команды uncompress -c, и не может работать с файлами, сжатыми с помощью gzip. |
См. также Пример 7-7.
Альтернативная утилита сжатия, обычно дает более высокую степень сжатия (но при этом работает медленнее), чем gzip, особенно это проявляется на больших файлах. Соответствующая утилита декомпрессии — bunzip2.
![]() |
В современные версии tar добавлена поддержка bzip2. |
Устаревшие проприетарные утилиты для работы с архивами, входящие в состав некоторых коммерческих дистрибутивов Unix. В последнее время вытесняются более мощной утилитой gzip. Linux-дистрибутивы, как правило, включают в свой состав эти утилиты для обратной совместимости, однако gunzip корректно разархивирует файлы, обработанные с помощью compress.
![]() |
Утилита znew предназначена для преобразования compress-архивов в gzip-архивы. |
Еще одна утилита-фильтр сжатия, которая обслуживает только отсортированные списки слов. Использует стандартный, для фильтров, синтаксис вызова — sq < input-file > output-file. Быстрая, но не такая эффективная как gzip. Соответствующая ей утилита декомпрессии называется unsq, синтаксис вызова аналогичен утилите sq.
![]() |
Вывод от sq может быть передан по конвейеру утилите gzip, для дальнейшего сжатия. |
Кроссплатформенная утилита архивирования и сжатия, совместимая, по формату архивного файла, с утилитой DOS — pkzip.exe. "Zip"-архивы, по-моему, более приемлемый вариант для обмена данными через Internet, чем "tarballs" (тарболлы, или tar-архивы).
Этот набор утилит предназначен для распаковки архивов, созданных с помощью DOS архиваторов — arc.exe, arj.exe и rar.exe.
Утилита идентификации файлов. Команда file file-name верне тип файла file-name, например, ascii text или data. Для этого она анализирует сигнатуру, или магическое число и сопоставляет ее со списком известных сигнатур из /usr/share/magic, /etc/magic или /usr/lib/magic (в зависимости от дистрибутива Linux/Unix).
-f — ключ пакетного режима работы утилиты file, в этом случае утилита принимает список анализируемых имен файлов из заданного файла. Ключ -z используется для анализа файлов в архиве.
Пример 12-27. Удаление комментариев из файла с текстом программы на языке C
Команда which command-xxx вернет полный путь к "command-xxx". Очень полезна для того, чтобы узнать — установлена ли та или иная утилита в системе.
$bash which rm
Очень похожа на which, упоминавшуюся выше. Команда whereis command-xxx вернет полный путь к "command-xxx", но кроме того, еще и путь к manpage — файлу, странице справочника по заданной утилите.
$bash whereis rm
Утилита whatis filexxx отыщет "filexxx" в своей базе данных. Может рассматриваться как упрощенный вариант команды man.
$bash whatis whatis
Пример 12-28. Исследование каталога /usr/X11R6/bin
См. также Пример 10-3.
Вывод списка файлов в каталоге. Тот же эффект имеет команда ls -l.
Это одна из утилит GNU fileutils.
Команда locate определяет местонахождение файла, используя свою базу данных, создаваемую специально для этих целей. Команда slocate — это защищенная версия locate (которая может оказаться простым псевдонимом команды slocate).
$bash locate hickson
Возвращает имя файла, на который указывает символическая ссылка.
Команда strings используется для поиска печатаемых строк в двоичных файлах. Она выводит последовательности печатаемых символов, обнаруженных в заданном файле. Может использоваться для прикидочного анализа дамп-файлов (core dump) или для отыскания информации о типе файла, например для графических файлов неизвестного формата (например, strings image-file | more может вывести такую строчку: JFIF, что говорит о том, что мы имеем дело с графическим файлом в формате jpeg). В сценариях, вероятнее всего, вам придется использовать эту команду в связке с grep или sed. См. Пример 10-7 и Пример 10-9.
Пример 12-29. "Расширенная" команда strings
diff: очень гибкая утилита сравнения файлов. Она выполняет построчное сравнение файлов. В отдельных случаях, таких как поиск по словарю, может оказаться полезной фильтрация файлов с помощью sort и uniq перед тем как отдать поток данных через конвейер утилите diff. diff file-1 file-2 — выведет строки, имеющие отличия, указывая — какому файлу, какая строка принадлежит.
С ключом --side-by-side, команда diff выведет сравниваемые файлы в две колонки, с указанием несовпадающих строк. Ключи -c и -u так же служат для облегчения интерпретации результатов работы diff.
Существует ряд интерфейсных оболочек для утилиты diff, среди них можно назвать: spiff, wdiff, xdiff и mgdiff.
![]() |
Команда diff возвращает код завершения 0, если сравниваемые файлы идентичны и 1, если они отличаются. Это позволяет использовать diff в условных операторах внутри сценариев на языке командной оболочки (см. ниже). |
В общем случае, diff используется для генерации файла различий, который используется как аргумент команды patch. Ключ -e отвечает за вывод файла различий в формате, пригодном для использования с ed или ex.
patch: гибкая утилита для "наложения заплат". С помощью файла различий, сгенерированного утилитой diff, утилита patch может использоваться для обновления устаревших версий файлов. Это позволяет распространять относительно небольшие "diff"-файлы вместо целых пакетов. Распространение "заплат" к ядру стало наиболее предпочтительным методом распространения более новых версий ядра Linux.
Наложение "заплат" на ядро:
![]() |
Кроме того, утилита diff в состоянии выполнять рекурсивный обход каталогов.
|
![]() |
Утилита zdiff сравнивает сжатые, с помощью gzip, файлы. |
Расширенная версия diff, которая сравнивает сразу 3 файла. В случае успеха возвращает 0, но, к сожалению, не дает никакой информации о результатах сравнения.
Сравнение и/или редактирование двух файлов перед объединением их в один файл. Это интерактивная утилита, по своей природе, и из-за этого она довольно редко используется в сценариях.
Утилита cmp — это упрощенная версия diff. В то время, как diff выводит подробную информацию об имеющихся различиях, утилита cmp лишь показывет номер строки и позицию в строке, где было встречено различие.
![]() |
Подобно команде diff, команда cmp возвращает код завершения 0, если файлы идентичны и 1, если они различны. Это позволяет использовать команду cmp в условных операторах. |
Пример 12-30. Пример сравнения двух файлов с помощью cmp.
![]() |
Для работы с gzip файлами используется утилита zcmp. |
Универсальная утилита сравнения. Работает с отсортированными файлами.
comm -options first-file second-file
comm file-1 file-2 — вывод в три колонки:
колонка 1 = уникальные строки для file-1
колонка 2 = уникальные строки для file-2
колонка 3 = одинаковые строки.
Ключи, подавляющие вывод в одной или более колонках.
-1 — подавление вывода в колонку 1
-2 — подавление вывода в колонку 2
-3 — подавление вывода в колонку 3
-12 — подавление вывода в колонки 1 и 2, и т.д.
Выводит только название файла, без каталога размещения. Конструкция basename $0 — позволяет сценарию узнать свое имя, то есть имя файла, который был запущен. Это имя может быть использовано для вывода сообщений, напрмиер:
Отсекает basename от полного имени файла и выводит только путь к файлу.
![]() |
Утилитам basename и dirname может быть передана любая строка, в качестве аргумента. Этот аргумент необязательно должен быть именем существующего файла (см. Пример A-8). |
Пример 12-31. Утилиты basename и dirname
Утилита разбивает файл на несколько частей. Обычно используется для разбиения больших файлов, чтобы их можно было записать на дискеты или передать по электронной почте по частям.
Эти утилиты предназначены для вычисления контрольных сумм. Контрольная сумма — это некоторое число, вычисляемое исходя из содержимого файла, и служит для контроля целостности информации в файле. Сценарий может выполнять проверку контрольных сумм для того, чтобы убедиться, что файл не был изменен или поврежден. Для большей безопасности, рекомендуется использовать 128-битную сумму, генерируемую утилитой md5sum (message digest checksum).
Обратите внимание: утилита cksum выводит контрольную сумму и размер файла в байтах.
Пример 12-32. Проверка целостности файла
Более творческий подход к использованию md5sum вы нйдете в Пример A-21.
Надежное, с точки зрения безопасности, стирание файла, посредством предварительной, многократной записи в файл случайной информации, перед тем как удалить его. Эта команда имеет тот же эффект, что и Пример 12-45, но делает это более изящным и безопасным способом.
Является составной частью пакета GNU fileutils.
![]() |
Имеется ряд технологий, с помощью которых все-таки возможно восстановить файлы, удаленные утилитой shred. |
Эта утилита используется для кодирования двоичных файлов в символы ASCII, после такого кодирования файлы могут, с достаточной степенью безопасности, передаваться по сети, вкладываться в электронные письма и т.п..
Утилита декодирования файлов, прошедших обработку утилитой uuencode.
Пример 12-33. Декодирование файлов
![]() |
При декодировании и выводе длинных текстовых сообщений из новостных групп Usenet, очень нелишним будет передать текст, по конвейеру, команде fold -s. |
Утилиты mimencode и mmencode предназначены для обработки закодированных мультимедийных вложений в электронные письма. Хотя почтовые программы (такие как pine или kmail) имеют возможность автоматической обработки таких вложений, тем не менее эти утилиты позволяют обрабатывать вложения вручную, из командной строки или в пакетном режиме, из сценария на языке командной оболочки.
Одно время, это была стандартная, для Unix, утилита шифрования файлов. [31] Политически мотивированные, правительственные постановления ряда стран, напрямую запрещают экспорт программного обеспечения для шифрования, что, в результате, привело практически к полному исчезновению crypt из большинства Unix-систем (в том числе и Linux). К счастью, программистами было разработано множество вполне приличных альтернатив, и среди них cruft (см. Пример A-5).
Создает временный файл с "уникальным" именем.
Утилита для компиляции и сборки программ. Но может использоваться для выполнения любых других операций, основанных на анализе наличия изменений в исходных файлах.
Команда make использует в своей работе Makefile, который содержит перечень зависимостей и операций, которые необходимо выполнить для удовлетворения этих зависимостей.
Своего рода — утилита копирования файлов, похожа на cp, но дополнительно позволяет изменять права доступа и атрибуты копируемых файлов. Напрямую эта команда практически не используется, чаще всего она встречается в Makefile (в разделе make install :). Она может использоваться в сценариях установки ПО.
Автор утилиты — Benjamin Lin со-товарищи. Предназначена для преобразования текстовых файлов из формата DOS (в котором строки завершаются комбинацией символов CR-LF) в формат Unix (в котором строки завершаются одним символом LF) и обратно.
Команда ptx [targetfile] выводит a упорядоченный предметный указатель для targetfile, который можно обработать, по мере необходимости, какой либо утилитой форматирования, в конвейере.
Команды постраничного просмотра текстовых файлов или потоков на stdout. Могут использоваться в сценариях в качестве фильтров.
[30] Команда tar czvf archive_name.tar.gz * включит в архив все скрытые файлы (имена которых начинаются с точки) из вложенных подкаталогов. Это недокументированная "особенность" GNU-версии tar.
[31] Она реализует алгоритм симметричного блочного шифрования, в противоположность алгоритмам шифрования с "открытым ключом", из которых широко известен pgp.
Команды, описываемые в этом разделе, могут найти применение при исследовании и анализе процессов передачи данных по сети, а также могут использоваться в борьбе со спамерами.
Возвращает информацию об узле Интернета, по заданному имени или IP адресу, выполняя поиск с помощью службы DNS.
Выводит информацию о заданном узле сети. С ключом -h, ipcalc выполняет поиск имени хоста в DNS, по заданному IP адресу.
Выполняет "поиск имени узла" Интернета по заданному IP адресу. По сути, эквивалентна командам ipcalc -h и dig -x. Команда может исполняться как в интерактивном, так и в неинтерактивном режиме, т.е. в пределах сценария.
Подобно команде nslookup, выполняет "поиск имени узла" в Интернете.
Сравните вывод команды dig -x с выводом команд ipcalc -h и nslookup.
Утилита предназначена для исследования топологии сети посредством передачи ICMP пакетов удаленному узлу. Эта программа может работать в LAN, WAN и в Интернет. Удаленный узел может быть указан как по имени, так и по IP адресу. Вывод команды traceroute может быть передан по конвейеру утилитам grep или sed, для дальнейшего анализа.
Выполняет передачу пакета "ICMP ECHO_REQUEST" другой системе в сети. Чаще всего служит в качестве инструмента диагностики соединений, должна использоваться с большой осторожностью.
В случае успеха, ping возвращает код завершения 0, поэтому команда ping может использоваться в условных операторах.
Выполняет поиск в DNS (Domain Name System). Ключом -h можно указать какой из whois серверов будет запрошен. См. Пример 4-6.
Возвращает информацию о пользователях в сети. По желанию, эта команда может выводить содержимое файлов ~/.plan, ~/.project и ~/.forward, указанного пользователя.
По соображениям безопасности, в большинстве сетей служба finger, и соответствующий демон, отключена. [32]
Изменяет некоторые сведения о пользователе, такие как: полное имя, номер кабинета, телефон рабочий и домашний. Которые обычно выводятся командой finger.
Проверка адреса электронной почты.
Команды sx и rx служат для приема/передачи файлов на/из удаленный узел в сети, по протоколу xmodem. Входят в состав пакета minicom.
Команды sz и rz служат для приема/передачи файлов на/из удаленный узел в сети, по протоколу zmodem. Протокол zmodem имеет некоторые преимущества перед протоколом xmodem, в качестве такого преимущества можно назвать более высокую скорость передачи и возможность возобновления передачи, в случае ее разрыва. Входят в состав пакета minicom.
Под этим именем подразумевается утилита и протокол передачи файлов. Сеансы ftp могут устанавливаться из сценариев (см. Пример 17-6, Пример A-5 и Пример A-14).
Unix to Unix copy. Это коммуникационный пакет для передачи файлов между Unix серверами. Сценарий на языке командной оболочки — один из самых эффективных способов автоматизации такого обмена.
Похоже, что с появлением Интернет и электронной почты, uucp постепенно уходит в небытие, однако, она с успехом может использоваться в изолированных, не имеющих выхода в Интернет, сетях.
Call Up — выполняет соединение с удаленной системой, как простой терминал. Эта команда является частью пакета uucp и, своего рода, упрощенным вариантом команды telnet.
Утилита и протокол для подключения к удаленной системе.
![]() |
Протокол telnet небезопасен по своей природе, поэтому следует воздерживаться от его использования. |
wget — неинтерактивная утилита для скачивания файлов с Web или ftp сайтов.
lynx — Web браузер, внутри сценариев (с ключом -dump) может использоваться для скачивания файлов с Web или ftp сайтов, в неинтерактивном режиме.
Remote login — инициирует сессию с удаленной системой. Эта команда небезопасна, вместо нее лучше использовать ssh.
Remote shell — исполняет команду на удаленной системе. Эта команда небезопасна, вместо нее лучше использовать ssh.
Remote copy — копирование файлов между двумя машинами через сеть. Подобно прочим r* утилитам, команда rcp небезопасна и потому, использовать ее в сценариях нежелательно. В качестве замены можно порекомендовать ssh или expect.
Secure shell — устанавливает сеанс связи и выполняет команды на удаленной системе. Выступает в качестве защищенной замены для telnet, rlogin, rcp и rsh. Использует идентификацию, аутентификацию и шифрование информации, передаваемой через сеть. Подробности вы найдете в man ssh.
Эта утилита позволяет передать текст сообщения на другой терминал (console или xterm). Разрешить или запретить доступ к терминалу можно с помощью команды mesg.
Поскольку команда write работает в интерактивном режиме, то, как правило, она не употребляется в сценариях.
Чтение или передача электронной почты.
Этот почтовый клиент командной строки с успехом может использоваться в сценариях.
Пример 12-34. Сценарий, отправляющий себя самого по электронной почте
Команда mailto, похожа на mail, она также отправляет сообщения по электронной почте. Однако, кроме этого, mailto позволяет отправлять MIME (multimedia) сообщения.
Эта утилита предназначена для автоматической передачи ответов на электронные письма, например для того, чтобы уведомить отправителя о том, что получатель временно отсутствует. Работает совместно с sendmail и не может использоваться для передачи сообщений через коммутируемые линии (по модему).
Команды, имеющие отношение к консоли или терминалу
инициализация терминала или выполнение запроса к базе данных терминалов terminfo. С помощью tput можно выполнять различные операции. tput clear — эквивалентно команде clear. tput reset — эквивалентно команде reset. tput sgr0 — так же сбрасывет настройки терминал, но без очистки экрана.
Команда tput cup X Y перемещает курсор в координаты (X,Y). Обычно этой команде предшествует clear, очищающая экран.
Обратите внимание: stty предлагает более широкий диапазон возможностей.
Cравнение или печать информации о характеристиках терминалов, хранящейся в базе данных terminfo.
Сбрасывает настройки терминала и очищает экран. Как и в случае команды clear, курсор и приглашение к вводу (prompt) выводятся в верхнем левом углу терминала.
Команда clear просто очищает экран терминала или окно xterm. Курсор и приглашение к вводу (prompt) выводятся в верхнем левом углу терминала. Эта команда может запускаться как из командной строки, так и из сценария. См. Пример 10-25.
Эта утилита позволяет сохранять в файле все символы, введенные пользователем c клавиатуры (вывод тоже). Получая, фактически, подробнейший синхронный протокол сессии.
Разложение целого числа на простые множители.
Bash не в состоянии выполнять действия над числами с плавающей запятой и не содержит многих важных математических функций. К счастью существует bc.
Универсальная, выполняющая вычисления с произвольной точностью, утилита bc обладает некоторыми возможностями, характерными для языков программирования.
Синтаксис bc немного напоминает язык C.
Поскольку это утилита Unix, то она может достаточно широко использоваться в сценариях на языке командной оболочки, в том числе и в конвейерной обработке данных.
Ниже приводится простой шаблон работы с утилитой bc в сценарии. Здесь используется прием подстановки команд.
Пример 12-35. Ежемесячные выплаты по займу
Пример 12-36. Перевод чисел из одной системы счисления в другую
Один из вариантов вызова bc — использование вложенного документа, внедряемого в блок с подстановкой команд. Это особенно актуально, когда сценарий должен передать bc значительный по объему список команд и аргументов.
Пример 12-37. Пример взаимодействия bc со "встроенным документом"
Пример 12-38. Вычисление числа "пи"
Утилита dc (desk calculator) — это калькулятор, использующий "Обратную Польскую Нотацию", и ориентированный на работу со стеком.
Многие стараются избегать испоьзования dc, из-за непривычной формы записи операндов и операций. Однако, dc имеет и своих сторонников.
Пример 12-39. Преобразование чисел из десятичной в шестнадцатиричную систему счисления
Изучение страниц info dc позволит детальнее разобраться с утилитой. Однако, отряд "гуру", которые могут похвастать своим знанием этой мощной, но весьма запутанной утилиты, весьма немногочислен.
Пример 12-40. Разложение числа на простые множители
Еще один способ выполнения математических операций, над числами с плавающей запятой, состоит в создании сценария-обертки, использующего математические функции awk.
Пример 12-41. Расчет гипотенузы прямоугольного треугольника
Команды, которые нельзя отнести ни к одной из вышеперечисленных категорий
Эти утилиты выводят последовательность целых чисел с шагом, заданным пользователем.
По-умолчанию, выводимые числа отделяются друг от друга символом перевода строки, однако, с помощью ключа -s может быть задан другой разделитель.
Обе утилиты, и jot, и seq, очень удобно использовать для генерации списка аргументов в цикле for.
Пример 12-42. Использование seq для генерации списка аргументов цикла for
Команда getopt служит для разбора командной строки, выделяя из нее ключи — символы, с предшествующим символом дефиса. Этой утилите имеется, встроенный в Bash, аналог — getopts, более мощная и универсальная команда. Тем не менее, команда getopt, с ключом -l, позволяет производить разбор "длинных" ключей и допускает переупорядочивание ключей.
Пример 12-43. Использование getopt для разбора аргументов командной строки
Команда run-parts [33] запускает на исполнение все сценарии, в порядке возрастания имен файлов-сценариев, в заданном каталоге. Естественно, файлы сценариев должны иметь права на исполнение.
Демон cron вызывает run-parts для запуска сценариев из каталогов /etc/cron.*.
По-умолчанию, команда yes выводит на stdout непрерывную последовательность символов y, разделенных символами перевода строки. Исполнение команды можно прервать комбинацией клавиш control-c. Команду yes можно заставить выводить иную последовательность символов. Теперь самое время задаться вопросом о практической пользе этой команды. Основное применение этой команды состоит в том, что вывод от нее может быть передан, через конвейер, другой команде, ожидающей реакции пользователя. В результате получается, своего рода, слабенькая версия команды expect.
yes | fsck /dev/hda1 запускает fsck в неинтерактивном режиме (будьте осторожны!).
yes | rm -r dirname имеет тот же эффект, что и rm -rf dirname (будьте осторожны!).
Печатает на stdout заданную строку символов (не более 10), рисуя каждый символ строки при помощи символа '#'. Вывод от команды может быть перенаправлен на принтер.
Выводит все переменные окружения текущего пользователя.
Команды lp и lpr отправляют файлы в очередь печати [34] для вывода на принтер. Названия этих команд произошли от "line printers".
bash$ lp file1.txt или bash lp <file1.txt
Очень часто используются в комбинации с командой форматированного вывода pr.
bash$ pr -options file1.txt | lp
Программы подготовки текста к печати, такие как groff и Ghostscript, так же могут напрямую взаимодействовать с lp.
bash$ groff -Tascii file.tr | lp
bash$ gs -options | lp file.ps
Команда lpq предназначена для просмотра очереди заданий печати, а lprm — для удаления заданий из очереди.
[Unix заимствовал эту идею из водопроводного дела.]
Это опрератор перенаправления, но с некоторыми особенностями. Подобно водопроводным трубам, "tee" позволяет "направить поток" данных в несколько файлов и на stdout одновременно, никак не влияя на сами данные. Эта команда может оказаться очень полезной при отладке.
Эта, редко встречающаяся, команда создает именованный канал - очередь, через который производится обмен данными между процессами. [35] Как правило, один процесс записывает данные в очередь (FIFO), а другой читает данные из очереди. См. Пример A-17.
Производит проверку полного имени файла — проверяет, доступны ли на чтение, каталоги в пути к файлу, и не превышает ли длина полного имени файла 255 символов. При несоблюдении одного из условий — возвращает сообщение об ошибке.
К сожалению, pathchk не возвращает соответствующего кода ошибки, и потому, в общем-то, бесполезна в сценариях. Вместо нее лучше использовать операторы проверки файлов.
Эта немного непонятная и "страшная" команда ("data duplicator") изначально использовалась для переноса данных на магнитной ленте между микрокомпьютерами с ОС Unix и майнфреймами IBM. Команда dd просто создает копию файла (или stdin/stdout), выполняя по пути некоторые преобразования. Один из вариантов: преобразование из ASCII в EBCDIC, [36] dd --help выведет список возможных вариантов преобразований и опций этой мощной утилиты.
Для демонстрации возможностей dd, попробуем перехватить нажатия на клавиши.
Пример 12-44. Захват нажатых клавиш
Команда dd имеет возможность произвольного доступа к данным в потоке.
Команда dd может использоваться для создания образов дисков, считывая данные прямо с устройств, таких как дискеты, компакт диски, магнитные ленты (Пример A-6). Обычно она используется для создания загрузочных дискет.
dd if=kernel-image of=/dev/fd0H1440
Точно так же, dd может скопировать все содержимое дискеты, даже с неизвестной файловой системой, на жесткий диск в виде файла-образа.
dd if=/dev/fd0 of=/home/bozo/projects/floppy.img
Еще одно применение dd — создание временного swap-файла (Пример 28-2) и ram-дисков (Пример 28-3). Она может создавать даже образы целых разделов жесткого диска, хотя и не рекомендуется делать это без особой на то необходимости.
Многие (которые, вероятно, не знают чем себя занять) постоянно придумывают все новые и новые области применения команды dd.
Пример 12-45. Надежное удаление файла
Команда od (octal dump) производит преобразование ввода (или файла) в один или несколько форматов, в соответствии с указанными опциями. При отсутствии опций используется восьмеричный формат (опция -o). Эта команда полезна при просмотре или обработке файлов с двоичными данными, например /dev/urandom. См. Пример 9-27 и Пример 12-13.
Выводит дамп двоичных данных из файла в восьмеричном, шестнадцатиричном, десятичном виде или в виде ASCII. Эту команду, с массой оговорок, можно назвать эквивалентом команды of od.
Отображает сведения об исполняемом или объектном файле либо в шестнадцатиричной форме, либо в виде дизассемблерного листинга (с ключом -d).
Эта команда создает псевдослучайные шестнадцатиричные 128-битные числа, так называемые "magic cookie", обычно используется X-сервером в качестве "сигнатуры" авторизации. В сценариях может использоваться как малоэффективный генератор случайных чисел.
Конечно, для тех же целей, сценарий может использовать md5.
С помощью mcookie можно создавать "уникальные" имена файлов.
Пример 12-46. Генератор имен файлов
Эта утилита производит преобразование величин из одних единиц измерения в другие. Как правило вызывается в интерактивном режиме, ниже приводится пример использования units в сценарии.
Пример 12-47. Преобразование метров в мили
Не команда, а клад, m4 — это мощный фильтр обработки макроопределений, [37] фактически — целый язык программирования. Изначально создававшаяся как препроцессор для RatFor, m4 оказалась очень полезной и как самостоятельная утилита. Фактически, m4 сочетает в себе функциональные возможности eval, tr, awk, и дополнительно предоставляет обширные возможности по созданию новых макроопределений.
В апрельском выпуске, за 2002 год, журнала Linux Journal вы найдете замечательную статью, описывающую возможности утилиты m4.
Пример 12-48. Пример работы с m4
Команда doexec предоставляет возможность передачи произвольного списка аргументов внешней программе. В частности, передавая argv[0] (для сценариев соответствует специальной переменной $0), можно вызвать программу под другим именем, определяя тем самым, ее реакцию.
Например, Пусть в каталоге /usr/local/bin имеется программа с именем "aaa", которая при вызове doexec /usr/local/bin/aaa list выведет список всех файлов в текущем каталоге, имена которых начинаются с символа "a", а при вызове той же самой программы как doexec /usr/local/bin/aaa delete , она удалит эти файлы.
![]() |
Естественно, реакция программы на свое собственное имя должна быть реализована в коде программы, для сценария на языке командной оболочки это может выглядеть примерно так:
|
Утилита dialog предоставляет в распоряжение программиста целый набор инструментов для построения интерактивного интерфейса в сценариях. Более совершенные разновидности команды dialog — gdialog, Xdialog и kdialog — которые используют в своей работе графические элементы управления X-Windows. См. Пример 33-15.
[33] Фактически — это сценарий, заимствованный из дистрибутива Debian Linux.
[34] Очередь печати — это группа заданий "ожидающих вывода" на принтер.
[35] Эта тема прекрасно освещена в статье, которую написал Andy Vaught, Introduction to Named Pipes, в сентябре 1997 для Linux Journal.
[36] EBCDIC (произносится как "ebb-sid-ic") — это аббревиатура от Extended Binary Coded Decimal Interchange Code (Расширенный Двоично-Десятичный Код Обмена Информацией). Это формат представления данных от IBM, не нашедший широкого применения. Не совсем обычное применение опции conv=ebcdic — это использовать dd для быстрого и легкого, но слабого, шифрования текстовых файлов.
[37] макроопределение — это идентификатор, символическая константа, которая представляет некоторую последовательность команд, операций и параметров.
Примеры использования большинства этих команд вы найдете в сценариях начальной загрузки и остановки системы, в каталогах /etc/rc.d. Они, обычно, вызываются пользователем root и используются для администрирования системы или восстановления файловой системы. Эти команды должны использоваться с большой осторожностью, так как некоторые из них могут разрушить систему, при неправильном использовании.
Выведет список всех зарегистрировавшихся пользователей. Она, до некоторой степени, является эквивалентом команды who -q.
Выводит список групп, в состав которых входит текущий пользователь. Эта команда соответствует внутренней переменной $GROUPS, но выводит названия групп, а не их числовые идентификаторы.
Команда chown изменяет владельца файла или файлов. Эта команда полезна в случаях, когда root хочет передать монопольное право на файл от одного пользователя другому. Обычный пользователь не в состоянии изменить владельца файла, за исключением своих собственных файлов.
Команда chgrp изменяет группу, которой принадлежит файл или файлы. Чтобы изменить группу, вы должны быть владельцем файла (при этом должны входить в состав указываемой группы) или привилегированным пользователем (root).
Команда useradd добавляет учетную запись нового пользователя в систему и создает домашний каталог для данного пользователя. Противоположная, по смыслу, команда userdel удаляет учетную запись пользователя из системы. [38] и удалит соответствующие файлы.
![]() |
Команда adduser является синонимом для useradd и, как правило, является обычной символической ссылкой на useradd. |
Модификация (изменение) характеристик пользовательского аккаунта. Может изменить пароль пользователя, членство в группах срок действия аккаунта и другие характеристики. С помощью этой команды можно заблокировать пользовательский пароль, что равносильно блокировке аккаунта.
Модификация (изменение) характеристик группы. С помощью этой команды можно изменить имя группы и/или ID группы.
Команда id выводит идентификатор пользователя (реальный и эффективный) и идентификаторы групп, в состав которых входит пользователь. По сути — выводит содержимое переменных $UID, $EUID и $GROUPS.
![]() |
Команда id выводит эффективный иднетификатор только тогда, когда он отличается от реального. |
См. также Пример 9-5.
Выводит список пользователей, работающих в настоящий момент в системе.
С ключом -m — выводит информацию только о текущем пользователе. Если число аргументов, передаваемых команде, равно двум, то это эквивалентно вызову who -m, например who am i или who The Man.
whoami — похожа на who -m, но выводит только имя пользователя.
Выводит информацию о системе, список пользователей, подключенных к системе и процессы, связанные с пользователями. Это расширенная версия команды who. Вывод от команды w может быть передан по конвейеру команде grep, с целью поиска требуемого пользователя и/или процесса.
Выводит имя текущего пользователя (из файла /var/run/utmp). Это довольно близкий эквивалент команды whoami.
![]() |
Команда logname выводит имя пользователя, зарегистрировавшегося в системе (залогировавшегося), в то время как whoami — дает имя пользователя, под которым исполняется текущий процесс. Как я уже упоминал — это не всегда одно и то же. |
Однако...
Команда предназначена для запуска программы или сценария от имени другого пользователя. su rjones — запускает командную оболочку от имени пользователя rjones. Запуск команды su без параметров означает запуск командной оболочки от имени привилегированного пользователя root. См. Пример A-17.
Исполняет заданную команду от имени пользователя root (или другого пользователя).
Имена пользователей, которым разрешено использовать команду sudo, хранятся в файле /etc/sudoers.
Устанавливает или изменяет пароль пользователя.
Команда passwd может использоваться в сценариях, но это плохая практика.
Пример 13-1. Установка нового пароля
Команда passwd с ключами -l, -u и -d выполняет блокировку, разблокировку и удаление пароля пользователя. Только root может вызывать команду passwd с этими ключами.
Выводит время работы пользователей, основываясь на записях в файле /var/log/wtmp. Это одна из утилит пакета GNU acct.
Выводит информацию о последних входах/выходах пользователей в ситему, основываясь на записях в файле /var/log/wtmp. Эта команда может отображать информацию об удаленных (в смысле — с удаленного терминала) соединениях.
Позволяет сменить активную группу пользователя. Пользователь остается в системе и текущий каталог не изменяется, но права доступа к файлам вычисляются в соответствии с новыми реальным и эффективным идентификаторами группы. Эта команда используется довольно редко, так как пользователь, обычно, является членом нескольких групп.
Выводит имя терминала текущего пользователя. Обратите внимание: каждое отдельное окно xterm считается отдельным терминалом.
Выводит и/или изменяет настройки терминала. Эта сложная команда используется в сценариях для управления поведением терминала.
Пример 13-2. Установка символа "забоя"
Пример 13-3. невидимый пароль: Отключение эхо-вывода на терминал
Пример 13-4. Перехват нажатия на клавиши с помощью stty.
См. также Пример 9-3.
Выводит или изменяет настройки терминала. Это более слабая версия stty.
Настройка параметров последовательного порта. Эта команда должна запускаться пользователем, обладающим привилегиями root. Эту команду можно встретить в сценариях настройки системы.
Программа getty или agetty запускается процессом init и обслуживает процедуру входа пользователя в систему. Эти команды не используются в сценариях.
Разрешает или запрещает доступ к терминалу текущего пользователя командой write.
![]() |
Наверное это очень неприятно, когда, во время работы над текстовым файлом, в окне терминала, прямо среди текста, вдруг появляется предложение заказать пиццу. Поэтому, при работе в многопользовательской системе, вам наверняка захочется отключить доступ к своему терминалу. |
Имя этой команды — аббревиатура от "write all", т.е., передать сообщение всем пользователям на все терминалы в сети. Это, в первую очередь, инструмет администратора, который можно использовать, например, для оповещения всех пользователей о предстоящей, в ближайшее время, перезагрузке системы (см. Пример 17-2).
![]() |
Если доступ к терминалу был закрыт командой mesg, то сообщение на этом терминале выводиться не будет. |
Выводит все сообщения, выдаваемые системой во время загрузки на stdout. Очень полезная утилита для отладочных целей. Вывод dmesg может анализироваться с помощью grep, sed или awk внутри сценария.
Информационные и статистические утилиты
Выводит на stdout имя системы. С ключом -a, выводит подробную информацию, содержащую имя системы, имя узла (то есть имя, под которым система известна в сети), версию операционной системы, наименование модификации операционной системы, аппаратную архитектуру (см. Пример 12-5).
Выводит тип аппаратной платформы компьютерв. Эквивалентна команде uname -m. См. Пример 10-26.
Выводит информацию, о ранее выполненных командах, из файла /var/account/pacct. Дополнительно могут указываться команда и пользователь. Это одна из утилит пакета GNU acct.
Выводит список всех пользователей, с указанием времени последнего входа в систему. Данные берутся из файла /var/log/lastlog.
![]() |
Исполнение этой команды будет завершаться неудачей, если пользователь, вызвавший утилиту, не имеет прав на чтение файла /var/log/lastlog. |
Выводит детальный список открытых, в настоящий момент времени, файлов в виде таблицы. В таблице указаны — владелец файла, размер файла, тип файла, процесс, открывший файл, и многое другое. Само собой разумеется, что вывод команды lsof может быть обработан, в конвейере, с помощью утилит grep и/или awk.
Диагностическая и отладочная утилита, предназначенная для трассировки системных вызовов и сигналов. В простейшем случае, запускается как: strace COMMAND.
Эквивалентна команде truss.
Сканер сетевых портов. Эта утилита сканирует сервер в поисках открытых портов и сервисов. Это очень важный инструмент, используемый для поиска уязвимостей при настройке системы.
Показывает информацию об использовании памяти, в табличной форме. Вывод команды может быть проанализирован с помощью grep, awk или Perl. Команда procinfo тоже выводит эту информацию, среди всего прочего.
Показать размер неиспользуемой памяти RAM:
Извлекает и выводит информацию из файловой системы /proc.
Список аппаратных устройств в системе.
Выводит сведения о занимаемом дисковом пространстве в каталоге и вложенных подкаталогах. Если каталог не указан, то по-умолчанию выводятся сведения о текущем каталоге.
Выводит в табличной форме сведения о смонтированных файловых системах.
Дает подробную информацию о заданном файле (каталоге или файле устройства) или наборе файлов.
Если заданный файл отсутствует, то stat вернет сообщение об ошибке.
Выводит информацию о виртуальной памяти.
Показывает сведения о сетевой подсистеме, такие как: таблицы маршрутизации и активные соединения. Эта утилита получает сведения из /proc/net (Глава 27). См. Пример 27-3.
netstat -r — эквивалентна команде route.
Показывает количество времени, прошедшего с момента последней перезагрузки системы.
Выводит имя узла (сетевое имя системы). С помощью этой команды устанавливается сетевое имя системы в сценарии /etc/rc.d/rc.sysinit. Эквивалентна команде uname -n и внутренней переменной $HOSTNAME.
Выводит 32-битный шестнадцатиричный идентификатор системы.
![]() |
Эта команда генерирует "уникальный" числовой идентификатор системы. Некоторые программные продукты используют этот идентификатор в процедуре регистрации. К сожалению, при генерации идентификатора, hostid использует только IP адрес системы, переводя его в шестнадцатиричное представление и переставляя местами пары байт. Обычно, IP адрес системы можно найти в файле /etc/hosts.
Переставив местами байты, попарно, в начальном адресе 127.0.0.1, мы получим 0.127.1.0, в шестнадцатиричном представлении это будет 007f0100, что в точности совпадает с приведенным выше результатом выполнения hostid. Наверняка можно найти несколько миллионов компьютеров с таким же "уникальным" идентификатором. |
Команда sar (System Activity Reporter) выводит очень подробную статистику о функционировании операционной системы. В июне 1999 года, компания Santa Cruz Operation (SCO) опубликовала исходные тексты утилиты. Она, как правило, не входит в базовый комплект пакетов Linux-систем. Но ее можно получить в составе пакета sysstat utilities, автор: Sebastien Godard.
Показывает сведения о заданном бинарном файле формата elf. Входит в состав пакета binutils.
Команда size [/path/to/binary] выведет информацию о размерах различных сегментов в исполняемых или библиотечных файлах. В основном используется программистами.
Добавляет в системный журнал (/var/log/messages) сообщение от пользователя. Для добавления сообщения пользователь не должен обладать привилегиями суперпользователя.
Встраивая вызов logger в сценарии, вы получаете возможность заносить отладочную информацию в системный журнал /var/log/messages.
Эта утилита производит манипуляции над системным журналом: ротация, сжатие, удаление и/или отправляет его по электронной почте, по мере необходимости. Как правило, утилита logrotate вызывается демоном cron ежедневно.
Добавляя соответствующие строки в /etc/logrotate.conf, можно заставить logrotate обрабатывать не только системный журнал, но и ваш личный.
Process Statistics: Список исполняющихся в данный момент процессов. Обычно вызывается с ключами ax, вывод команды может быть обработан командами grep или sed, с целью поиска требуемого процесса (см. Пример 11-11 и Пример 27-2).
Список исполняющихся процессов в виде "дерева". С ключом -p — вместе с именами процессов отображает их PID.
Выводит список наиболее активных процессов. С ключом -b — отображение ведется в обычном текстовом режиме, что дает возможность анализа вывода от команды внутри сценария.
Запускает фоновый процесс с заданным приоритетом. Приоритеты могут задаваться числом из диапазона от 19 (низший приоритет) до -20 (высший приоритет). Но только root может указать значение приоритета меньше нуля (отрицательные значения). См. так же команды renice, snice и skill.
Запуск команд в режиме игнорирования сигналов прерывания и завершения, что предотвращает завершение работы команды даже если пользователь, запустивший ее, вышел из системы. Если после команды не указан символ &, то она будет исполняться как процесс "переднего плана". Если вы собираетесь использовать nohup в сценариях, то вам потребуется использовать его в связке с командой wait, чтобы не породить процесс "зомби".
Возвращает идентификатор процесса (pid) по его имени. Поскольку многие команды управления процессами, такие как kill и renice, требуют указать pid процесса, а не его имя, то pidof может сослужить неплохую службу при идентификации процесса по его имени. Эта коменда может рассматриваться как приблизительный эквивалент внутренней переменной $PPID.
Пример 13-5. Использование команды pidof при остановке процесса
Возвращает идентификаторы процессов, использующих указанный файл(ы) или каталог. С ключом -k, завершает найденые процессы. Может с успехом использоваться для защиты системы, особенно в сценариях разграничения доступа к системным службам.
Планировщик заданий. С его помощью выполняются такие задачи, как очистка и удаление устаревших файлов системных журналов, обновление базы данных slocate. Это суперпользовательская версия команды at (хотя любой пользователь может создать собственную таблицу crontab). Эта утилита запускается как фоновый процесс-daemon и выполняет задания, находящиеся в файле /etc/crontab.
![]() |
В некоторых дистрибутивах Linux, в качестве crond используется версия cron от Matthew Dillon. |
Команды управления процессами и загрузкой
init — предок (родитель) всех процессов в системе. Вызывается на последнем этапе загрузки системы и определяет уровень загрузки (runlevel) из файла /etc/inittab.
Символическая ссылка на init — инструмент для смены уровня загрузки (runlevel), как правило используется при обслуживании системы или восстановлении файловой системы. Может быть вызвана только суперпользователем. Эта команда может быть очень опасна, при неумелом обращении — прежде чем использовать ее, убедитесь в том, что вы совершенно точно понимаете что делаете!
Выводит предыдущий и текущий уровни загрузки (runlevel). Уровень загрузки может иметь одно из 6 значений: 0 — остановка системы, 1 — однопользовательский режим, 2 или 3 — многопользовательский режим, 5 — многопользовательский режим и запуск X Window, 6 — перезагрузка. Уровни загрузки определяются из файла /var/run/utmp.
Набор команд для остановки системы, обычно перед выключением питания.
Утилита конфигурирования и запуска сетевых интерфейсов. Чаще всего используется в сценариях начальной загрузки системы, для настройки и запуска сетевых интерфейсов или для их остановки перед остановкой или перезагрузкой.
Эта команда используется для настройки беспроводной (wireless) сети. Представляет собой эквивалент команды ifconfig, описанной выше.
Выводит сведения о таблице маршрутизации ядра или вносит туда изменения.
Проверка сетевой конфигурации. Обслуживает список, запускаемых на этапе загрузки, сетевых сервисов, список сервисов хранится в каталогах /etc/rc?.d (строго говоря, chkconfig работает не только с сетевыми сервисами, а с сервисами вообще, не зависимо от того сетевые это службы или нет. прим. перев.).
Изначально эта утилита была перенесена в Red Hat Linux из ОС IRIX, chkconfig входит в состав далеко не всех дистрибутивов Linux.
"Сниффер" ("sniffer") сетевых пакетов. Инструмент для перехвата и анализа сетевого трафика по определенным критериям.
Дамп трафика ip-пакетов между двумя узлами сети — bozoville и caduceus:
Конечно же, вывод команды tcpdump может быть проанализирован с помощью команд обработки текста, обсуждавшихся выше.
Команды для работы с файловыми системами
Выполняет монтирование файловой системы, обычно на устройстве со сменными носителями, такими как дискеты или CDROM. Файл /etc/fstab содержит перечень доступных для монтирования файловых систем, разделов и устройств, включая опции монтирования, благодаря этому файлу, монтирование может производиться автоматически или вручеую. Файл /etc/mtab содержит список смонтированных файловых систем и разделов (включая виртуальные, такие как /proc).
mount -a — монтирует все (all) файловые системы и разделы, перечисленные в /etc/fstab, за исключением тех, которые имеют флаг noauto. Эту команду можно встретить в сценариях начальной загрузки системы из /etc/rc.d (rc.sysinit или нечто похожее).
Эта команда может даже смонтировать обычный файл как блочное устройство. Достигается это за счет связывания файла с loopback-устройством. Эту возможность можно использовать для проверки ISO9660 образа компакт-диска перед его записью на болванку. [39]
Пример 13-6. Проверка образа CD
Отмонтирует смонтированную файловую систему. Перед тем как физически вынуть компакт-диск или дискету из устройства, это устройство должно быть отмонтировано командой umount, иначе файловая система может оказаться поврежденной (особенно это относится к накопителям на гибких магнитных дисках, прим. перев.).
![]() |
Утилита automount, если она установлена, может выполнять атоматическое монтирование/размонтирование устройств со сменными носителями, такие как дискеты и компакт-диски. На ноутбуках со сменными устройствами FDD и CDROM, такой подход может привести к возникновению определенных проблем. |
Принудительный сброс содержимого буферов на жесткий диск (синхронизация содержимого буферов ввода-вывода и устройства-носителя). Несмотря на то, что нет такой уж острой необходимости в этой утилите, тем не менее sync придает уверенности системным администраторам или пользователям в том, что их данные будут сохранены на жестком диске, и не будут потеряны в случае какого-либо сбоя. В былые дни, команда sync; sync (дважды — для абсолютной уверенности) была упреждающей мерой перед перезагрузкой системы.
Иногда возникает необходимость принудительной синхронизации буферов ввода-вывода с содержимым на магнитном носителе, как, например, при надежном удалении файла (см. Пример 12-45) или когда наблюдаются скачки напряжения в сети электроснабжения.
Устанавливает и конфигурирует loopback-устройства.
Пример 13-7. Создание файловой системы в обычном файле
Создание swap-раздела или swap-файла. Созданный swap-раздел (файл) нужно затем подключить командой swapon.
Разрешает/запрещает использование swap-раздела (файла). Эта команда обычно используется во время загрузки системы или во время остановки.
Создает файловую систему ext2. Должна вызываться с правами суперпользователя.
Пример 13-8. Добавление нового жесткого диска
См. также Пример 13-7 и Пример 28-3.
Настройка отдельных параметров файловой системы ext2, например счетчик максимального количества монтирований без проверки. Должна вызываться с привилегиями пользователя root.
![]() |
Очень опасная утилита. Вы можете использовать ее только на свой страх и риск, поскольку, по неосторожности, вы запросто можете разрушить файловую систему. |
Выводит на stdout очень подробную информацию о файловой системе. Должна вызываться с привилегиями пользователя root.
Выводит или изменяет параметры настройки жесткого диска. Должна вызываться с привилегиями пользователя root. Потенциально опасна при неправильном использовании.
Создание или изменение таблицы разделов на устройствах хранения информации, обычно — жестких дисках. Должна вызываться с привилегиями пользователя root.
![]() |
Пользуйтесь этой утилитой с особой осторожностью, т.к. при неправильном использовании можно легко разрушить существующую файловую систему. |
Набор команд для проверки, восстановления и отладки файловой системы.
fsck: интерфейсная утилита для проверки файловых систем в Unix (может вызывать другие утилиты проверки).
e2fsck: проверка файловой системы ext2.
debugfs: отладчик файловой системы ext2. Одно из применений этой универсальной (и опасной) утилиты — это восстановление удаленных файлов. Только для опытных пользователей!
![]() |
Все эти утилиты должны вызываться с привилегиями пользователя root. При неправильном использовании, любая из них может разрушить файловую систему. |
Выполняет поиск плохих блоков (физические повреждения носителей) на устройствах хранения информации. Эта команда может использоваться для поиска плохих блоков при форматировании вновь устанавливаемых жестких дисков или для проверки устройств резервного копирования. [40] Например, badblocks /dev/fd0, проверит дискету на наличие поврежденных блоков.
Утилита badblocks может быть вызвана в деструктивном (проверка осуществляется путем записи некоторого шаблона в каждый блок, а затем производится попытка чтения этого блока) или в недеструктивном (неразрушающем — только чтение) режиме.
Команда lsusb выводит сведения о имеющихся в системе шинах USB (Universal Serial Bus) и подключенных к ним устройствах.
Команда usbmodules выводит информацию о модулях драйверов присоединенных USB-устройств.
Создание загрузочной дискеты, которая может быть использована для загрузки системы, если, например, была повреждена MBR (master boot record — главная загрузочная запись). Команда mkbootdisk — это сценарий на языке командной оболочки Bash, автор: Erik Troan, располагается в каталоге /sbin.
CHange ROOT — смена корневого каталога. Обычно, команды и утилиты ориентируются в файловой системе посредством переменной $PATH, относительно корневого каталога /. Команда chroot изменяет корневой каталог по-умолчанию на другой (рабочий каталог также изменяется). Эта утилита, как правило, используется с целью защиты системы, например, с ее помощью можно ограничить доступ к разделам файловой системы для пользователей, подключающихся к системе с помощью telnet (это называется — "поместить пользователя в chroot окружение"). Обратите внимание: после выполнения команды chroot изменяется путь к исполняемым файлам системы.
Команда chroot /opt приведет к тому, что все обращения к каталогу /usr/bin будут переводиться на каталог /opt/usr/bin. Аналогично, chroot /aaa/bbb /bin/ls будет пытаться вызвать команду ls из каталога /aaa/bbb/bin, при этом, корневым каталогом для ls станет каталог /aaa/bbb. Поместив строчку alias XX 'chroot /aaa/bbb ls' в пользовательский ~/.bashrc, можно эффективно ограничить доступ команде "XX", запускаемой пользователем, к разделам файловой системы.
![]() |
При изменении корневого каталога, вам наверняка потребуется скопировать системные утилиты и разделяемые библиотеки в новый корневой каталог, поскольку после смены корневого каталога, директории с системными утилитами могут оказаться за пределами нового корневого каталога. |
Эта утилита входит в состав пакета procmail (www.procmail.org). Она создает lock file, файл-семафор (или, если угодно, файл блокировки), который управляет доступом к заданному файлу, устройству или ресурсу. Lock file служит признаком того, что данный файл, устройство или ресурс "занят" некоторым процессом, и ограничивает (или вообще запрещает) доступ к ресурсу другим процессам.
Файлы блокировок широко применяются для защиты системных почтовых каталогов от одновременной записи несколькими пользователями, для индикации занятости порта модема, и т.п. Сценарии могут использовать файлы блокировок для того, чтобы выяснить — запущен ли тот или иной процесс. Обратите внимание: если в сценарии будет предпринята попытка создать файл блокировки, когда он уже существует, то такой сценарий скорее всего зависнет.
Как правило, файлы блокировки создаются в каталоге /var/lock. Проверка наличия файла блокировки может быть проверена примерно таким образом:.
Создает специальный файл для блочного или символьного устройства (может потребоваться при установке новых устройств в компьютер). В системе имеется более удобная в обращении утилита MAKEDEV, которая обладает всей функциональностью команды mknod.
Автоматически удаляет файлы, к которым не было обращений в течение заданного периода времени. Обычно вызывается демоном cron для удаления устаревших файлов системного журнала.
Утилита предназначена для создания файлов-устройств. Должна запускаться с привилегиями пользователя root, в каталоге /dev.
Команды резервного копирования
Команда dump создает резервные копии целых файловых систем, обычно используется в крупных системах и сетях. [41] Она считывает дисковые разделы и сохраняет их в файле, в двоичном формате. Созданные таким образом файлы, могут быть сохранены на каком-либо носителе — на жестком диске или магнитной ленте. Команда restore — "разворачивает" файлы, созданные утилитой dump.
Выполняет низкоуровневое форматирование дискет.
Команды управления системными ресурсами
Устанавливает верхний предел для системных ресурсов. Как правило вызывается с ключом -f, что означает наложение ограничений на размер файлов (ulimit -f 1000 ограничит размер вновь создаваемых файлов одним мегабайтом). Ключ -c ограничивает размер файлов coredump (ulimit -c 0 запретит создание coredump-файлов). Обычно, все ограничения прописываются в файле /etc/profile и/или ~/.bash_profile (см. Глава 26).
![]() |
Грамотное использование ulimit поможет избежать нападений, целью которых является исчерпание системных ресурсов, известных под названием fork bomb.
Команда ulimit -Hu XX (где XX — это верхний предел количества процессов, которые может запустить пользователь одновременно) в /etc/profile вызовет аварийное завершение этого сценария, когда количество процессов превысит установленный предел. |
Команда управления дисковыми квотами для пользователей и групп.
Установка маски режима создания файлов. Накладывает ограничения на атрибуты по-умлчанию для создаваемых файлов. Маска представляет собой восьмеричное значение и определяет запрещенные атрибуты файла. Например, umask 022 удаляет права на запись для группы и прочих пользователей (у файлов, создававшихся с режимом 777, он оказывается равным 755; а режим 666 преобразуется в 644, т.е. 777 NAND 022 = 755, 666 NAND 022 = 644). [42] Конечно же, впоследствие, пользователь может откорректировать права доступа к своему файлу с помощью команды chmod. Как правило, значение umask устанавливается в файле /etc/profile и/или ~/.bash_profile (см. Глава 26).
Выводит или изменяет корневое устройство, размер RAM-диска или видео режим. Функциональные возможности утилиты rdev вообще повторяются загрузчиком lilo, но rdev по прежнему остается востребованной, например, при установке электронного диска (RAM-диск). Это потенциально опасная, при неумелом использовании, утилита.
Команды для работы с модулями ядра
Выводит список загруженных модулей.
![]() |
Команда cat /proc/modules выведет на экран эту же информацию. |
Принудительная загрузка модуля ядра (старайтесь вместо insmod использовать команду modprobe). Должна вызываться с привилегиями пользователя root.
Выгружает модуль ядра. Должна вызываться с привилегиями пользователя root.
Загрузчик модулей, который обычно вызывается из сценариев начальной загрузки системы. Должна вызываться с привилегиями пользователя root.
Создает файл зависимостей между модулями, обычно вызывается из сценариев начальной загрузки системы.
Выводит сведения о загруженных модулях ядра.
Запускает указанную программу или сценарий с модифицированными переменными окружения (не изменяя среду системы в целом, изменения касаются только окружения запускаемой программы/сценария). Посредством [varname=xxx], устанавливает значение переменной окружения varname, которая будет доступна из запускаемой программы/сценария. Без параметров — просто выводит список переменных окружения с их значениями.
![]() |
В Bash, и других производных от Bourne shell, имеется возможность установки переменных окружения и запуска программы (или сценария) одной командной строкой.
|
![]() |
В первой строке сценария ("sha-bang") можно указать команду env, если путь к командному интерпретатору не известен.
|
Выводит список разделяемых библиотек, необходимых для исполняемого файла.
Периодически запускает указанную программу с заданным интервалом времени.
По-умолчанию интервал между запусками принимается равным 2 секундам, но может быть изменен ключом -n.
Удаляет отладочную информацию из исполняемого файла. Это значительно уменьщает размер исполняемого файла, но при этом делает отладку программы невозможной.
Эту команду часто можно встретить в Makefile-ах, и редко — в сценариях на языке командной оболочки.
Выводит список символов (используемых в целях отладки), содержащихся в откомпилированном двоичном файле.
Позволяет на заданных машинах хранить идентичные копии файлов. По умолчанию, rdist просматривает только те файлы, версия которых на удаленных машинах более старая, чем на локальной машине. Это делается сравнением последнего времени модификации и размера файла на локальной машине и на удаленных.
А теперь, используя полученные нами знания, попробуем разобраться с одним из системных сценариев. Один из самых коротких и простых — это killall, который вызывается для остановки процессов при перезагрузке или выключении компьютера.
Пример 13-9. Сценарий killall, из каталога /etc/rc.d/init.d
Вобщем все довольно понятно. Кроме хитрого манипулирования с переменными, при определении имени подсистемы (службы), здесь нет ничего нового.
Упражнение 1. Просмотрите сценарий halt в каталоге /etc/rc.d/init.d. Он по размеру немного больше, чем killall, но придерживается той же концепции. Создайте копию этого сценария в своем домашнем каталоге и поэкспериментируйте с ним (НЕ запускайте его с привилегиями суперпользователя). Попробуйте запустить его с ключами -vn (sh -vn scriptname). Добавьте свои комментарии. Замените действующие команды на "echo".
Упражнение 2. Просмотрите другие, более сложные сценарии из /etc/rc.d/init.d. Попробуйте разобраться в их работе. Проверьте их работу, следуя рекомендациям, приведенным выше. За дополнительной информацией вы можете обратиться к документу sysvinitfiles в каталоге /usr/share/doc/initscripts-?.??, который входит в пакет документации к "initscripts".
[38] Команда userdel завершится неудачей, если удаляемый пользователь в этот момент работает с системой
[39] Дополнительную информацию по записи компакт-дисков, вы найдете в статье Алекса Уизера (Alex Wither): Creating CDs, в октябрьском выпуске журнала Linux Journal за 1999 год.
[40] Утилита mke2fs, с ключом -c, так же производит поиск поврежденных блоков.
[41] Пользователи небольших, десктопных Linux-систем предпочитают утилиты попроще, например tar.
[42] NAND — логическая операция "И-НЕ". В общих чертах она напоминает вычитание.
Подстановка команд — это подстановка результатов выполнения команды [43] или даже серии команд; буквально, эта операция позволяет вызвать команду в другом окружении. [44]
Классический пример подстановки команд — использование обратных одиночных кавычек (`...`). Команды внутри этих кавычек представляют собой текст командной строки.
Вывод от команд может использоваться: как аргумент другой команды, для установки значения переменной и даже для генерации списка аргументов цикла for.
![]() |
Подстанавливаемая команда выполняется в подоболочке. |
![]() |
Подстанавливаемая команда может получиться разбитой на отдельные слова.
Даже когда не происходит разбиения на слова, операция подстановки команд может удалять завершающие символы перевода строки.
|
![]() |
При выводе значений переменных, полученных в результате подстановки команд, командой echo, без кавычек, символы перевода строки будут удалены. Это может оказаться неприятным сюрпризом.
|
Подстановка команд позволяет даже записывать в переменные содержимое целых файлов, с помощью перенаправления или команды cat.
Подстановка команд, позволяет записать в переменную результаты выполнения цикла. Ключевым моментом здесь является команда echo, в теле цикла.
Пример 14-2. Запись результатов выполнения цикла в переменную
![]() |
Альтернативой обратным одиночным кавычкам, используемым для подстановки команд, можно считать такую форму записи: $(COMMAND).
Следует упомянуть, что в конструкции $(...) два идущих подряд обратных слэша интерпретируются несколько иначе, чем в конструкции `...`.
|
Примеры подстановки команд в сценариях:
[43] Замещающая команда может быть внешней системной командой, внутренней (встроенной) командой или даже функцией в сценарии.
[44] Более корректно (с технической точки зрения) следовало бы сказать, что операция подстановки команды заключается в получении вывода от команды (со stdout) и присвоения результата выполнения переменной, с помощью оператора =.
Арифметические подстановки — это мощный инструмент, предназначенный для выполнения арифметических операций в сценариях. Перевод строки в числовое выражение производится с помощью обратных одиночных кавычек, двойных круглых скобок или предложения let.
В арифметических подстановках, обратные одиночные кавычки могут быть заменены на двойные круглые скобки — $((...)) и $((...)) или очень удобной конструкцией, с применением предложения let.
Примеры арифметических подстановок в сценариях:
В системе по-умолчанию всегда открыты три "файла" — stdin (клавиатура), stdout (экран) и stderr (вывод сообщений об ошибках на экран). Эти, и любые другие открытые файлы, могут быть перенапрвлены. В данном случае, термин "перенаправление" означает получить вывод из файла, команды, программы, сценария или даже отдельного блока в сценарии (см. Пример 3-1 и Пример 3-2) и передать его на вход в другой файл, команду, программу или сценарий.
С каждым открытым файлом связан дескриптор файла. [45] Дескрипторы файлов stdin, stdout и stderr — 0, 1 и 2, соответственно. При открытии дополнительных файлов, дескрипторы с 3 по 9 остаются незанятыми. Иногда дополнительные дескрипторы могут сослужить неплохую службу, временно сохраняя в себе ссылку на stdin, stdout или stderr. [46] Это упрощает возврат дескрипторов в нормальное состояние после сложных манипуляций с перенаправлением и перестановками (см. Пример 16-1).
Операции перенаправления и/или конвейеры могут комбинироваться в одной командной строке.
Допускается перенаправление нескольких потоков в один файл.
Закрыть дескриптор входного файла n.
Закрыть stdin.
Закрыть дескриптор выходного файла n.
Закрыть stdout.
Дочерние процессы наследуют дескрипторы открытых файлов. По этой причине и работают конвейеры. Чтобы предотвратить наследование дескрипторов — закройте их перед запуском дочернего процесса.
Дополнительные сведения о перенаправлении ввода/вывода вы найдете в Приложение E.
[45] дескриптор файла — это просто число, по которому система идентифицирует открытые файлы. Рассматривайте его как упрощенную версию указателя на файл.
[46] При использрвании дескриптора с номером 5 могут возникать проблемы. Когда Bash порождает дочерний процесс, например командой exec, то дочерний процесс наследует дескриптор 5 как "открытый" (см. архив почты Чета Рамея (Chet Ramey), SUBJECT: RE: File descriptor 5 is held open) Поэтому, лучше не использовать этот дескриптор.
Команда exec <filename перенаправляет ввод со stdin на файл. С этого момента весь ввод, вместо stdin (обычно это клавиатура), будет производиться из этого файла. Это дает возможность читать содержимое файла, строку за строкой, и анализировать каждую введенную строку с помощью sed и/или awk.
Пример 16-1. Перенаправление stdin с помощью exec
Аналогично, конструкция exec >filename перенаправляет вывод на stdout в заданный файл. После этого, весь вывод от команд, который обычно направляется на stdout, теперь выводится в этот файл.
Пример 16-2. Перенаправление stdout с помощью exec
Пример 16-3. Одновременное перенаправление устройств, stdin и stdout, с помощью команды exec
Блоки кода, такие как циклы while, until и for, условный оператор if/then, так же могут смешиваться с перенаправлением stdin. Даже функции могут использовать эту форму перенаправления (см. Пример 22-10). Оператор перенаправления <, в таких случаях, ставится в конце блока.
Пример 16-4. Перенаправление в цикл while
Пример 16-5. Альтернативная форма перенаправления в цикле while
Пример 16-6. Перенаправление в цикл until
Пример 16-7. Перенаправление в цикл for
Предыдущий пример можно модифицировать так, чтобы перенаправить вывод из цикла.
Пример 16-8. Перенаправление устройств (stdin и stdout) в цикле for
Пример 16-9. Перенаправление в конструкции if/then
Пример 16-10. Файл с именами "names.data", для примеров выше
Перенаправление stdout для блока кода, может использоваться для сохранения результатов работы этого блока в файл. См. Пример 3-2.
Встроенный документ — это особая форма перенаправления для блоков кода.
Как один из вариантов грамотного применения перенаправления ввода/вывода, можно назвать разбор и "сшивание" вывода от команд (см. Пример 11-6). Это позволяет создавать файлы отчетов и журналов регистрации событий.
Пример 16-11. Регистрация событий
Встроенный документ (here document) является специальной формой перенаправления ввода/вывода, которая позволяет передать список команд интерактивной программе или команде, например ftp, telnet или ex.
Конец встроенного документа выделяется "строкой-ограничителем", которая задается с помощью специальной последовательности символов <<. Эта последовательность — есть перенаправление вывода из файла на stdin программы или команды, что напоминает конструкцию interactive-program < command-file, где command-file содержит строки:
Сценарий, использующий "встроенный документ" для тех же целей, может выглядеть примерно так:
В качестве строки-ограничителя должна выбираться такая последовательность символов, которая не будет встречаться в теле "встроенного документа".
Обратите внимание: использование встроенных документов может иногда с успехом применяться и при работе с неинтерактивными командами и утилитами.
Пример 17-1. dummyfile: Создание 2-х строчного файла-заготовки
Этот сценарий, с тем же эффектом, мог бы быть реализован, основываясь не на vi, а на ex. Встроенные документы, содержащие команды для ex, стали настолько обычным делом, что их уже смело можно вынести в отдельную категорию — ex-сценарии.
Пример 17-2. broadcast: Передача сообщения всем, работающим в системе, пользователям
Пример 17-3. Вывод многострочных сообщений с помощью cat
Если строка-ограничитель встроенного документа начинается с символа - (<<-LimitString), то это приводит к подавлению вывода ведущих (начальных) символов табуляции (но не пробелов). Это может оказаться полезным при форматировании текста сценария для большей удобочитаемости.
Пример 17-4. Вывод многострочных сообщений с подавлением символов табуляции
Встроенные документы поддерживают подстановку команд и параметров. Что позволяет передавать различные параметры в тело встроенного документа.
Пример 17-5. Встроенные документы и подстановка параметров
Еще один пример сценария, содержащего встроенный документ и подстановку параметров в его теле.
Пример 17-6. Передача пары файлов во входящий каталог на "Sunsite"
Заключая строку-ограничитель в кавычки или экранируя ее, можно запретить подстановку параметров в теле встроенного документа.
Пример 17-7. Отключение подстановки параметров
Запрет на подстановку параметров позволяет выводить текст, как говорится, "один к одному". Это обстоятельство может использоваться, например, для автоматической генерации сценариев или даже текстов программ на других языках программирования.
Пример 17-8. Сценарий, который создает другой сценарий
Допускается запись тела встроенного документа в переменную.
Встроенные документы могут передаваться на вход функции, находящейся в том же сценарии.
Пример 17-9. Встроенные документы и функции
Встроенный документ можно передать "пустой команде" :. Такая конструкция, фактически, создает "анонимный" встроенный документ.
Пример 17-10. "Анонимный" Встроенный Документ
![]() |
Подобную технику можно использовать для создания "блочных комментариев". |
Пример 17-11. Блочный комментарий
![]() |
Еще одно остроумное применение встроенных документов — встроенная справка к сценарию. |
Пример 17-12. Встроенная справка к сценарию
![]() |
Для встроенных документов, во время исполнения, создаются временные файлы, но эти файлы удаляются после открытия и недоступны для других процессов.
|
![]() |
Некоторые утилиты не могут работать внутри встроенных документов. |
![]() |
Строка-ограничитель, закрывающая встроенный документ, должна начинаться с первого символа в строке. Перед ней не должно быть пробельных символов. Аналогично, пробельные символы, стоящие за строкой-ограничителем, могут дать нежелательные побочные эффекты.
|
Если какая либо задача не может быть решена с помощью "встроенного документа", то вам следует попробовать язык сценариев expect, который приспособлен для передачи параметров на вход интерактивных программ.
Итак, мы вплотную подошли к изучению очень сложных и необычных аспектов написания сценариев. В этой части мы попытаемся "сбросить покров тайны" и заглянуть за пределы известного нам мира (представьте себе путешествие по территории, не отмеченной на карте).
Для того, чтобы полностью реализовать потенциал командной оболочки, вам придется овладеть Регулярными Выражениями. Многие команды и утилиты, обычно используемые в сценариях, такие как grep, expr, sed и awk, используют Регулярные Выражения.
Выражение — это строка символов. Символы, которые имеют особое назначение, называются метасимволами. Так, например, кавычки могут выделять прямую речь, т.е. быть метасимволами для строки, заключенной в эти кавычки. Регулярные выражения — это набор символов и/или метасимволов, которые наделены особыми свойствами. [47]
Основное назначение регулярных выражений — это поиск текста по шаблону и работа со строками.
Звездочка — * — означает любое количество символов в строке, предшествующих "звездочке", в том числе и нулевое число символов.
Выражение "1133*" — означает 11 + один или более символов "3" + любые другие символы: 113, 1133, 113312, и так далее.
Точка — . — означает не менее одного любого символа, за исключением символа перевода строки (\n). [48]
Выражение "13." будет означать 13 + по меньшей мере один любой символ (включая пробел): 1133, 11333, но не 13 (отсутствуют дополнительные символы).
Символ — ^ — означает начало строки, но иногда, в зависимости от контекста, означает отрицание в регулярных выражениях.
Знак доллара — $ — в конце регулярного выражения соответствует концу строки.
Выражение "^$" соответствует пустой строке.
![]() |
Символы ^ и $ иногда еще называют якорями, поскольку они означают, или закрепляют, позицию в регулярных выражениях. |
Квадратные скобки — [...] — предназначены для задания подмножества символов. Квадратные скобки, внутри регулярного выражения, считаются одним символом, который может принимать значения, перечисленные внутри этих скобок..
Выражение "[xyz]" — соответствует одному из символов x, y или z.
Выражение "[c-n]" соответствует одному из символов в диапазоне от c до n, включительно.
Выражение "[B-Pk-y]" соответствует одному из символов в диапазоне от B до P или в диапазоне от k до y, включительно.
Выражение "[a-z0-9]" соответствует одному из символов латиницы в нижнем регистре или цифре.
Выражение "[^b-d]" соответствует любому символу, кроме символов из диапазона от b до d, включительно. В данном случае, метасимвол ^ означает отрицание.
Объединяя квадратные скобки в одну последовательность, можно задать шаблон искомого слова. Так, выражение "[Yy][Ee][Ss]" соответствует словам yes, Yes, YES, yEs и так далее. Выражение "[0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9]" определяет шаблон для поиска любого номера карточки социального страхования (для США).
Обратный слэш — \ — служит для экранирования специальных символов, это означает, что экранированные символы должны интерпретироваться буквально, т.е. как простые символы.
Комбинация "\$" указывает на то, что символ "$" трактуется как обычный символ, а не как признак конца строки в регулярных выражениях. Аналогично, комбинация "\\" соответствует простому символу "\".
Экранированные "угловые скобки" — \<...\> — отмечают границы слова.
Угловые скобки должны экранироваться, иначе они будут интерпретироваться как простые символы.
Выражение "\<the\>" соответствует слову "the", и не соответствует словам "them", "there", "other" и т.п.
Знак вопроса — ? — означает, что предыдущий символ или регулярное выражение встречается 0 или 1 раз. В основном используется для поиска одиночных символов.
Знак "плюс" — + — указывает на то, что предыдущий символ или выражение встречается 1 или более раз. Играет ту же роль, что и символ "звездочка" (*), за исключением случая нулевого количества вхождений.
Экранированные "фигурные скобки" — \{ \} — задают число вхождений предыдущего выражения.
Экранирование фигурных скобок — обязательное условие, иначе они будут интерпретироваться как простые символы. Такой порядок использования, технически, не является частью основного набора правил построения регулярных выражений.
Выражение "[0-9]\{5\}" — в точности соответствует подстроке из пяти десятичных цифр (символов из диапазона от 0 до 9, включительно).
![]() |
В "классической" (не совместимой с POSIX) версии awk, фигурные скобки не могут быть использованы. Однако, в gawk предусмотрен ключ --re-interval, который позволяет использовать (неэкранированные) фигурные скобки.
Язык программирования Perl и некоторые версии egrep не требуют экранирования фигурных скобок. |
Круглые скобки — ( ) — предназначены для выделения групп регулярных выражений. Они полезны при использовании с оператором "|" и при извлечении подстроки с помощью команды expr.
Вертикальная черта — | — выполняет роль логического оператора "ИЛИ" в регулярных выражениях и служит для задания набора альтернатив.
![]() |
Некоторые версии sed, ed и ex поддерживают экранированные версии регулярных выражений, описанные выше. |
Это альтернативный способ указания диапазона символов.
Класс [:alnum:] — соответствует алфавитным символам и цифрам. Эквивалентно выражению A-Za-z0-9.
Класс [:alpha:] — соответствует символам алфавита. Эквивалентно выражению A-Za-z.
Класс [:blank:] — соответствует символу пробела или символу табуляции.
Класс [:cntrl:] — соответствует управляющим символам (control characters).
Класс [:digit:] — соответствует набору десятичных цифр. Эквивалентно выражению 0-9.
Класс [:graph:] (печатаемые и псевдографические символы) — соответствует набору символов из диапазона ASCII 33 - 126. Это то же самое, что и класс [:print:], за исключением символа пробела.
Класс [:lower:] — соответствует набору алфавитных символов в нижнем регистре. Эквивалентно выражению a-z.
Класс [:print:] (печатаемые символы) — соответствует набору символов из диапазона ASCII 32 - 126. По своему составу этот класс идентичен классу [:graph:], описанному выше, за исключением того, что в этом классе дополнительно присутствует символ пробела.
Класс [:space:] — соответствует пробельным символам (пробел и горизонтальная табуляция).
Класс [:upper:] — соответствует набору символов алфавита в верхнем регистре. Эквивалентно выражению A-Z.
Класс [:xdigit:] — соответствует набору шестнадцатиричных цифр. Эквивалентно выражению 0-9A-Fa-f.
![]() |
Вообще, символьные классы POSIX требуют заключения в кавычки или двойные квадратные скобки ([[ ]]).
Эти символьные классы могут использоваться, с некоторыми ограничениями, даже в операциях подстановки имен файлов (globbing).
Примеры использования символьных классов в сценариях вы найдете в Пример 12-17 и Пример 12-18. |
Sed, awk и Perl, используемые в сценариях в качестве фильтров, могут принимать регулярные выражения в качестве входных аргументов. См. Пример A-13 и Пример A-19.
В качестве стандартного руководства по этой сложной теме можно порекомендовать "Mastering Regular Expressions", автор Friedl. Книга "Sed & Awk" (авторы Dougherty и Robbins) так же дает полное и ясное описание регулярных выражений (см. раздел Библиография).
[47] В качестве простейшего регулярного выражения можно привести строку, не содержащую никаких метасимволов.
[48] Поскольку с помощью sed, awk и grep обрабатывают одиночные строки, то обычно символ перевода строки не принимается во внимание. В тех же случаях, когда производится разбор многострочного текста, метасимвол "точка" будет соответствовать символу перевода строки.
Bash, сам по себе, не распознает регулярные выражения. Но в сценариях можно использовать команды и утилиты, такие как sed и awk, которые прекрасно справляются с обработкой регулярных выражений.
Фактически, Bash может выполнять подстановку имен файлов, этот процесс называется "globbing", но при этом не используется стандартный набор регулярных выражений. Вместо этого, при выполнении подстановки имен файлов, производится распознавание и интерпретация шаблонных символов. В число интерпретируемых шаблонов входят символы * и ?, списки символов в квадратных скобках и некоторые специальные символы (например ^, используемый для выполнения операции отрицания). Применение шаблонных символов имеет ряд важных ограничений. Например, если имена файлов начинаются с точки (например так: .bashrc), то они не будут соответствовать шаблону, содержащему символ *. [49] Аналогично, символ ? в операции подстановки имен файлов имеет иной смысл, нежели в регулярных выражениях.
Bash выполняет подстановку имен файлов при использовании аргументов командной строки без кавычек. Команда echo наглядно демонстрирует это.
![]() |
Bash предоставляет возможность изменить порядок интерпретации специальных символов во время подстановки имен файлов. Так команда set -f запрещает подстановку, а ключи nocaseglob и nullglob в shopt изменяют характер подстановки. |
См. также Пример 10-4.
[49] Подстановка таких имен файлов возможна, но только при условии, что символ точки будет явно присутствовать в шаблоне.
Запуск сценария приводит к запуску дочернего командного интерпретатора. Который выполняет интерпретацию и исполнение списка команд, содержащихся в файле сценария, точно так же, как если бы они были введены из командной строки. Любой сценарий запускается как дочерний процесс родительской командной оболочки, той самой, которая выводит перед вами строку приглашения к вводу на консоли или в окне xterm.
Сценарий может, так же, запустить другой дочерний процесс, в своей подоболочке. Это позволяет сценариям распараллелить процесс обработки данных по нескольким задачам, исполняемым одновременно.
|
Как правило, внешние команды в сценариях порождают дочерние процессы, в то время как встроенные команды Bash — нет. По этой причине, встроенные команды выполняются много быстреесвоих "внешних" аналогов. |
Список команд в круглых скобках
Список команд, в круглых скобках, исполняется в подоболочке.
![]() |
Значения переменных, определенных в дочерней оболочке, не могут быть переданы родительской оболочке. Они недоступны родительскому процессу. Фактически, они ведут себя как локальные переменные. |