Чтение онлайн

ЖАНРЫ

Искусство программирования на языке сценариев командной оболочки

Купер Мендель

Шрифт:

# cleanup

# Для работы сценария требуются права root.

cd /var/log

cat /dev/null > messages

cat /dev/null > wtmp

echo "Лог-файлы очищены."

Здесь нет ничего необычного, это простая последовательность команд, которая может быть набрана в командной строке с консоли или в xterm. Преимущество размещения последовательности команд в скрипте состоит в том, что вам не придется всякий раз набирать эту последовательность вручную. Кроме того, скрипты легко могут быть модифицированы или обобщены для разных применений.

Пример 2-2. cleanup: Расширенная версия предыдущего сценария.

#!/bin/bash

# cleanup, version 2

#

Для работы сценария требуются права root.

LOG_DIR=/var/log

ROOT_UID=0 # Только пользователь с $UID 0 имеет привилегии root.

LINES=50 # Количество сохраняемых строк по-умолчанию.

E_XCD=66 # Невозможно сменить каталог?

E_NOTROOT=67 # Признак отсутствия root-привилегий.

if [ "$UID" -ne "$ROOT_UID" ]

then

echo "Для работы сценария требуются права root."

exit $E_NOTROOT

fi

if [ -n "$1" ]

# Проверка наличия аргумента командной строки.

then

lines=$1

else

lines=$LINES # Значение по-умолчанию, если число не задано в командной строке

fi

# Stephane Chazelas предложил следующее,

#+ для проверки корректности аргумента, переданного из командной строки,

#+ правда это достаточно сложно для данного руководства.

#

# E_WRONGARGS=65 # Не числовой аргумент

#

# case "$1" in

# "" ) lines=50;;

# *[!0-9]*) echo "Usage: `basename $0` file-to-cleanup"; exit $E_WRONGARGS;;

# * ) lines=$1;;

# esac

#

#* Конец проверки корректности аргумента

cd $LOG_DIR

if [ `pwd` != "$LOG_DIR" ] # или if [ "$PWD" != "$LOG_DIR" ]

# Не в /var/log?

then

echo "Невозможно перейти в каталог $LOG_DIR."

exit $E_XCD

fi # Проверка каталога перед очисткой лог-файлов.

# более эффективный вариант:

#

# cd /var/log || {

# echo "Невозможно перейти в требуемый каталог." >&2

# exit $E_XCD;

# }

tail -$lines messages > mesg.temp # Сохранить последние строки в лог-файле.

mv mesg.temp messages

# cat /dev/null > messages

#* Необходимость этой команды отпала, поскольку очистка выполняется выше.

cat /dev/null > wtmp # команды ': > wtmp' и '> wtmp' имеют тот же эффект.

echo "Лог-файлы очищены."

exit 0

# Возвращаемое значение 0

#+ указывает на успешное завершение работы сценария.

Если вы не желаете полностью вычищать системные логи, то выше представлена улучшенная версия предыдущего

сценария. Здесь сохраняются последние несколько строк (по-умолчанию -- 50).

Если файл сценария начинается с последовательности #!, которая в мире UNIX называется sha-bang, то это указывает системе какой интерпретатор следует использовать для исполнения сценария. Это двухбайтовая последовательность, или [ 4 ]– - специальный маркер, определяющий тип сценария, в данном случае -- сценарий командной оболочки (см. man magic). Более точно, sha-bang определяет интерпретатор, который вызывается для исполнения сценария, это может быть командная оболочка (shell), иной интерпретатор или утилита [ 5 ] .

4

Некоторые разновидности UNIX (основанные на 4.2BSD) требуют, чтобы эта последовательность состояла из 4-х байт, за счет добавления пробела после !, #! /bin/sh.

5

В shell-скриптах последовательность #! должна стоять самой первой и задает интерпретатор (sh или bash). Интерпретатор, в свою очередь, воспринимает эту строку как комментарий, поскольку она начинается с символа #.

Если в сценарии имеются еще такие же строки, то они воспринимаются как обычный комментарий.

#!/bin/bash

echo "Первая часть сценария."

a=1

#!/bin/bash

# Это *НЕ* означает запуск нового сценария.

echo "Вторая часть сценария."

echo $a # Значение переменной $a осталось равно 1.

#!/bin/sh

#!/bin/bash

#!/usr/bin/perl

#!/usr/bin/tcl

#!/bin/sed -f

#!/usr/awk -f

Каждая, из приведенных выше сигнатур, приводит к вызову различных интерпретаторов, будь то /bin/sh– - командный интерпретатор по-умолчанию (bash для Linux-систем), либо иной [ 6 ] . При переносе сценариев с сигнатурой #!/bin/sh на другие UNIX системы, где в качестве командного интерпретатора задан другой shell, вы можете лишиться некоторых особенностей, присущих bash. Поэтому такие сценарии должны быть POSIX совместимыми [ 7 ] .

6

Эта особенность позволяет использовать различные хитрости.

#!/bin/rm

# Самоуничтожающийся сценарий.

# Этот скрипт ничего не делает -- только уничтожает себя.

WHATEVER=65

echo "Эта строка никогда не будет напечатана."

exit $WHATEVER # Не имеет смысла, поскольку работа сценария завершается не здесь.

Попробуйте запустить файл README с сигнатурой #!/bin/more (предварительно не забудьте сделать его исполняемым).

7

Portable Operating System Interface, попытка стандартизации UNIX-подобных операционных систем.

Обратите внимание на то, что сигнатура должна указывать правильный путь к интерпретатору, в противном случае вы получите сообщение об ошибке -- как правило это "Command not found".

Сигнатура #! может быть опущена, если вы не используете специфичных команд. Во втором примере (см. выше) использование сигнатуры #! обязательно, поскольку сценарий использует специфичную конструкцию присваивания значения переменной lines=50. Еще раз замечу, что сигнатура #!/bin/sh вызывает командный интерпретатор по-умолчанию -- /bin/bash в Linux-системах.

Поделиться с друзьями: