KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программирование » Мендель Купер - Искусство программирования на языке сценариев командной оболочки

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

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Мендель Купер, "Искусство программирования на языке сценариев командной оболочки" бесплатно, без регистрации.
Перейти на страницу:

kernel_version=$( awk '{ print $3 }' /proc/version )


CPU=$( awk '/model name/ {print $4}' < /proc/cpuinfo )


if [ $CPU = Pentium ]

then

выполнить_ряд_специфичных_команд

...

else

выполнить_ряд_других_специфичных_команд

...

fi


В каталоге /proc вы наверняка заметите большое количество подкаталогов, с не совсем обычными именами, состоящими только из цифр. Каждый из них соответствует исполняющемуся процессу, а имя каталога -- это ID (идентификатор) процесса. Внутри каждого такого подкаталога находится ряд файлов, в которых содержится полезная информация о соответствующих процессах. Файлы stat и status хранят статистику работы процесса, cmdline -- команда, которой был запущен процесс, exe -- символическая ссылка на исполняемый файл программы. Здесь же вы найдете ряд других файлов, но, с точки зрения написания сценариев, они не так интересны, как эти четыре.

Пример 27-1. Поиск файла программы по идентификатору процесса

#!/bin/bash

# pid-identifier.sh: Возвращает полный путь к исполняемому файлу программы по идентификатору процесса (pid).


ARGNO=1 # Число, ожидаемых из командной строки, аргументов.

E_WRONGARGS=65

E_BADPID=66

E_NOSUCHPROCESS=67

E_NOPERMISSION=68

PROCFILE=exe


