Advanced Bash-Scripting Guide: Искусство программирования на языке сценариев командной оболочки | ||
---|---|---|
Назад | Глава 27. /dev и /proc | Вперед |
Фактически, каталог /proc -- это виртуальная файловая система. Файлы, в каталоге /proc, содержат информацию о процессах, о состоянии и конфигурации ядра и системы.
bash$ cat /proc/devices Character devices: 1 mem 2 pty 3 ttyp 4 ttyS 5 cua 7 vcs 10 misc 14 sound 29 fb 36 netlink 128 ptm 136 pts 162 raw 254 pcmcia Block devices: 1 ramdisk 2 fd 3 ide0 9 md bash$ cat /proc/interrupts CPU0 0: 84505 XT-PIC timer 1: 3375 XT-PIC keyboard 2: 0 XT-PIC cascade 5: 1 XT-PIC soundblaster 8: 1 XT-PIC rtc 12: 4231 XT-PIC PS/2 Mouse 14: 109373 XT-PIC ide0 NMI: 0 ERR: 0 bash$ cat /proc/partitions major minor #blocks name rio rmerge rsect ruse wio wmerge wsect wuse running use aveq 3 0 3007872 hda 4472 22260 114520 94240 3551 18703 50384 549710 0 111550 644030 3 1 52416 hda1 27 395 844 960 4 2 14 180 0 800 1140 3 2 1 hda2 0 0 0 0 0 0 0 0 0 0 0 3 4 165280 hda4 10 0 20 210 0 0 0 0 0 210 210 ... bash$ cat /proc/loadavg 0.13 0.42 0.27 2/44 1119
Сценарии командной оболочки могут извлекать необходимую информацию из соответствующих файлов в каталоге /proc. [1]
bash$ cat /proc/filesystems | grep iso9660 iso9660
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 '%l\n' # 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, так как попытка записи в некоторые файлы может повредить файловую систему или привести к краху системы.
[1] |
Отдельные системные команды, такие как procinfo, free, vmstat, lsdev и uptime делают это именно таким образом. |