菜单

Administrator
发布于 2025-11-08 / 29 阅读
0

常用脚本

metrics

监控/proc/下pid各项指标 cpu、内存、磁盘io、磁盘读写带宽、exe、cmdline 可以结合管道符进行排序 如:bash metrics.sh |sort -k 2 -r -q

INTERVAL=${1:-1}

if (( BASH_VERSINFO[0] < 4 )); then
    echo "err: need bash4.0 or later" >&2
    exit 1
fi
if [[ $EUID -ne 0 ]]; then
   echo "err: suggest root exec " >&2
fi
CLK_TCK=$(getconf CLK_TCK)

human_readable() {
    local bytes=$1
    local unit="B"
    if (( bytes >= 1024 )); then
        bytes=$(( bytes / 1024 ))
        unit="K"
        if (( bytes >= 1024 )); then
            bytes=$(( bytes / 1024 ))
            unit="M"
            if (( bytes >= 1024 )); then
                bytes=$(( bytes / 1024 ))
                unit="G"
            fi
        fi
    fi
    echo "$bytes$unit"
}

echo "Collecting first data snapshot (interval ${INTERVAL}s)..."
declare -A s1_cpu s1_read_bytes s1_write_bytes s1_read_iops s1_write_iops

for pid_dir in /proc/[0-9]*; do
    pid="${pid_dir##*/}"
    [[ -d "$pid_dir" ]] || continue

    if [[ -r "${pid_dir}/stat" ]]; then
        read -r -a stat_data < "${pid_dir}/stat"
        s1_cpu[$pid]=$(( ${stat_data[13]} + ${stat_data[14]} ))
    fi

    if [[ -r "${pid_dir}/io" ]]; then
        while read -r key value; do
            case "$key" in
                rchar:) s1_read_bytes[$pid]=$value ;;
                wchar:) s1_write_bytes[$pid]=$value ;;
                syscr:) s1_read_iops[$pid]=$value ;;
                syscw:) s1_write_iops[$pid]=$value ;;
            esac
        done < "${pid_dir}/io"
    fi
done

sleep "$INTERVAL"

printf "%-8s %-10s %-10s %-8s %-8s %-10s %-10s %-8s %s\n" \
    "PID" "CPU(%)" "MEM(RSS)" "R_IOPS" "W_IOPS" "DISK_R/s" "DISK_W/s" "EXE" "COMMAND-LINE"

for pid_dir in /proc/[0-9]*; do
    pid="${pid_dir##*/}"
    [[ -v "s1_cpu[$pid]" ]] || continue

    mem_rss_kb=0
    if [[ -r "${pid_dir}/status" ]]; then
        while read -r key value _; do
            if [[ "$key" == "VmRSS:" ]]; then
                mem_rss_kb=$value; break
            fi
        done < "${pid_dir}/status"
    fi
    mem_rss_hr=$(human_readable $(( mem_rss_kb * 1024 )))

    cmdline="-"
    if [[ -r "${pid_dir}/cmdline" ]]; then
        read -r -d '' cmdline_raw < "${pid_dir}/cmdline"
        if [[ -z "$cmdline_raw" ]]; then
            cmdline="[$(<"${pid_dir}/comm")]"
        else
            cmdline="${cmdline_raw//$'\0'/ }"
        fi
    fi

    exe="-"
    exe=$(readlink -f "/proc/${pid}/exe" 2>/dev/null)

    cpu_usage="0.00"
    if [[ -r "${pid_dir}/stat" ]]; then
        read -r -a stat_data2 < "${pid_dir}/stat"
        cpu_ticks_diff=$(( (${stat_data2[13]} + ${stat_data2[14]}) - ${s1_cpu[$pid]:-0} ))
        total_ticks=$(( CLK_TCK * INTERVAL ))
        if (( total_ticks > 0 )); then
            cpu_usage_scaled=$(( cpu_ticks_diff * 10000 / total_ticks ))
            cpu_usage=$(printf "%d.%02d" $((cpu_usage_scaled / 100)) $((cpu_usage_scaled % 100)))
        fi
    fi
   #-----------split-----------#
    read_rate=0; write_rate=0; read_iops=0; write_iops=0
    if [[ -r "${pid_dir}/io" ]]; then
        s2_read_bytes=0; s2_write_bytes=0; s2_read_iops=0; s2_write_iops=0
        while read -r key value; do
            case "$key" in
                rchar:) s2_read_bytes=$value ;;
                wchar:) s2_write_bytes=$value ;;
                syscr:) s2_read_iops=$value ;;
                syscw:) s2_write_iops=$value ;;
            esac
        done < "${pid_dir}/io"
        read_rate=$(( (s2_read_bytes - ${s1_read_bytes[$pid]:-0}) / INTERVAL ))
        write_rate=$(( (s2_write_bytes - ${s1_write_bytes[$pid]:-0}) / INTERVAL ))
        read_iops=$(( (s2_read_iops - ${s1_read_iops[$pid]:-0}) / INTERVAL ))
        write_iops=$(( (s2_write_iops - ${s1_write_iops[$pid]:-0}) / INTERVAL ))
    fi
    read_rate_hr=$(human_readable $read_rate)
    write_rate_hr=$(human_readable $write_rate)

    printf "%-8s %-10s %-10s %-8s %-8s %-10s %-10s %-8s %s\n" \
        "$pid" \
        "$cpu_usage" \
        "$mem_rss_hr" \
        "$read_iops" \
        "$write_iops" \
        "$read_rate_hr" \
        "$write_rate_hr" \
        "$exe" \
        "${cmdline}"
done

测试