if [ $# -ne $ARGNO ]

then

echo "Порядок использования: `basename $0` PID-процесса" >&2 # Сообщение об ошибке на >stderr.

exit $E_WRONGARGS

fi


ps ax


pidno=$( ps ax | grep $1 | awk '{ print $1 }' | grep $1 )

# Проверка наличия процесса с заданным pid в списке, выданном командой "ps", поле #1.

# Затем следует убедиться, что этот процесс не был запущен этим сценарием ('ps').

# Это делает последний "grep $1".

if [ -z "$pidno" ] # Если после фильтрации получается пустая строка,

then # то это означает, что в системе нет процесса с заданым pid.

echo "Нет такого процесса."

exit $E_NOSUCHPROCESS

fi


# Альтернативный вариант:

# if ! ps $1 > /dev/null 2>&1

# then # в системе нет процесса с заданым pid.

# echo "Нет такого процесса."

# exit $E_NOSUCHPROCESS

# fi


if [ ! -r "/proc/$1/$PROCFILE" ] # Проверить право на чтение.

then

echo "Процесс $1 найден, однако..."

echo "у вас нет права на чтение файла /proc/$1/$PROCFILE."

exit $E_NOPERMISSION # Обычный пользователь не имеет прав

# на доступ к некоторым файлам в каталоге /proc.

fi


# Последние две проверки могут быть заменены на:

# if ! kill -0 $1 > /dev/null 2>&1 # '0' -- это не сигнал, но

# команда все равно проверит наличие

# процесса-получателя.

# then echo "Процесс с данным PID не найден, либо вы не являетесь его владельцем" >&2

# exit $E_BADPID

# fi


exe_file=$( ls -l /proc/$1 | grep "exe" | awk '{ print $11 }' )

# Или exe_file=$( ls -l /proc/$1/exe | awk '{print $11}' )

#

# /proc/pid-number/exe -- это символическая ссылка

# на исполняемый файл работающей программы.


if [ -e "$exe_file" ] # Если файл /proc/pid-number/exe существует...

then # то существует и соответствующий процесс.

echo "Исполняемый файл процесса #$1: $exe_file."

else

echo "Нет такого процесса."

fi


# В большинстве случаев, этот, довольно сложный сценарий, может быть заменен командой

# ps ax | grep $1 | awk '{ print $5 }'

# В большинстве, но не всегда...

# поскольку пятое поле листинга,выдаваемого командой 'ps', это argv[0] процесса,

# а не путь к исполняемому файлу.

#

# Однако, оба следующих варианта должны работать безотказно.

# find /proc/$1/exe -printf '%ln'

# lsof -aFn -p $1 -d txt | sed -ne 's/^n//p'


# Автор последнего комментария: Stephane Chazelas.


exit 0

Пример 27-2. Проверка состояния соединения

#!/bin/bash


PROCNAME=pppd # демон ppp

PROCFILENAME=status # Что смотреть.

NOTCONNECTED=65

INTERVAL=2 # Период проверки -- раз в 2 секунды.


pidno=$( ps ax | grep -v "ps ax" | grep -v grep | grep $PROCNAME | awk '{ print $1 }' )

# Найти идентификатор процесса 'pppd', 'ppp daemon'.

# По пути убрать из листинга записи о процессах, порожденных сценарием.

#

# Однако, как отмечает Oleg Philon,

#+ Эта последовательность команд может быть заменена командой "pidof".

# pidno=$( pidof $PROCNAME )

#

# Мораль:

#+ Когда последовательность команд становится слишком сложной,

#+ это повод к тому, чтобы поискать более короткий вариант.


if [ -z "$pidno" ] # Если получилась пустая строка, значит процесс не запущен.

then

echo "Соединение не установлено."

exit $NOTCONNECTED

else

echo "Соединение установлено."; echo

fi


while [ true ] # Бесконечный цикл.

do


if [ ! -e "/proc/$pidno/$PROCFILENAME" ]

# Пока работает процесс, файл "status" существует.

then

echo "Соединение разорвано."

exit $NOTCONNECTED

fi


netstat -s | grep "packets received" # Получить некоторые сведения о соединении.

netstat -s | grep "packets delivered"


sleep $INTERVAL

echo; echo


done


exit 0


# Как обычно, этот сценарий может быть остановлен комбинацией клавиш Control-C.


# Упражнение:

# ----------

# Добавьте возможность завершения работы сценария, по нажатии на клавишу "q".

# Это сделает скрипт более жружественным к пользователю.

Будьте предельно осторожны при работе с файловой системой /proc, так как попытка записи в некоторые файлы может повредить файловую систему или привести к краху системы.


Глава 28. /dev/zero и /dev/null

/dev/null

Псевдоустройство /dev/null -- это, своего рода, "черная дыра" в системе. Это, пожалуй, самый близкий смысловой эквивалент. Все, что записывается в этот файл, "исчезает" навсегда. Попытки записи или чтения из этого файла не дают, ровным счетом, никакого результата. Тем не менее, псевдоустройство /dev/null вполне может пригодиться.

Подавление вывода на stdout.

cat $filename >/dev/null

# Содержимое файла $filename не появится на stdout.


Подавление вывода на stderr (from Пример 12-2).

rm $badname 2>/dev/null

# Сообщение об ошибке "уйдет в никуда".


Подавление вывода, как на stdout, так и на stderr.

cat $filename 2>/dev/null >/dev/null

# Если "$filename" не будет найден, то вы не увидите сообщения об ошибке.

# Если "$filename" существует, то вы не увидите его содержимое.

# Таким образом, вышеприведенная команда ничего не выводит на экран.

#

# Такая методика бывает полезной, когда необходимо лишь проверить код завершения команды

#+ и нежелательно выводить результат работы команды на экран.

#

# cat $filename &>/dev/null

# дает тот же результат, автор примечания Baris Cicek.


Удаление содержимого файла, сохраняя, при этом, сам файл, со всеми его правами доступа (очистка файла) (из Пример 2-1 и Пример 2-2):

cat /dev/null > /var/log/messages

# : > /var/log/messages дает тот же эффект, но не порождает дочерний процесс.


cat /dev/null > /var/log/wtmp


Автоматическая очистка содержимого системного журнала (logfile) (особенно хороша для борьбы с надоедливыми рекламными идентификационными файлами ("cookies")):

Пример 28-1. Удаление cookie-файлов

if [ -f ~/.netscape/cookies ] # Удалить, если имеются.

then

rm -f ~/.netscape/cookies

fi


ln -s /dev/null ~/.netscape/cookies

# Теперь, все cookie-файлы, вместо того, чтобы сохраняться на диске, будут "вылетать в трубу".

/dev/zero

Подобно псевдоустройству /dev/null, /dev/zero так же является псевдоустройством, с той лишь разницей, что содержит нули. Информация, выводимая в этот файл, так же бесследно исчезает. Чтение нулей из этого файла может вызвать некоторые затруднения, однако это можно сделать, к примеру, с помощью команды od или шестнадцатиричного редактора. В основном, /dev/zero используется для создания заготовки файла с заданой длиной.

Пример 28-2. Создание файла подкачки (swapfile), с помощью /dev/zero

#!/bin/bash


# Создание файла подкачки.

# Этот сценарий должен запускаться с правами root.


ROOT_UID=0 # Для root -- $UID 0.

E_WRONG_USER=65 # Не root?


FILE=/swap

BLOCKSIZE=1024

MINBLOCKS=40

SUCCESS=0


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

then

echo; echo "Этот сценарий должен запускаться с правами root."; echo

exit $E_WRONG_USER

fi


blocks=${1:-$MINBLOCKS} # По-умолчанию -- 40 блоков,

#+ если размер не задан из командной строки.

# Ниже приводится эквивалентный набор команд.

# --------------------------------------------------

# if [ -n "$1" ]

# then

# blocks=$1

# else

# blocks=$MINBLOCKS

# fi

# --------------------------------------------------


if [ "$blocks" -lt $MINBLOCKS ]

then

blocks=$MINBLOCKS # Должно быть как минимум 40 блоков.

fi


echo "Создание файла подкачки размером $blocks блоков (KB)."

dd if=/dev/zero of=$FILE bs=$BLOCKSIZE count=$blocks # "Забить" нулями.


mkswap $FILE $blocks # Назначить как файл подкачки.

swapon $FILE # Активировать.


echo "Файл подкачки создан и активирован."


exit $SUCCESS

Еще одна область применения /dev/zero -- "очистка" специального файла заданного размера, например файлов, монтируемых как loopback-устройства (см. Пример 13-6) или для безопасного удаления файла (см. Пример 12-42).

Пример 28-3. Создание электронного диска

#!/bin/bash

# ramdisk.sh


# "электронный диск" -- это область в ОЗУ компьютера

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*