统计进程CPU使用率并按使用率从大到小排序
#!/bin/bash
# 文件名: show_cpu_usage.sh
# 作者: wanghongwei
# 日期: 2025年1月20日
# 版本: 1.0
# 描述: 统计进程 CPU 使用率并按使用率从大到小排序
# 使用方式:./show_cpu_usage.sh [-i interval]
# 初始化存储进程信息的数组
declare -A process_cpu_usage
declare -g temp_file=""
# 显示脚本使用方法
show_usage() {
echo "Usage: $0 [-i interval]"
echo " -i interval: 采样时间间隔,单位为秒,默认为 1 秒。"
exit 1
}
# 函数:检查输入是否为有效的正整数且不为 0
is_valid_number() {
local num=$1
if [[ $num =~ ^[1-9][0-9]*$ ]]; then
return 0
else
return 1
fi
}
# 函数:获取进程的 CPU 时间信息
get_process_cpu_time() {
local process_id=$1
local cpu_info=$(cat /proc/$process_id/stat 2>/dev/null)
if [[ -z $cpu_info ]]; then
echo "Error: Failed to read /proc/$process_id/stat"
return 1
fi
# 解析 stat 文件中的信息
# 格式为 pid comm state ppid pgrp session tty_nr tpgid flags minflt cminflt majflt cmajflt utime stime cutime cstime priority nice num_threads itrealvalue starttime vsize rss rsslim startcode endcode startstack kstkesp ksteip signal blocked sigignore sigcatch wchan nswap cnswap 0 0 1 2 3 4 5 6
read -r pid comm state ppid pgrp session tty_nr tpgid flags minflt cminflt majflt cmajflt utime stime cutime cstime priority nice num_threads itrealvalue starttime vsize rss rsslim startcode endcode startstack kstkesp ksteip signal blocked sigignore sigcatch wchan nswap cnswap _ <<<"$cpu_info"
local total_time=$((utime + stime + cutime + cstime))
echo $total_time
return 0
}
# 函数:计算 CPU 使用率
calculate_process_cpu_usage() {
local process_id=$1
local previous_time=$2
local current_time=$(get_process_cpu_time $process_id)
local elapsed_time=$(( $3 ))
if [[ $elapsed_time -eq 0 ]]; then
echo 0
else
local cpu_usage=$(echo "scale=2; (($current_time - $previous_time) / $elapsed_time)" | bc)
echo $cpu_usage
fi
}
# 获取进程的 CPU 使用率
get_cpu_usage() {
# 存储上一次的 CPU 时间和时间戳
declare -A previous_cpu_times
declare -A previous_timestamps
# 第一次读取
for pid in /proc/[0-9]*; do
pid=${pid##*/}
previous_cpu_times[$pid]=$(get_process_cpu_time $pid)
previous_timestamps[$pid]=$(date +%s)
done
# 等待一段时间,以便获取时间差
sleep $1 # 使用传入的采样时间间隔
# 第二次读取
for pid in /proc/[0-9]*; do
pid=${pid##*/}
local curr_time=$(get_process_cpu_time $pid)
local prev_time=${previous_cpu_times[$pid]}
local prev_timestamp=${previous_timestamps[$pid]}
local curr_timestamp=$(date +%s)
local elapsed_time=$((curr_timestamp - prev_timestamp))
if [[ -n $prev_time ]]; then
local usage=$(calculate_process_cpu_usage $pid $prev_time $elapsed_time)
process_cpu_usage[$pid]=$usage
fi
done
}
# 对 CPU 使用率进行排序并输出
sort_and_print() {
# 将关联数组转换为适合排序的格式
temp_file=$(mktemp)
if [[ -z $temp_file ]]; then
echo "Error: Failed to create temporary file."
exit 1
fi
for pid in "${!process_cpu_usage[@]}"; do
echo "${process_cpu_usage[$pid]} $pid" >> $temp_file
done
# 对文件中的内容进行排序
sort -nr $temp_file | while read -r usage pid; do
printf "| %-8s | %-20s |\n" "$pid" "${usage}%"
done
rm $temp_file
}
# 输出表格的标题
print_title() {
echo "+----------+----------------------+"
printf "| %-8s | %-20s |\n" "PID" "CPU Usage (%)"
echo "+----------+----------------------+"
}
# 信号处理函数,用于在程序结束或异常终止时删除临时文件
cleanup() {
rm -f $temp_file 2>/dev/null
}
main() {
interval=1
if [ $# -eq 2 ] && [ "$1" == "-i" ]; then
if is_valid_number $2; then
interval=$2
else
echo "Error: Invalid interval value. Please provide a positive integer greater than 0."
show_usage
fi
elif [ $# -eq 1 ] && [ "$1" == "-i" ]; then
echo "Error: Interval value is missing after -i."
show_usage
elif [ $# -ne 0 ]; then
show_usage
fi
print_title
get_cpu_usage $interval
sort_and_print
exit 0
}
# 注册信号处理函数
trap cleanup EXIT
main $1 $2
作者:wanghongwei
版权声明:本作品遵循<CC BY-NC-ND 4.0>版权协议,商业转载请联系作者获得授权,非商业转载请附上原文出处链接及本声明。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统