当前位置: 首页 > news >正文

Linux shell编程:监控进程CPU使用率并使用 perf 抓取高CPU进程信息

0. 概要

本文将介绍一个用于监控一组进程CPU使用率的Shell脚本,,当检测到某进程的CPU使用率超出阈值时,使用 perf 工具抓取该进程的详细信息。
本shell脚本为了能在普通嵌入式系统上运行做了妥协和优化。

1. shell脚本流程的简要图示:

在这里插入图片描述

2. perf介绍

perf 是 Linux 内核提供的一个强大性能分析工具,能够用于分析和调优系统性能。它支持多种事件类型,如CPU时钟、缓存命中/未命中、中断等。

在本脚本中,当某个进程的CPU使用率超过设定阈值(例如80%)时,会使用以下命令抓取该进程的详细性能数据:

perf record -F 99 -e cpu-clock -p $pid -g -o "perf-$process_name.data" -- sleep $perf_sleep_time
  • -F 99:以每秒99次的频率进行采样。
  • -e cpu-clock:采样的事件类型为CPU时钟周期。
  • -p $pid:指定要采样的进程ID。
  • -g:记录调用栈信息,帮助分析性能瓶颈。
  • -o "perf-$process_name.data":将采样数据输出到指定文件中。
  • -- sleep $perf_sleep_time:持续采样时间为10秒。

通过抓取高CPU使用率进程的详细性能数据,我们可以深入分析性能瓶颈,找出导致高CPU使用的原因,从而进行针对性的优化。

更多介绍请查看:
使用perf(火焰图)查看热点函数和系统调用最大延迟函数
如何使用perf 统计cpu和内存?

3. shell脚本详解

  1. 日志文件配置

    # Log file location
    LOGFILE="process_monitor.log"
    # Redirect standard input, output, and error to log file
    exec 1>>"$LOGFILE"
    exec 2>>"$LOGFILE"
    

    这部分代码配置日志文件,并将标准输入、输出和错误重定向到日志文件中。

  2. 后台运行检测

    # Check if the script is already running
    if [ "$1" != "background" ]; then"$0" background &exit 0
    fi
    

    这段代码用于检测脚本是否已经在后台运行,如果没有,则重新以后台模式启动自己。

  3. 初始化上次报告时间文件

    # Initialize last report time file
    last_report_time_file="last_report_time"
    touch "$last_report_time_file"
    

    初始化用于存储上次报告时间的文件。

  4. 获取CPU总时间的函数

    # Function to get the total CPU usage from /proc/stat
    get_total_cpu_time() {awk '/^cpu / {print $2 + $3 + $4 + $5 + $6 + $7 + $8}' /proc/stat
    }
    

    /proc/stat 文件中获取CPU总时间。

  5. 获取进程CPU时间的函数

    # Function to get the process CPU usage from /proc/[pid]/stat
    get_process_cpu_time() {pid=$1awk '{print $14 + $15 + $16 + $17}' /proc/$pid/stat
    }
    

    /proc/[pid]/stat 文件中获取指定进程的CPU时间。

  6. 计算进程CPU使用率的函数

    # Function to calculate CPU usage of a process
    calculate_cpu_usage() {pid=$1prev_process_time=$(get_process_cpu_time "$pid")prev_total_time=$(get_total_cpu_time)sleep 1process_time=$(get_process_cpu_time "$pid")total_time=$(get_total_cpu_time)process_delta=$((process_time - prev_process_time))total_delta=$((total_time - prev_total_time))cpu_usage=$((100 * process_delta / total_delta))echo $cpu_usage
    }
    

    计算指定进程的CPU使用率。

  7. 加载上次报告时间的函数

    # Function to load the last report time for a PID
    load_last_report_time() {pid=$1grep "^$pid=" "$last_report_time_file" | cut -d'=' -f2
    }
    

    从文件中加载上次报告时间。

  8. 保存上次报告时间的函数

    # Function to save the last report time for a PID
    save_last_report_time() {pid=$1time=$2sed -i "/^$pid=/d" "$last_report_time_file"echo "$pid=$time" >> "$last_report_time_file"
    }
    

    将上次报告时间保存到文件中。

  9. 进程监控列表

    # List of process names to monitor
    process_names="top systemd"
    

    定义需要监控的进程名称列表。

  10. 监控循环

 while true; docurrent_time=$(date +%s)for process_name in $process_names; doif [ -n "$DEBUG_ON" ]; thenecho "Checking process: $process_name"fi# Find all matching process PIDspids=$(ps aux | grep "$process_name" | grep -v grep | awk '{print $2}')for pid in $pids; do# Calculate CPU usagecpu_usage=$(calculate_cpu_usage "$pid")# Check if CPU usage exceeds $max_cpu_usage%if [ "$cpu_usage" -gt $max_cpu_usage ]; thenecho "High CPU usage detected for process '$process_name' (PID: $pid): $cpu_usage%"# Load the last report time for this PIDlast_time=$(load_last_report_time "$pid")last_time=${last_time:-0}time_diff=$((current_time - last_time))# Check if the last report time is more than 60 seconds agoif [ "$time_diff" -ge 60 ]; thenecho "time_diff: $time_diff, perf record -F 99 -e cpu-clock -p $pid -g -o perf-$process_name.data -- sleep $perf_sleep_time"ps -p "$pid" -o pid,ppid,cmd,%mem,%cpu >> "$LOGFILE"perf record -F 99 -e cpu-clock -p $pid -g -o "perf-$process_name.data" -- sleep $perf_sleep_time# Save the last report time for this PIDsave_last_report_time "$pid" "$current_time"# sleep for 1 secondsleep 1fielseif [ -n "$DEBUG_ON" ]; thenecho "CPU usage for process '$process_name' (PID: $pid): $cpu_usage%"fifidonedonedone

