Получение информации о процессах в стиле BASH 4

BASH
При написании BASH-скриптов распространённой практикой является считывание любой информации о процессах с помощью утилиты ps в сочетании с awk. В большинстве случаев это делается не ради кроссплатформенности (ps весьма ограниченно кроссплатформенна), а просто в силу непонимания возможностей BASH и принципиального отсутствия желания писать на нём более-менее «традиционный» код вместо нагромождения pipe'ов.

В данном посте я покажу, что код на BASH может оперировать вполне «традиционными» собственными структурами данных — и при этом с минимальным использованием внешних утилит.

С целью наглядной демонстрации встроенных языковых средств BASH 4-й версии, предлагаю вашему вниманию «продвинутый» вариант pgrep на базе традиционного pgrep'а из состава ps-utils:


#!/bin/bash
shopt -s extglob; set +H

my_pgrep () {
local PROC_NAME=$1

local pid key i
local -a arr 
local -A procInfo uid2name

 while IFS=':' read -a arr; do
  uid2name[${arr[2]}]=${arr[0]}
 done < <(getent passwd)
 while read pid; do
  while IFS=':'$'\x09' read -a arr; do
   arr[1]=${arr[1]##+([[:space:]])}   
   if (( ${#arr[@]}>2 )); then
    key=${arr[0],,}    
    for ((i=1; i<${#arr[@]}; i++)); do
     procInfo["${key}__${i}"]=${arr[$i]}
    done   
   else    
    procInfo[${arr[0],,}]=${arr[1]}
   fi
  done </proc/$pid/status
# Здесь Вы можете использовать любую информацию из /proc/$pid/status, она лежит в хэше procInfo
  printf "[pid=%s,ppid=%s(%s),user=%s] %s\n" \
            $pid \
            ${procInfo[ppid]} \
            "$(</proc/${procInfo[ppid]}/comm)" \
            "${uid2name[${procInfo[uid__1]}]}" \
            "$(xargs -0 </proc/$pid/cmdline)"   
 done < <(pgrep $PROC_NAME)
}


Использовать my_pgrep можно, например, так:

my_pgrep zabbix_server

( Обратите внимание на то, что BASH не поддерживает, к сожалению, вложенных структур, из-за чего списки внутри элементов хеша пришлось эмулировать добавлением индекса в конец ключа, разделяя индекс и ключ символами "__". У BASH, безусловно, имеется масса пробелов по части функционала. )

Профит данного подхода в том, что вся информация о процессе оказывается в хэш-массиве procInfo, и как в случае с любой структурой данных — эту информацию с минимальным overhead'ом можно запрашивать сколько угодно раз, пользуясь простой и удобной семантикой ( наподобие procInfo[threads] ).

Именно так поступают разработчики на том же Python: я встречал немало примеров чтения информации о процессах напрямую из /proc. Непонятно только, что мешает Shell-скриптерам делать то же самое…

0 комментариев

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.