Искусство программирования на языке сценариев командной оболочки [заметки]
1
Их так же называют встроенными конструкциями языка командной оболочки shell.
2
Многие особенности ksh88 и даже ksh93 перекочевали в Bash.
3
В соответствии с соглашениями, имена файлов с shell-скриптами, такими как Bourne shell и совместимыми, имеют расширение .sh. Все стартовые скрипты, которые вы найдете в /etc/rc.d, следуют этому соглашению.
4
Некоторые разновидности UNIX (основанные на 4.2BSD) требуют, чтобы эта последовательность состояла из 4-х байт, за счет добавления пробела после !, #! /bin/sh.
5
В shell-скриптах последовательность #! должна стоять самой первой и задает интерпретатор (sh или bash). Интерпретатор, в свою очередь, воспринимает эту строку как комментарий, поскольку она начинается с символа #.
Если в сценарии имеются еще такие же строки, то они воспринимаются как обычный комментарий.
#!/bin/bash
echo "Первая часть сценария."
a=1
#!/bin/bash
# Это *НЕ* означает запуск нового сценария.
echo "Вторая часть сценария."
echo $a # Значение переменной $a осталось равно 1.
6
Эта особенность позволяет использовать различные хитрости.
#!/bin/rm
# Самоуничтожающийся сценарий.
# Этот скрипт ничего не делает -- только уничтожает себя.
WHATEVER=65
echo "Эта строка никогда не будет напечатана."
exit $WHATEVER # Не имеет смысла, поскольку работа сценария завершается не здесь.
Попробуйте запустить файл README с сигнатурой #!/bin/more (предварительно не забудьте сделать его исполняемым).
7
Portable Operating System Interface, попытка стандартизации UNIX-подобных операционных систем.
8
Внимание: вызов Bash-скрипта с помощью команды sh scriptname отключает специфичные для Bash расширения, что может привести к появлению ошибки и аварийному завершению работы сценария.
9
Сценарий должен иметь как право на исполнение, так и право на чтение, поскольку shell должен иметь возможность прочитать скрипт.
10
Почему бы не запустить сценарий просто набрав название файла scriptname, если сценарий находится в текущем каталоге? Дело в том, что из соображений безопасности, путь к текущему каталогу "." не включен в переменную окружения $PATH. Поэтому необходимо явно указывать путь к текущему каталогу, в котором находится сценарий, т.е. ./scriptname.
11
Интерпретатор, встретив фигурные скобки, раскрывает их и возвращает полученный список команд, которые затем и исполняет.
12
Исключение: блок кода, являющийся частью конвейера, может быть запущен в дочернем процессе (subshell-е).
ls | { read firstline; read secondline; }
# Ошибка! Вложенный блок будет запущен в дочернем процессе,
# таким образом, вывод команды "ls" не может быть записан в переменные
# находящиеся внутри блока.
echo "Первая строка: $firstline; вторая строка: $secondline" # Не работает!
# Спасибо S.C.
13
Аргумент $0 устанавливается вызывающим процессом. В соответствии с соглашениями, этот параметр содержит имя файла скрипта. См. страницы руководства для execv (man execv).
14
Символ "!", помещенный в двойные кавычки, порождает сообщение об ошибке, если команда вводится с командной строки. Вероятно это связано с тем, что этот символ интерпретируется как попытка обращения к истории команд. Однако внутри сценариев такой прием проблем не вызывает.
Не менее любопытно поведение символа "\", употребляемого внутри двойных кавычек.
bash$ echo hello\!
hello!
bash$ echo "hello\!"
hello\!
bash$ echo -e x\ty
xty
bash$ echo -e "x\ty"
x y
(Спасибо Wayne Pollock за пояснения.)
15
"Разбиение на слова", в данном случае это означает разделение строки символов на некоторое число аргументов.
16
С флагом suid, на двоичных исполняемых файлах, надо быть очень осторожным, поскольку это может быть небезопасным. Установка флага suid на файлы-сценарии не имеет никакого эффекта.
17
В современных UNIX-системах, "sticky bit" больше не используется для файлов, только для каталогов.
18
Как указывает S.C., даже заключение строки в кавычки, при построении сложных условий проверки, может оказаться недостаточным. [ -n "$string" -o "$a" = "$b" ] в некоторых версиях Bash такая проверка может вызвать сообщение об ошибке, если строка $string пустая. Безопаснее, в смысле отказоустойчивости, было бы добавить какой-либо символ к, возможно пустой, строке: [ "x$string" != x -o "x$a" = "x$b" ] (символ "x" не учитывается).
19
PID текущего процесса хранится в переменной $$.
20
Слова "аргумент" и "параметр" очень часто используются как синонимы. В тексте данного документа, они применяются для обозначения одного и того же понятия, будь то аргумент, передаваемый скрипту из командной строки или входной параметр функции.
21
Применяется к аргументам командной строки или входным параметрам функций.
22
Если $parameter "пустой",в неинтерактивных сценариях, то это будет приводить к завершению с кодом возврата 127 ("command not found").
23
Эти команды являются встроенными командами языка сценариев командной оболочки (shell), в то время как while, case и т.п. -- являются зарезервированными словами.
24
Исключение из правил -- команда time, которая в официальной документации к Bash называется ключевым словом.
25
Опция -- это аргумент, который управляет поведением сценария и может быть либо включен, либо выключен. Аргумент, который объединяет в себе несколько опций (ключей), определяет поведение сценария в соответствии с отдельными опциями, объединенными в данном аргументе..
26
Как правило, исходные тексты подобных библиотек, на языке C, располагаются в каталоге /usr/share/doc/bash-?.??/functions.
Обратите внимание: ключ -f команды enable может отсутствовать в некоторых системах.
27
Тот же эффект можно получить с помощью typeset -fu.
28
Скрытыми считаются файлы, имена которых начинаются с точки, например, ~/.Xdefaults. Такие файлы не выводятся простой командой ls, и не могут быть удалены командой rm -rf *. Как правило, скрытыми делаются конфигурационные файлы в домашнем каталоге пользователя.
29
Это верно только для GNU-версии команды tr, поведение этой команды, в коммерческих UNIX-системах, может несколько отличаться.
30
Команда tar czvf archive_name.tar.gz * включит в архив все скрытые файлы (имена которых начинаются с точки) из вложенных подкаталогов. Это недокументированная "особенность" GNU-версии tar.
31
Она реализует алгоритм симметричного блочного шифрования, в противоположность алгоритмам шифрования с "открытым ключом", из которых широко известен pgp.
32
Демон -- это некий фоновый процесс, не привязанный ни к одной из терминальных сессий. Демоны предназначены для выполнения определенного круга задач либо через заданные промежутки времени, либо по наступлению какого либо события.
Слово "демон" ("daemon"), в греческой мифологии, употреблялось для обозначения призраков, духов, чего-то мистического, сверхестественного. В мире UNIX -- под словом демон подразумевается процесс, который "тихо" и "незаметно" выполняет свою работу.
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 для быстрого и легкого, но слабого, шифрования текстовых файлов.
cat $file | dd conv=swab,ebcdic > $file_encrypted
# Зашифрованный файл будет выглядеть как "абракадабра".
# опция swab добавлена для внесения большей неразберихи.
cat $file_encrypted | dd conv=swab,ascii > $file_plaintext
# Декодирование.
37
макроопределение -- это идентификатор, символическая константа, которая представляет некоторую последовательность команд, операций и параметров.
38
Команда userdel завершится неудачей, если удаляемый пользователь в этот момент работает с системой
39
Дополнительную информацию по записи компакт-дисков, вы найдете в статье Алекса Уизера (Alex Wither): Creating CDs, в октябрьском выпуске журнала Linux Journal за 1999 год.
40
Утилита mke2fs, с ключом -c, так же производит поиск поврежденных блоков.
41
Пользователи небольших, десктопных Linux-систем предпочитают утилиты попроще, например tar.
42
NAND -- логическая операция "И-НЕ". В общих чертах она напоминает вычитание.
43
Замещающая команда может быть внешней системной командой, внутренней (встроенной) командой или даже функцией в сценарии.
44
дескриптор файла -- это просто число, по которому система идентифицирует открытые файлы. Рассматривайте его как упрощенную версию указателя на файл.
45
При использрвании дескриптора с номером 5 могут возникать проблемы. Когда Bash порождает дочерний процесс, например командой exec, то дочерний процесс наследует дескриптор 5 как "открытый" (см. архив почты Чета Рамея (Chet Ramey), SUBJECT: RE: File descriptor 5 is held open) Поэтому, лучше не использовать этот дескриптор.
46
В качестве простейшего регулярного выражения можно привести строку, не содержащую никаких метасимволов.
47
[47]Поскольку с помощью sed, awk и grep обрабатывают одиночные строки, то обычно символ перевода строки не принимается во внимание. В тех же случаях, когда производится разбор многострочного текста, метасимвол "точка" будет соответствовать символу перевода строки.
#!/bin/bash
sed -e 'N;s/.*/[&]/' << EOF # Встроенный документ
line1
line2
EOF
# OUTPUT:
# [line1
# line2]
echo
awk '{ $0=$1 "\n" $2; if (/line.1/) {print}}' << EOF
line 1
line 2
EOF
# OUTPUT:
# line
# 1
# Спасибо S.C.
exit 0
48
Подстановка таких имен файлов возможна, но только при условии, что символ точки будет явно присутствовать в шаблоне.
~/[.]bashrc # Не будет соответствовать имени ~/.bashrc
~/?bashrc # То же самое.
# Метасимволы не могут соответствовать символу точки при подстановке имен файлов.
~/.[b]ashrc # Имя ~./bashrc будет соответствовать данному шаблону
~/.ba?hrc # Аналогично.
~/.bashr* # Аналогично.
# Установка ключа "dotglob" отключает такое поведение интерпретатора.
# Спасибо S.C.
49
Имеет тот же эффект, что и именованные каналы (временный файл), фактически, именованные каналы некогда использовались в операциях подстановки процессов.
50
Механизм косвенных ссылок на переменные (см. Пример 34-2) слишком неудобен для передачи аргументов по ссылке.
#!/bin/bash
ITERATIONS=3 # Количество вводимых значений.
icount=1
my_read () {
# При вызове my_read varname,
# выводит предыдущее значение в квадратных скобках,
# затем просит ввести новое значение.
local local_var
echo -n "Введите говое значение переменной "
eval 'echo -n "[$'$1'] "' # Прежнее значение.
read local_var
[ -n "$local_var" ] && eval $1=\$local_var
# Последовательность "And-list": если "local_var" не пуста, то ее значение переписывается в "$1".
}
echo
while [ "$icount" -le "$ITERATIONS" ]
do
my_read var
echo "Значение #$icount = $var"
let "icount += 1"
echo
done
# Спасибо Stephane Chazelas за этот поучительный пример.
exit 0
51
Команда return -- это встроенная команда Bash.
52
Herbert Mayer определяет рекурсию, как "...описание алгоритма с помощью более простой версии того же самого алгоритма..." Рекурсивной называется функция, которая вызывает самого себя.
53
Слишком глубокая рекурсия может вызвать крах сценария.
#!/bin/bash
recursive_function ()
{
(( $1 < $2 )) && recursive_function $(( $1 + 1 )) $2;
# Увеличивать 1-й параметр до тех пор,
#+ пока он не станет равным, или не превысит, второму параметру.
}
recursive_function 1 50000 # Глубина рекурсии = 50,000!
# Само собой -- Segmentation fault.
# Рекурсия такой глубины может "обрушить" даже программу, написанную на C,
#+ по исчерпании памяти, выделенной под сегмент стека.
# Спасибо S.C.
exit 0 # Этот сценарий завершает работу не здесь, а в результате ошибки Segmentation fault.
54
Однако, псевдонимы могут "раскручивать" позиционные параметры.
55
Это не относится к таким оболочкам, как csh, tcsh и другим, которые не являются производными от классической Bourne shell (sh).
56
Каталог /dev содержит специальные файлы -- точки монтирования физических и виртуальных устройств. Они занимают незначительное пространство на диске.
Некоторые из устройств, такие как /dev/null, /dev/zero или /dev/urandom -- являются виртуальными. Они не являются файлами физических устройств, система эмулирует эти устройства программным способом.
57
Блочное устройство читает и/или пишет данные целыми блоками, в отличие от символьных устройств, которые читают и/или пишут данные по одному символу. Примером блочного устройства может служить жесткий диск, CD-ROM. Примером символьного устройства -- клавиатура.
58
Отдельные системные команды, такие как procinfo, free, vmstat, lsdev и uptime делают это именно таким образом.
59
Bash debugger (автор: Rocky Bernstein) частично возмещает этот недостаток.
60
В соответствии с соглашениями, сигнал с номером 0 соответствует команде exit.
61
Установка этого бита на файлы сценариев не имеет никакого эффекта.
62
ANSI -- аббревиатура от American National Standards Institute.
63
См. статью Marius van Oers, Unix Shell Scripting Malware, а также ссылку на Denning в разделе Литература.
64
Chet Ramey обещал ввести в Bash ассоциативные массивы (они хорошо знакомы программистам, работающим с языком Perl) в одном из следующих релизов Bash.
65
Кто может -- тот делает. Кто не может... тот получает сертификат MCSE.
66
Если адресное пространство не указано, то, по-умолчанию, к обработке принимаются все строки.
67
Указание кода завершения за пределами установленного диапазона, приводит к возврату ошибочных кодов. Например, exit 3809 в
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
Сейчас во многих школах, институтах и других учебных заведениях можно встретить компьютеры старого парка, уже отслужившие свое как морально, так и физически. На таких компьютерах можно изучать разве что Dos, что далеко от реалий сегодняшнего дня. К тому же у большинства, как правило, жесткий диск уже в нерабочем состоянии. Но и выбросить жалко, а новых никто не дает. Различные спонсоры, меценаты, бывает, подарят компьютер (один) и радуются, как дети. Спасибо, конечно, большое, но проблемы, как вы понимаете, этот компьютер в общем не решает, даже наоборот, усугубляет, работать на старых уже как-то не хочется, теперь просто есть с чем сравнивать.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.