这是主要的监控循环,定期检查指定进程的CPU使用率,并在超过阈值时使用 perf 抓取详细信息。

4. 完整脚本实现

以下是优化后的Shell脚本,适用于普通嵌入式系统:

#!/bin/sh# This script monitors the CPU usage of a list of processesDEBUG_ON=1
# Log file location
LOGFILE="process_monitor.log"# Redirect standard input, output, and error to log file
exec 1>>"$LOGFILE"
exec 2>>"$LOGFILE"# Check if the script is already running
if [ "$1" != "background" ]; then"$0" background &exit 0
fi# Initialize last report time file
last_report_time_file="last_report_time"
touch "$last_report_time_file"# Function to get the total CPU usage from /proc/stat
get_total_cpu_time() {awk '/^cpu / {print $2 + $3 + $4 + $5 + $6 + $7 + $8}' /proc/stat
}# Function to get the process CPU usage from /proc/[pid]/stat
get_process_cpu_time() {pid=$1awk '{print $14 + $15 + $16 + $17}' /proc/$pid/stat
}# Function to calculate CPU usage of a process
calculate_cpu_usage() {pid=$1prev_process_time=$(get_process_cpu_time "$pid")prev_total_time=$(get_total_cpu_time)sleep 1process_time=$(get_process_cpu_time "$pid")total_time=$(get_total_cpu_time)process_delta=$((process_time - prev_process_time))total_delta=$((total_time - prev_total_time))cpu_usage=$((100 * process_delta / total_delta))echo $cpu_usage
}# Function to load the last report time for a PID
load_last_report_time() {pid=$1grep "^$pid=" "$last_report_time_file" | cut -d'=' -f2
}# Function to save the last report time for a PID
save_last_report_time() {pid=$1time=$2sed -i "/^$pid=/d" "$last_report_time_file"echo "$pid=$time" >> "$last_report_time_file"
}# List of process names to monitor
process_names="top systemd"echo "Monitoring CPU usage for processes: $process_names"# Perf sleep time
perf_sleep_time=10
max_cpu_usage=80# Monitoring loop
while true; docurrent_time=$(date +%s)for process_name in $process_names; doif [ -n "$DEBUG_ON" ]; thenecho "Checking process: $process_name"fi# Find all matching process PIDs# pids=$(ps | grep "$process_name" | grep -v grep | awk '{print $1}')pids=$(ps aux | grep "$process_name" | grep -v grep | awk '{print $2}')for pid in $pids; do# Calculate CPU usagecpu_usage=$(calculate_cpu_usage "$pid")# Check if CPU usage exceeds $max_cpu_usage%if [ "$cpu_usage" -gt $max_cpu_usage ]; thenecho "High CPU usage detected for process '$process_name' (PID: $pid): $cpu_usage%"# Load the last report time for this PIDlast_time=$(load_last_report_time "$pid")last_time=${last_time:-0}time_diff=$((current_time - last_time))# Check if the last report time is more than 60 seconds agoif [ "$time_diff" -ge 60 ]; thenecho "time_diff: $time_diff, perf record -F 99 -e cpu-clock -p $pid -g -o perf-$process_name.data -- sleep $perf_sleep_time"ps -p "$pid" -o pid,ppid,cmd,%mem,%cpu >> "$LOGFILE"perf record -F 99 -e cpu-clock -p $pid -g -o "perf-$process_name.data" -- sleep $perf_sleep_time# Save the last report time for this PIDsave_last_report_time "$pid" "$current_time"# sleep for 1 secondsleep 1fielseif [ -n "$DEBUG_ON" ]; thenecho "CPU usage for process '$process_name' (PID: $pid): $cpu_usage%"fifidonedonedone

