Спец курс (Автоматизация процесса проектирования)/Лекция 2 (BASH) — различия между версиями
Vidokq (обсуждение | вклад) |
Vidokq (обсуждение | вклад) |
||
Строка 84: | Строка 84: | ||
done | done | ||
echo "-----------------" | echo "-----------------" | ||
+ | </source> | ||
+ | |||
+ | |||
+ | == Завершение и код завершения == | ||
+ | |||
+ | * ...эта часть Bourne shell покрыта мраком, тем не менее все пользуются ею. | ||
+ | Chet Ramey | ||
+ | * Команда exit может использоваться для завершения работы сценария, точно так же как и в программах на языке C. Кроме того, она может возвращать некоторое значение, которое может быть проанализировано вызывающим процессом. | ||
+ | |||
+ | * Каждая команда возвращает код завершения (иногда код завершения называют возвращаемым значением ). В случае успеха команда должна возвращать 0, а в случае ошибки -- ненулевое значение, которое, как правило, интерпретируется как код ошибки. Практически все команды и утилиты UNIX возвращают 0 в случае успешного завершения, но имеются и исключения из правил. | ||
+ | |||
+ | * Аналогичным образом ведут себя функции, расположенные внутри сценария, и сам сценарий, возвращая код завершения. Код, возвращаемый функцией или сценарием, определяется кодом возврата последней команды. Команде exit можно явно указать код возврата, в виде: exit nnn, где nnn -- это код возврата (число в диапазоне 0 - 255). | ||
+ | |||
+ | * {{ЖЛампа|24px}}Note : Когда работа сценария завершается командой exit без параметров, то код возврата сценария определяется кодом возврата последней исполненной командой. | ||
+ | |||
+ | |||
+ | Код возврата последней команды хранится в специальной переменной $?. После исполнения кода функции, переменная $? хранит код завершения последней команды, исполненной в функции. Таким способом в Bash передается "значение, возвращаемое" функцией. После завершения работы сценария, код возврата можно получить, обратившись из командной строки к переменной $?, т.е. это будет код возврата последней команды, исполненной в сценарии. | ||
+ | |||
+ | Пример 6-1. завершение / код завершения | ||
+ | <source lang="bash"> | ||
+ | #!/bin/bash | ||
+ | |||
+ | echo hello | ||
+ | echo $? # код возврата = 0, поскольку команда выполнилась успешно. | ||
+ | |||
+ | lskdf # Несуществующая команда. | ||
+ | echo $? # Ненулевой код возврата, поскольку команду выполнить не удалось. | ||
+ | |||
+ | echo | ||
+ | |||
+ | exit 113 # Явное указание кода возврата 113. | ||
+ | # Проверить можно, если набрать в командной строке "echo $?" | ||
+ | # после выполнения этого примера. | ||
+ | |||
+ | # В соответствии с соглашениями, 'exit 0' указывает на успешное завершение, | ||
+ | #+ в то время как ненулевое значение означает ошибку. | ||
+ | |||
+ | </source>Переменная $? особенно полезна, когда необходимо проверить результат исполнения команды (см. Пример 12-27 и Пример 12-13). | ||
+ | |||
+ | Note | ||
+ | Символ !, может выступать как логическое "НЕ" для инверсии кода возврата. | ||
+ | |||
+ | Пример 6-2. Использование символа ! для логической инверсии кода возврата | ||
+ | |||
+ | <source lang="bash"> | ||
+ | true # встроенная команда "true". | ||
+ | echo "код возврата команды \"true\" = $?" # 0 | ||
+ | |||
+ | ! true | ||
+ | echo "код возврата команды \"! true\" = $?" # 1 | ||
+ | # Обратите внимание: символ "!" от команды необходимо отделять пробелом. | ||
+ | # !true вызовет сообщение об ошибке "command not found" | ||
</source> | </source> |
Версия 16:45, 11 февраля 2018
Содержание |
Перенаправление потока вывода в файл
Дескриптор файла -- это просто число, по которому система идентифицирует открытые файлы. Рассматривайте его как упрощенную версию указателя на файл.
- COMMAND_OUTPUT > # Перенаправление stdout (вывода) в файл. Если файл отсутствовал, то он создается, иначе -- перезаписывается.
ls -lR > dir-tree.list # Создает файл, содержащий список дерева каталогов.
- : > filename # Операция > усекает файл "filename" до нулевой длины. Если до выполнения операции файла не существовало, то создается новый файл с нулевой длиной (тот же эффект дает команда 'touch'). Символ : выступает здесь в роли местозаполнителя, не выводя ничего.
- COMMAND_OUTPUT >> Перенаправление stdout (вывода) в файл. Создает новый файл, если он отсутствовал, иначе -- дописывает в конец файла.
- 1>filename # Перенаправление вывода (stdout) в файл "filename".
- 1>>filename # Перенаправление вывода (stdout) в файл "filename", файл открывается в режиме добавления.
- 2>filename # Перенаправление stderr в файл "filename".
- 2>>filename # Перенаправление stderr в файл "filename", файл открывается в режиме добавления.
- &>filename # Перенаправление stdout и stderr в файл "filename".
Поток ввода
- < FILENAME # Ввод из файла. Парная команде ">", часто встречается в комбинации с ней.
Перенаправление потоков
- 2>&1 # Перенаправляется stderr на stdout. Сообщения об ошибках передаются туда же, куда и стандартный вывод.
- i>&j # Перенаправляется файл с дескриптором i в j. Вывод в файл с дескриптором i передается в файл с дескриптором j.
- >&j # Перенаправляется файл с дескриптором 1 (stdout) в файл с дескриптором j. Вывод на stdout передается в файл с дескриптором j.
- [j]<>filename # Файл "filename" открывается на чтение и запись, и связывается с дескриптором "j". Если "filename" отсутствует, то он создается. Если дескриптор "j" не указан, то, по-умолчанию, берется дескриптор 0, stdin. Как одно из применений этого -- запись в конкретную позицию в файле.
echo 1234567890 > File # Записать строку в файл "File". exec 3<> File # Открыть "File" и связать с дескриптором 3. read -n 4 <&3 # Прочитать 4 символа. echo -n . >&3 # Записать символ точки. exec 3>&- # Закрыть дескриптор 3. cat File # ==> 1234.67890 # Произвольный доступ, да и только!
Закрытие дескрипторов файлов
- n<&- Закрыть дескриптор входного файла n.
- 0<&-, <&- Закрыть stdin.
- n>&- Закрыть дескриптор выходного файла n.
- 1>&-, >&- Закрыть stdout.
Дочерние процессы наследуют дескрипторы открытых файлов. По этой причине и работают конвейеры. Чтобы предотвратить наследование дескрипторов -- закройте их перед запуском дочернего процесса.
# В конвейер передается только stderr. exec 3>&1 # Сохранить текущее "состояние" stdout. ls -l 2>&1 >&3 3>&- | grep bad 3>&- # Закрыть дескр. 3 для 'grep' (но не для 'ls'). # ^^^^ ^^^^ exec 3>&- # Теперь закрыть его для оставшейся части сценария.
Конвееры
- | # Конвейер (канал). Универсальное средство для объединения команд в одну цепочку. Похоже на ">", но на самом деле -- более обширная. Используется для объединения команд, сценариев, файлов и программ в одну цепочку (конвейер).
cat *.txt | sort | uniq > result-file
- Допускается перенаправление нескольких потоков в один файл.
ls -yz >> command.log 2>&1 # Сообщение о неверной опции "yz" в команде "ls" будет записано в файл "command.log". # Поскольку stderr перенаправлен в файл.
Операции перенаправления и/или конвейеры могут комбинироваться в одной командной строке.
command < input-file > output-file command1 | command2 | command3 > output-file
Генерация псевдослучайных чисел
- $RANDOM -- внутренняя функция Bash (не константа), которая возвращает псевдослучайные целые числа в диапазоне 0 - 32767. Функция $RANDOM не должна использоваться для генераци ключей шифрования.
- Если вам нужны случайные числа не превышающие определенного числа, воспользуйтесь оператором деления по модулю (остаток от деления).
- Если вы желаете ограничить диапазон "снизу", то просто производите генерацию псевдослучайных чисел в цикле до тех пор, пока не получите число большее нижней границы.
#!/bin/bash # $RANDOM возвращает различные случайные числа при каждом обращении к ней. # Диапазон изменения: 0 - 32767 (16-битовое целое со знаком). MAXCOUNT=10 count=1 echo echo "$MAXCOUNT случайных чисел:" echo "-----------------" while [ "$count" -le $MAXCOUNT ] # Генерация 10 ($MAXCOUNT) случайных чисел. do number=$RANDOM echo $number let "count += 1" # Нарастить счетчик. done echo "-----------------"
Завершение и код завершения
- ...эта часть Bourne shell покрыта мраком, тем не менее все пользуются ею.
Chet Ramey
- Команда exit может использоваться для завершения работы сценария, точно так же как и в программах на языке C. Кроме того, она может возвращать некоторое значение, которое может быть проанализировано вызывающим процессом.
- Каждая команда возвращает код завершения (иногда код завершения называют возвращаемым значением ). В случае успеха команда должна возвращать 0, а в случае ошибки -- ненулевое значение, которое, как правило, интерпретируется как код ошибки. Практически все команды и утилиты UNIX возвращают 0 в случае успешного завершения, но имеются и исключения из правил.
- Аналогичным образом ведут себя функции, расположенные внутри сценария, и сам сценарий, возвращая код завершения. Код, возвращаемый функцией или сценарием, определяется кодом возврата последней команды. Команде exit можно явно указать код возврата, в виде: exit nnn, где nnn -- это код возврата (число в диапазоне 0 - 255).
-
Note : Когда работа сценария завершается командой exit без параметров, то код возврата сценария определяется кодом возврата последней исполненной командой.
Код возврата последней команды хранится в специальной переменной $?. После исполнения кода функции, переменная $? хранит код завершения последней команды, исполненной в функции. Таким способом в Bash передается "значение, возвращаемое" функцией. После завершения работы сценария, код возврата можно получить, обратившись из командной строки к переменной $?, т.е. это будет код возврата последней команды, исполненной в сценарии.
#!/bin/bash echo hello echo $? # код возврата = 0, поскольку команда выполнилась успешно. lskdf # Несуществующая команда. echo $? # Ненулевой код возврата, поскольку команду выполнить не удалось. echo exit 113 # Явное указание кода возврата 113. # Проверить можно, если набрать в командной строке "echo $?" # после выполнения этого примера. # В соответствии с соглашениями, 'exit 0' указывает на успешное завершение, #+ в то время как ненулевое значение означает ошибку.
Note Символ !, может выступать как логическое "НЕ" для инверсии кода возврата.
Пример 6-2. Использование символа ! для логической инверсии кода возврата
true # встроенная команда "true". echo "код возврата команды \"true\" = $?" # 0 ! true echo "код возврата команды \"! true\" = $?" # 1 # Обратите внимание: символ "!" от команды необходимо отделять пробелом. # !true вызовет сообщение об ошибке "command not found"