ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

CPU飙高排查实战:从Windows到Linux的完整定位思路

CPU飙高排查实战:从Windows到Linux的完整定位思路 做开发、做运维或者哪怕只是自己组了台电脑玩游戏CPU飙高这个问题大概率都撞上过。尤其是线上环境告警群里突然来一条“CPU使用率100%”那一刻的心情谁搞谁知道。这章是从我这些年实战里整理出来的一套排查思路从Windows到Linux从查进程到抓线程从工具到套路一条龙讲清楚。新入行的照着这个流程走一遍基本能把问题定位到具体模块老手也可以用来查漏补缺看看自己是不是漏了某个环节。先说清楚一个原则排查CPU问题顺序永远是“先定性、再定位、后处理”。一上来就kill进程、重启服务那是赌博不是排查。很多时候问题处置完了你都不知道凶手是谁下次换个马甲又来了。所以这篇内容我把大部分篇幅放在“怎么查”和“怎么看”上最后的处理反而是最小的环节。1. 先定性再动手CPU飙高不是只有一种“高”1.1 高负载和高使用率是两码事很多人开口就是“CPU爆了”但CPU使用率utilization和系统负载load average严格来说是两个维度的指标。我打个比方CPU是收银台使用率是收银员忙不忙负载是柜台前面排了多少人。收银员忙到冒烟使用率100%但队伍很短说明收银效率没问题收银员闲得很使用率20%队伍却越排越长那一定不是收银速度的问题而是前面某个环节卡住了。放到系统里这个“卡住”通常是IO等待或者锁等待。Linux下用uptime或者top看load average如果负载很高但CPU的us%并不高就别在CPU上浪费时间了优先去看磁盘IO、网络IO、锁竞争。反过来如果CPU使用率干到100%负载也高那才是真正的计算资源不够或者代码在空转。Windows下没有直接的load average概念但性能监视器里加一个“Processor Queue Length”计数器如果这个值长期大于CPU核心数说明CPU调度队列里积压了大量线程本质上和Linux的高负载是一回事。1.2 用户态、内核态、中断和IO等待方向完全不同拿到top或vmstat输出先别看进程先看这行汇总。CPU时间分成几块指标含义典型场景us用户态CPU业务代码、死循环、复杂计算sy内核态CPU系统调用频繁、驱动问题、锁竞争id空闲一切正常waIO等待磁盘慢、网络慢、swap频繁st被虚拟机管理程序偷走宿主机资源争抢、云服务器超卖us高问题大概率在你的程序里——算法复杂度爆炸、死循环、频繁创建线程都在这一类。sy高就有意思了往往是系统调用过于频繁典型的比如Java应用里疯狂打日志、高并发下的锁竞争、或者某些驱动疯狂触发中断。wa高说明CPU在等数据这时候换个更快的磁盘可能比加CPU核数更管用。st高是云服务器特有的说明宿主机上其他虚拟机在抢CPU你的机器再大也白搭。我见过最典型的误判是wa明明很高一群人盯着代码优化业务逻辑优化了两周一点效果没有最后发现是日志盘满了IO全卡在写日志上。所以先看这几项指标能少走一大半弯路。2. Windows下CPU飙高的快速排查实战2.1 任务管理器先看这四列Windows环境下90%的人第一步都是开任务管理器但多数人只盯着CPU那一列看哪个进程最高然后就不知道怎么往下走了。其实任务管理器能把信息看全切到“详细信息”页签把PID、CPU、内存、句柄数、线程数这五列都显示出来按CPU降序排列。这里有个坑要提醒任务管理器里的CPU%是个采样值不是瞬时精确值尤其在某个进程短时间内疯狂波动时它可能给你一个平均后的“假象”。所以看到某个进程50%左右飘忽不定别急着下结论多看几秒或者直接上Process Explorer看更精细的数据。另外“句柄数”和“线程数”也有参考价值。一个进程线程数莫名其妙涨到几千就算现在CPU不高大概率也快出事了——要么是线程泄漏要么是线程池没做回收这种进程迟早把CPU和内存打满。2.2 高频钉子户进程逐个击破dllhost、edge、idea这几个进程是我在Windows排查里遇到次数最多的各有各的坑挨个说。dllhost.exeCOM Surrogate飙高九成和缩略图、视频解码、Shell扩展有关。Windows资源管理器要用COM组件去解析视频文件、PDF、图片的缩略图这个解析工作就是dllhost干的。如果某个目录里全是损坏的视频或者超大图片dllhost会反复尝试解码CPU直接拉满。处理办法先在“文件夹选项”里关闭缩略图改成“始终显示图标”看CPU是否回落回落了就去清理缩略图缓存磁盘清理里勾选“缩略图”还没好就得排查第三方Shell扩展了用ShellExView禁用可疑扩展重启资源管理器。另外显卡驱动太老也容易让dllhost做软件解码顺手把显卡驱动更新一下。Edge浏览器占用CPU高的原因相对集中硬件加速、扩展、睡眠选项卡。遇到Edge飙高先在设置里把“使用硬件加速如果可用”关掉试一次有奇效。注意是“设置-系统”里那个开关不是每个网页里的视频加速。关掉后如果恢复那基本确认是显卡驱动和Edge的渲染管线不兼容。还有一招是启用Edge自带的“睡眠选项卡”功能让后台标签页自动休眠能省大量CPU和内存。IDEAJetBrains全家桶卡顿和高CPU是开发者的老朋友了。解决办法按优先级排先把内存给够idea64.exe.vmoptions里把-Xmx调到4G或更高机器够就8G项目索引很吃内存内存不足就会频繁GC导致CPU飙升再排除掉不需要索引的大目录右键标记为“排除”像target、node_modules、build这些目录千万别让IDEA扫描最后检查插件不是常用的插件能关就关。另外Gradle和Maven的守护进程也会占CPU特别是多项目同时编译的时候建议把Gradle的JVM参数也调一下不然构建时CPU直接爆炸。还有一个高频进程是wechatappex这是微信小程序的渲染进程CPU高通常和硬件加速设置有关在微信开发者工具设置里关掉“启用硬件加速”能缓解。这类国产套壳软件的渲染进程出问题根本原因往往是内置的Chromium版本过旧跟系统显卡驱动配合不好。2.3 任务管理器查不到时换Process Explorer任务管理器能看到进程级别但查不到线程级别。遇到一个进程特别能吃CPU、你怀疑是它内部某个模块在搞鬼的时候任务管理器就无能为力了。这时候上微软官方的Process ExplorerSysinternals套件里的绿色免安装。用Process Explorer双击占用率高的进程点开Threads页签就能看到这个进程里每个线程的CPU占用和入口地址。如果开了微软符号服务器还能看到线程的调用栈直接定位到是哪个dll里的哪个函数在烧CPU。我遇到过好几次某个服务进程整体占用30%看着不高但点进去发现里面一个线程占了100%单核。这种情况在任务管理器里根本看不出来因为30%是平均值掩盖了单线程热点。另一个好用的小技巧Process Explorer里可以查看进程加载的所有dll按公司名排序经常能在里面找到不明来源的第三方注入模块。Windows上有些软件会注入dll到别的进程里比如输入法、安全软件、广告组件一旦某个dll出bug它宿主进程的CPU就会莫名飙升从任务管理器看只能看到宿主进程的名字很容易误杀。2.4 命令行三板斧wmic、PowerShell和CPU真伪查询有些服务器环境没有图形界面或者你只想用命令快速看一圈那就要靠命令行。网上经常有人搜wmic cpu get processorid /value这条命令这里先纠正一下这条命令的作用是读取CPU的ProcessorId处理器标识用于辨别CPU真伪、核对CPU序列号之类的场景它本身并不能查看CPU占用率。想看占用率得用WMIC的性能类接口wmic path win32_perfformatteddata_perfproc_process get name,percentprocessortime这命令会列出每个进程的CPU占用百分比。注意它的第一行通常是Idle进程就是系统空闲时间那行值越高说明系统越闲。另外WMIC在Win11上已经被移除了要用的得去老系统上或者装兼容工具日常建议还是用PowerShell。PowerShell看CPU占用最方便Get-Process | Sort-Object CPU -Descending | Select-Object -First 15 Name,Id,CPU,WorkingSet64CPU列是进程累计消耗的CPU时间秒不是百分比。想看实时百分比有点麻烦可以直接看任务管理器或者用Get-CounterGet-Counter \Processor(_Total)\% Processor Time -SampleInterval 1 -MaxSamples 10想要在PowerShell里看CPU温度可以这样注意需要管理员权限且部分主板不支持Get-CimInstance -Namespace root/wmi -ClassName MSAcpi_ThermalZoneTemperature温度单位是K减掉273.15就是摄氏度。如果这条路走不通那就老老实实用CoreTemp或者HWiNFO。顺着这个说一句CPU真伪和型号识别的问题。很多人买CPU担心被坑尤其二手市场上工程样品ES/QS和正式版混卖的特别多。查证方法很简单CPU-Z里看Stepping和S-Spec编号和Intel/AMD官网对比就知道是不是正式版。命令行的话就是wmic cpu get processorid拿序列号再配合CPU-Z看基板编号。另外CPU-Z自带的Benchmark跑分也能辅助判断ES版往往频率、功耗表现都不正常。3. Linux下CPU飙高的定位方法3.1 第一现场top和htop怎么看Linux排查CPU问题top是绕不开的第一现场。启动top之后先按P按CPU使用率降序排列然后盯住前几行看top - 14:23:01 up 7 days, 3:21, 2 users, load average: 3.21, 2.89, 2.50 Tasks: 312 total, 1 running, 311 sleeping, 0 stopped, 0 zombie %Cpu(s): 85.6 us, 7.2 sy, 0.0 ni, 5.1 id, 1.9 wa, 0.0 hi, 0.2 si, 0.0 st MiB Mem : 32000.0 total, 2144.6 free, 18433.2 used, 11422.2 buff/cache那一行%Cpu(s)就是全系统汇总重点看us和sy的关系。us高到80%以上基本是用户态程序在忙碌如果sy占到20%以上就要警惕系统调用是不是过多了。wa超过10%说明IO有压力st在云服务器上超过10%说明被宿主机偷走了不少CPU。top还有一个细节每个进程的%CPU列可以超过100%那是因为多线程进程在多核上并行执行200%表示占满了两个CPU核心。看到800%也别慌说明这台机器至少有8个核心且在满负荷跑。htop是top的增强版支持鼠标操作、F6按任意列排序、F5树状视图。我最推荐树状视图因为很多应用会有父子进程关系比如Java服务可能fork出若干子进程Python的gunicorn也是树状视图一眼就能看清到底是哪个子进程在烧CPU不用一个个对PID。3.2 用vmstat、pidstat、mpstat区分用户态和内核态top看的是快照想观察趋势、判断是不是周期性波动就用vmstatvmstat 1 5procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 4 0 0 2144 1000 11200 0 0 0 10 5300 8900 70 20 10 0 0 5 0 0 2111 1000 11210 0 0 0 0 5500 9200 80 18 2 0 0第一列r是运行队列中的进程数持续大于CPU核心数就说明CPU不够用了。cs是上下文切换次数每秒几万次就要注意可能是线程过多或者锁竞争剧烈。sy高且cs高基本可以确认是内核在调度上花掉了太多时间。in是中断次数如果这个值异常高结合si软中断高大概率有网络或者磁盘中断风暴。pidstat是sysstat包里的工具能按进程输出CPU统计比top更适合写脚本收集。比如实时看每个进程的用户态和内核态CPU分开统计pidstat -u 1 5输出里usr和system两项分别对应用户态和内核态。如果你发现某个进程system占比常年超过10%就值得怀疑它是不是频繁在做系统调用——最常见的元凶是疯狂的日志写入和网络IO。想看多核负载是否均衡用mpstat -P ALL 1。如果所有核心都飙到100%那是整体负载高如果只有1个核心100%、其他核心空闲说明是单线程热点——程序没有充分利用多核或者某个循环没做多线程分解。这两种情况的解决方案天差地别一定要分清楚。3.3 线程级定位top -Hp、jstack、perf进程定位到了接下来要定位到线程。top -Hp PID可以显示这个进程内部的每个线程top -Hp 12345按P按CPU排序记下最上面那个线程的PID在top的线程视图里线程有自己的TID。然后把TID转成十六进制printf %x\n 12345如果这是Java程序用jstack直接打线程栈在输出里搜这个十六进制线程号jstack 12345 | grep -A 30 nid0x3039一般能看到这个线程正在执行的代码栈是不是死循环、是不是卡在锁等待、是不是在疯狂GC一目了然。C/C程序可以用pstack或者gdb attach看调用栈。如果觉得每次手动转十六进制太麻烦可以用jstack配合grep自动找jstack 12345 | grep -B 5 nid0x$(printf %x $(top -H -p 12345 -n1 | awk NR7 $9 ~ /^[0-9]$/ $980 {print $1}))这个命令稍微长了点实际就是取CPU占用最高的线程TID格式化后丢给jstack去匹配。多线程场景下线程名往往也带线索——Thread-xxx后面的数字对应线程池的编号如果是tomcat的http线程池还能对上请求ID。perf top是另一个利器能基于采样告诉你CPU时间到底花在了哪个函数上perf top -p 12345它不需要程序做任何改动每隔几毫秒采样一次CPU的调用栈只要热点函数占比够高就能在屏幕上看到。对原生程序或者Java配合perf-map-agent都能用。注意perf需要root权限而且容器内默认会拒绝要在宿主机上用nsenter切进容器的PID命名空间来跑。3.4 用stress造压力验证环境排查归排查有时候还得自己动手造点问题来验证环境。Ubuntu/Debian系装stress很方便apt install stress -y # CentOS/RHEL上用 yum install stress -y压测的经典用法是stress --cpu 4 --timeout 60 --verbose这会临时生成4个进程每个进程都跑无限循环把4个CPU核心打满60秒。压测时可以另开一个终端看top和vmstat观察CPU曲线是否平直、系统温度是否异常、有没有降频。我通常用stress干两件事一是验证新机器的散热和供电——压测10分钟如果温度超过95度还伴有降频说明散热器没装好或者硅脂涂太薄二是验证容器的CPU限额是否生效——在容器里压测如果使用率只能到0.5核说明docker run --cpus0.5之类的配额在起作用。还有个小坑如果给stress指定了8个进程但实际CPU使用率只有50%先看看是不是进程被绑核了。用taskset -c 0-3 stress --cpu 4可以限制到指定核上检查系统当前绑核情况用taskset -cp PID。云服务器上还得注意cgroup的cpu限制cat /sys/fs/cgroup/cpu.maxcgroup v2能看配额很多压测性能上不去的所谓“问题”其实都是配额卡死的。4. 从工具回到根因CPU飙高常见的几种病根4.1 死循环、空转和高复杂度算法最常见的原因没有之一。写代码的时候一个for循环里忘了break、一个while条件永远为真或者一个递归没有终止条件一旦走到这条路径CPU立刻就能飙起来。这种问题的特征很明显top里某个进程稳定占满一个或多个核心CPU时间几乎全部在us用户态Java程序jstack能看到同一个方法栈反复出现。还有一种变体是自旋锁。多线程编程里如果锁竞争太激烈且实现用了CAS自旋线程会不停地在循环里尝试获取锁CPU被白白烧掉。这种情况的典型现象是sy不高但us极高线程栈上能看到大量的AtomicLong.compareAndSet或者Thread.yield。解决办法不是改锁代码而是先检查临界区是否太小尝试降低锁粒度或者改用无锁数据结构。另一个隐蔽的元凶是日志系统。生产环境开了debug级别的日志或者日志框架本身有同步IO的坑导致每个请求都要做大量字符串拼接和文件写入CPU和IO一起飙升。定位方法很直接jstack里搜logback或log4j的调用栈如果能搜到一大片就把日志级别调回info问题立刻缓解。4.2 GC、内存回收和JVM问题Java和Kotlin服务的一个噩梦是Full GC。GC本身是CPU密集型操作尤其是老年代的Full GC轻则几百毫秒重则几秒期间CPU全部被GC线程占满。更麻烦的是GC之后往往伴随内存碎片和频繁分配又引发下一轮GC形成一个恶性循环CPU曲线直接拉成一条直线。先用jstat -gcutil PID 1000看GC情况重点关注Full GC的次数和耗时jstat -gcutil 12345 1000 10如果FGC一列在持续增长每隔几百毫秒涨一次那基本实锤了。GC频繁的根源要么是堆太小、要么是对象分配过于集中。临时解决办法是-Xmx调大给堆更多空间根本解决得抓对象分配用jmap -histo:live看老年代里堆了哪些大对象很多情况就是某个缓存把数据全怼进内存没做淘汰或者循环里创建了大量临时对象。.NET服务同理看GC计数器原理一样。别一听GC就只会加内存要搞清楚是谁在产生这些垃圾。4.3 系统服务和第三方软件的锅有些CPU飙高根本不是你自己的程序有问题是系统里的杂音。Windows上比较常见的是Windows Search索引服务、Windows Defender实时扫描、Windows Update在后台下载和安装补丁。这些服务一旦忙起来CPU直接被人为拉高。处理思路不是禁用它们——那会引入安全风险——而是错峰和排除。比如Defender的排除列表里加上项目的build目录Windows Search的索引范围去掉大目录Windows Update的活跃时间改到业务低峰期。Linux上也有一堆“隐秘的系统服务”最常见的包括systemd-journald在写大量日志、logrotate在切割轮转日志、updatedb在更新文件索引数据库、clamav在扫描病毒。这些操作通常是周期性的所以CPU曲线会呈现规则的脉冲形状。对策是调整它们的执行时间避开业务高峰。比如logrotate的cron从每小时改成每天凌晨3点updatedb的/etc/cron.daily/mlocate改成weekly。这里插一个工控行业的冷门案例有人用西门子博图TIA PortalV17组态时选择CPU时报“找不到许可证STEP 7 Professional”实际上和CPU飙高没有直接关系但很多人在排查时会把它们混为一谈。博图这个报错的根源是授权软件Automation License Manager没激活或者许可证被其他版本占用解决办法是重装/激活许可证或者检查系统时间是否正确——授权校验失败时部分软件的CPU占用反而会异常升高。排查顺序报错信息里写的是License就别去查PLC的CPU先查软件授权方向别搞错。4.4 虚拟化环境中的CPU坑虚拟化环境里的CPU问题比物理机多了一层“中间商赚差价”的烦恼。很多人装虚拟机的时候会遇到“客户机操作系统已禁用CPU。请关闭或重置虚拟机”的报错同时宿主机的CPU占用还不低这是因为宿主机的硬件虚拟化开关VT-x/AMD-V没有开启虚拟机没法用硬件加速只能走软件模拟。软件模拟的CPU指令解析非常消耗资源CPU占用自然飙升。解决方法是进入BIOS开启Intel Virtualization Technology或者SVM Mode。还有一个零配置的办法在VMware的虚拟机设置里把“虚拟化引擎”的“虚拟化Intel VT-x/AMD-V”选项勾上这个选项开启后即使BIOS没开也能在部分场景下缓解。VirtualBox的话是“系统-处理器-启用嵌套VT-x/AMD-V”。装了安全软件或者某些老笔记本对虚拟化支持不好也会触发类似问题。云服务器上需要关注的是ststeal time指标。st表示你的虚拟CPU被宿主机“偷走”的时间占比。如果st长期超过10%说明母鸡上其他虚拟机在抢CPU你这台机器的性能就是不稳定怎么优化都没用。处理办法只有一个换实例类型或者等高峰期过去再观察。容器化的CPU坑也不少。Docker里docker run --cpus4限制的是容器最多用4个核但要留意--cpu-shares和--cpuset-cpus这些参数的组合效果。经常有人部署Milvus这类向量数据库时用CPU镜像发现CPU占用异常高排查半天发现是docker-compose里没设置CPU限额容器和宿主机上其他服务抢到了一个物理核上。正确的做法是先给容器设置明确的CPU限制再谈性能调优。4.5 老游戏、老软件的多核优化问题最后一个偏冷门但真实存在的场景老软件在现在的多核CPU上跑CPU占用就是上不去或者个别核爆满。典型就是魔兽争霸3这种上古游戏设计的时候最多支持单核放现在的机器上只能吃一个核另外七个核在旁边看戏。想验证是不是这类问题先开任务管理器切到“性能-CPU”看有没有一个核是100%、其他核基本空闲。如果是软件的代码层面已经不适合现代CPU了绕过去的办法是给进程设置CPU亲和性让系统把它固定到性能最好的P核上或者用第三方工具做多核负载均衡。war3的具体操作是开游戏后打开任务管理器找到war3.exe右键设置相关性把CPU亲和性选上几个核心。有些人会用注册表或者启动项加-opengl参数也有一定效果。把这几种情况分开看就会发现CPU飙高从来不是一个单独的技术动作能解决的它背后既有应用层的问题也有系统层的问题还有硬件和虚拟化的因素。先定位到具体的类别才能对症下药。5. 常用工具速查与日常预防5.1 工具箱速查表把常用的工具整理成表排查的时候对着看就行平台工具用途Windows任务管理器进程级CPU/内存概览WindowsProcess Explorer线程级定位、句柄、dll清单WindowsResource Monitor实时观察CPU/磁盘/网络WindowsPowerShell Get-Counter命令行采集CPU指标WindowsCoreTemp / HWiNFOCPU温度、功耗、频率Linuxtop / htop第一现场概览Linuxvmstat系统CPU/IO/中断趋势Linuxpidstat / mpstat进程级/核心级CPU统计Linuxperf top函数级热点采样Linuxstress / taskset压测和CPU绑定跨平台CPU-ZCPU型号、步进、真假识别跨平台AIDA64 / Prime95稳定性压力测试5.2 压力测试怎么开、负载多少才算正常很多人第一次接触压力测试以为打开CPU-Z跑一下自带的Benchmark就算压测了。这里说清楚CPU-Z的Benchmark是短时性能测试负载通常不到70%根本压不出散热问题。真正要压测得上AIDA64的系统稳定性测试Tools-System Stability Test勾选Stress CPU和Stress FPU或者用Prime95的Torture Test。Prime95默认模式会跑大约30分钟如果期间CPU温度稳定在85度以下、没有触发降频散热基本合格。注意跑Prime95之前先把BIOS里的AVX指令集选项确认好否则有些主板默认降频幅度过大测出来的已经不是CPU真实性能了。关于“CPU-Z稳定测试负载70%正常吗”这个问题CPU-Z自带的Benchmark跑分能到70%基本属于偏高说明后台有任务在占资源或者你用的是高负载的基准测试模式正常应该在30%-60%之间。这时候先关掉后台软件重测再看分数是否正常。压测完发现CPU温度直接过百并降频大概率是散热器安装问题——有些塔式散热器的风扇方向装反了或者水冷的水泵没有插对CPU_FAN接口导致水泵转速拉不上去。这属于硬件层面的坑排查的时候记得看一眼BIOS里的风扇转速如果水泵转速是0就要找机箱接线了。5.3 建立监控、留好现场再处置排查CPU问题最怕的就是“现场被破坏”。很多人在观察到CPU高的一瞬间就急着重启服务等到事后分析时现场没了进程没了日志也没留只能靠猜。正确的处置顺序是先通过监控平台截取进程列表和top快照再用jstack或pstack抓一份线程栈最后才考虑重启或者kill。抓线程栈这一步很多人觉得麻烦实际上一条命令而已for pid in $(pgrep -f appname); do jstack $pid /tmp/jstack_$pid_$(date %s).txt; done另外建议日常就建设好监控体系。Windows上性能监视器可以加Processor % Processor Time和Processor Queue Length两个计数器配置成每1分钟采集一次Linux上用node_exporter Prometheus是标配。告警阈值别设得太敏感我一般用“CPU持续5分钟超过85%”才触发告警这样能过滤掉很多瞬时抖动。5.4 快速排查checklist最后给一个我平时打印出来贴工位上的排查清单照着走基本不会漏看top/任务管理器汇总行us高还是sy高wa高还是st高先定性。按CPU排序找到消耗最高的进程记录PID。如果是Java进程抓一份jstack找线程热点。如果是原生进程用perf top看热点函数。查系统日志Windows事件查看器、Linux的dmesg/var/log/syslog看有没有报错。观察CPU曲线是持续陡峭还是周期性脉冲判断偶发还是持续。如果是偶发记录时间点去日志里找同时间的业务事件。确认根因后再处置改代码、调配置、换硬件、重启服务。处置后持续观察15分钟确认CPU回落到正常区间。这套流程我自己用了好几年基本没失手。最后分享一个小习惯遇到CPU飙高第一件事不是去kill进程而是先把现场数据保存下来——记下PID、线程号、top快照、当时的日志再动手处置。因为问题修完可能就不会再复现了没留证据等于白查。这个习惯帮我少踩了很多坑希望对你也有参考价值。
返回列表