通过这种方式,我们可以有效地监控嵌入式系统中高CPU使用率的进程,并通过 perf 工具获取详细的性能数据,帮助我们进行性能调优和问题排查。

相关文章:

Linux shell编程:监控进程CPU使用率并使用 perf 抓取高CPU进程信息

0. 概要 本文将介绍一个用于监控一组进程CPU使用率的Shell脚本,,当检测到某进程的CPU使用率超出阈值时,使用 perf 工具抓取该进程的详细信息。 本shell脚本为了能在普通嵌入式系统上运行做了妥协和优化。 1. shell脚本流程的简要图示&#…...

Linux网络编程的套接字分析(其一,基本知识)

文章目录 套接字的类型流套接字数据报套接字原始套接字 套接字地址获取套接字地址 协议族和地址族 套接字的类型 Linux系统的套接字有三类:流套接字(SOCK_STREAM),数据报套接字(SOCK_DGRAM),原始套接字(SOCK_RAM)。 流套接字 用于面向连接…...

后端Web开发之Maven

1.java项目构建工具maven介绍 Maven是apache旗下的一个开源项目。Apache软件基金会,成立于1999年7月,是目前世界上最大的最受欢迎的开源(源代码开放)软件基金会也是一一个专门为支持开源项目而生的非盈利性组织。 apache开源项目…...

前端创新实践:用JavaScript打造网页扫码新体验

引言 简述扫码技术在现代网页应用中的普及和重要性。引入JavaScript实现网页扫码功能的创新性和实用性。 扫码技术概述 介绍扫码技术的原理和在不同平台(如微信、支付宝)的应用。讨论扫码技术对用户体验和业务流程的影响。 JavaScript实现网页扫码的…...

AWS CLI命令行

参考文档:在 macOS 上安裝,更新和卸載 AWS CLI 版本 1 - AWS Command Line Interface...

领导力培养的底层逻辑

领导力就是从人们从他们现在的地方,到他们从未去过的地方的能力--基辛格 ## 1. 领导力的一些观点 ## 2. 五种习惯十大承诺 ## 3. 需要领导的场景 ## 4.0 组织中谁需要领导力 ## 5.0 领导力培养 领导力培养的底层逻辑可以简单描述为以下几个方面: 管理…...

【MATLAB第107期】基于MATLAB的Morris局部敏感性分析模型(无目标函数)

【MATLAB第107期】基于MATLAB的Morris局部敏感性分析模型(无目标函数) 更正: 局部敏感性分析方法 一、原理介绍 1.基本原理: Morris方法采用概率均匀抽样的方式估计每个模型输入因子在输出结果中的重要性,通过比较系…...

Tomcat搭建JSPServlet

一、Tomcat环境搭建 1. 将项目变为Web项目 选中项目,点击Help中的Find Action 搜索Add Framework Support 勾选Web Application 出现这些文件就是成功了 2. 配置Tomcat 点击Edit Configurations 点击加号,选择Tomcat Server Local Deployment栏下点击…...

32位定点数和32/64位浮点数的二进制生成方法

问题由来 定点数和浮点数在嵌入式软件处理和FPGA算法方面使用比较普遍,但是遇到FPGA实现32位定点数的处理,想要仿真时,突然发现全网都在讲浮点数和定点数的格式和理论,几乎没有生成的快捷方法,好在一片文章出现了一点…...

STM32利用arm-dsp库进行FIR低通滤波【详细】

arm-dsp库官方已经封装好了,使用的时候需要把dsp库移植到工程里面,具体怎么移植网上可以找到教程 这里直接说怎么用FIR的流程: 一、Matlab里面生成所配置的阶数和系数 1、在Matlab命令窗口输入fdatool,回车,会弹出一个新窗口 2…...

Efficient-KAN 源码详解

Efficient-KAN源码链接 Efficient-KAN (GitHub) 改进细节 1.内存效率提升 KAN网络的原始实现的性能问题主要在于它需要扩展所有中间变量以执行不同的激活函数。对于具有in_features个输入和out_features个输出的层,原始实现需要将输入扩展为shape为(batch_size, out_featur…...

Jlink commander使用方法(附指令大全)

Jlinkcmd它可以方便用户在非仿真的情况下,hold内核、单步、全速、设置断点、查看内核和外设寄存器、读取flash代码等等,方便大家拥有最高的权限查看在运行中的MCU情况,查找非IDE仿真情况下,MCU运行异常的原因。 目录 驱动安装 …...

Java SpringBoot实现PDF转图片

不是单页图片,是多页PDF转成一张图片的逻辑。 我这里的场景是PDF转成图片之后返回给前端,前端再在图片上实现签字,并且可拖拽的逻辑,就是签订合同的场景。 但是这里只写后端多页PDF转图片的逻辑。 先说逻辑,后面直接…...

elasticsearch SQL:在Elasticsearch中启用和使用SQL功能

❃博主首页 &#xff1a; 「码到三十五」 &#xff0c;同名公众号 :「码到三十五」&#xff0c;wx号 : 「liwu0213」 ☠博主专栏 &#xff1a; <mysql高手> <elasticsearch高手> <源码解读> <java核心> <面试攻关> ♝博主的话 &#xff1a…...

Java 并发编程:线程变量 ThreadLocal

大家好&#xff0c;我是栗筝i&#xff0c;这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 029 篇文章&#xff0c;在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验&#xff0c;并希望进…...

【OpenHarmony4.1 之 U-Boot 2024.07源码深度解析】018 - init_sequence_f 各函数源码分析(二)

【OpenHarmony4.1 之 U-Boot 2024.07源码深度解析】018 - init_sequence_f 各函数源码分析(二) 一、arch_cpu_init二、arch_cpu_init系列文章汇总:《【OpenHarmony4.1 之 U-Boot 源码深度解析】000 - 文章链接汇总》 本文链接:《【OpenHarmony4.1 之 U-Boot 2024.07源码深度…...

LVS原理——详细介绍

目录 介绍 lvs简介 LVS作用 LVS 的优势与不足 LVS概念与相关术语 LVS的3种工作模式 LVS调度算法 LVS-dr模式 LVS-tun模式 ipvsadm工具使用 实验 nat模式集群部署 实验环境 webserver1配置 webserver2配置 lvs配置 dr模式集群部署 实验环境 router 效果呈现…...

MYSQL 5.7.36 等保 建设记录

文章目录 前言一、开启审计日志1.1 查看当前状态1.2 开启方式1.3 查看开启后状态 二、密码有效期2.1 查看当前状态2.2 开启方式2.3 查看开启后状态 三、密码复杂度3.1 查看当前状态3.2 开启方式3.3 查看开启后状态 四、连接控制4.1 查看当前状态4.2 开启方式4.3 查看开启后状态…...

fatal: unable to access ‘https://github.com/xxxxx

ubuntu中git克隆项目异常 git clone https://github.com/xxx Cloning into ‘xxx’… fatal: unable to access ‘https://github.com/xxx/xx.git/’: Could not resolve host: github.com 解决办法使用命令&#xff1a; git config --global http.proxy git config --global…...

从零开始的CPP(38)——递归与动态规划

leetcode46 给定一个不含重复数字的数组 nums &#xff0c;返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]示例 2&#xff1a; 输入&#…...

像素冒险工坊初体验:维度裂变器真实使用报告,文字创作从未如此有趣

像素冒险工坊初体验&#xff1a;维度裂变器真实使用报告&#xff0c;文字创作从未如此有趣 1. 走进像素冒险工坊 当我第一次打开像素语言维度裂变器时&#xff0c;仿佛穿越回了16-bit游戏黄金年代。这款基于MT5-Zero-Shot-Augment核心引擎构建的文本增强工具&#xff0c;彻底…...

Python高效开发技巧汇总

这是一篇关于Python开发的技术文章示例内容&#xff0c;可以替换为真实文章内容。...

告别默认样式:C# WinForm自定义最大化最小化关闭按钮实战(含资源文件管理技巧)

深度定制WinForm界面&#xff1a;从按钮替换到资源管理的完整解决方案 1. 为什么需要自定义窗体控制按钮&#xff1f; 在商业软件和创意应用中&#xff0c;用户界面的视觉体验往往决定了用户对产品的第一印象。WinForm作为.NET生态中成熟的桌面应用框架&#xff0c;其默认的窗体…...

OpenProject:构建高效团队协作的终极开源项目管理平台

OpenProject&#xff1a;构建高效团队协作的终极开源项目管理平台 【免费下载链接】openproject OpenProject is the leading open source project management software. 项目地址: https://gitcode.com/GitHub_Trending/op/openproject OpenProject 是一款领先的开源项…...

CosyVoice2-0.5B效果实测:背景噪音音频对克隆效果影响量化

CosyVoice2-0.5B效果实测&#xff1a;背景噪音音频对克隆效果影响量化 1. 测试背景与目的 声音克隆技术近年来发展迅猛&#xff0c;阿里开源的CosyVoice2-0.5B作为一款强大的零样本语音合成系统&#xff0c;能够在短短3秒内复刻任意说话人的声音。但在实际应用中&#xff0c;…...

别再只会让舵机转圈了!用Arduino和SG90实现精准角度控制的保姆级教程

从转圈到精准控制&#xff1a;Arduino与SG90舵机的高级应用指南 第一次接触舵机时&#xff0c;我们往往满足于让它简单地来回转动——这确实很有趣&#xff0c;就像给玩具注入了生命。但当你真正想用它构建一个机械臂、智能云台或是自动喂食器时&#xff0c;这种粗放的控制方式…...

LongCat-Video:AI视频生成技术的范式突破与实践指南

LongCat-Video&#xff1a;AI视频生成技术的范式突破与实践指南 【免费下载链接】LongCat-Video 项目地址: https://ai.gitcode.com/hf_mirrors/meituan-longcat/LongCat-Video 在数字内容创作领域&#xff0c;AI视频生成技术正经历从实验性探索到产业化应用的关键转折…...

【Typst源文件】Typst 标题层级与样式定制

1. 标题层级&#xff1a;等号 的使用 Typst 使用等号 来定义标题&#xff0c;等号的数量决定标题层级。理论上没有层级限制&#xff0c;可以根据文档结构无限嵌套。一级标题二级标题三级标题四级标题五级标题六级标题七级标题八级标题使用示例IntroductionBackgroundPrevious…...

从零配置深度学习环境:Anaconda+PyTorch GPU版+Jupyter全流程详解

从零构建深度学习开发环境&#xff1a;Anaconda与PyTorch GPU实战指南 在开始深度学习项目前&#xff0c;搭建一个稳定高效的开发环境是每个开发者必须跨越的第一道门槛。不同于普通Python开发&#xff0c;深度学习环境需要处理GPU驱动、CUDA加速库、框架版本匹配等一系列复杂问…...

FPGA新手入门:用Verilog手搓一个交通灯控制器(附完整代码与仿真)

FPGA实战&#xff1a;从零构建智能交通灯控制系统的Verilog全流程指南 引言 第一次接触FPGA开发时&#xff0c;我被硬件描述语言的独特思维方式所吸引。与软件编程不同&#xff0c;Verilog让我们能够直接描述硬件电路的行为。交通灯控制系统作为数字电路设计的经典案例&#xf…...