Shell脚本执行慢需先定位瓶颈:用time区分real/user/sys判断是否等待为主;strace -c统计read/write/openat等系统调用耗时与频次;perf record采样分析外部命令(如grep、awk)CPU占用;避免循环调用$(ls)、重复执行命令等低效写法。

Shell 脚本执行慢,问题往往不在语法本身,而藏在外部调用、低效逻辑或系统等待上。直接改脚本不如先找准瓶颈——perf、time、strace 这些 Linux 自带工具就能快速定位“卡在哪”。
看整体耗时分布:用 time 区分 real/user/sys
在脚本前加 time,运行一次就能看出时间花在哪:
- real:总耗时(墙钟时间),如果它远大于 user+sys,说明大量时间花在等待(比如 I/O、网络、子进程挂起)
- user:脚本自身在用户态消耗的 CPU 时间
- sys:内核为该脚本执行系统调用所花的时间(如 open、stat、fork)
例如:time ./myscript.sh 输出 real 12.4s user 0.2s sys 0.1s,说明 98% 的时间都在等外部动作,不是脚本逻辑慢,而是它频繁调用命令或读写文件。
Linux 性能分析与调优专家,覆盖 CPU、内存、磁盘 I/O、网络、内核参数、编译优化、容器/K8s。适用场景:系统卡顿/高负载、内存不足/OOM/Swap 高、CPU 异常/iowait 高。
查系统调用热点:用 strace -c 统计阻塞点
strace -c 不显示详细过程,但能告诉你哪些系统调用最耗时、最频繁:
- 重点关注 read、write、openat、stat、wait4(子进程等待)、clone(fork 开销)
- 如果 clone 调用次数高达上万次,基本可断定是循环里写了 for f in $(ls) 或反复调用 date/grep 导致的
- 若 read 耗时占比高,检查是否在循环中反复读大文件,或用了未加引号的变量导致路径解析失败重试
盯住高频外部命令:用 perf record 抓进程级采样
当怀疑某个外部命令(如 awk、jq、find)拖慢整体节奏,可用 perf 对它采样:
- 先用 ps aux | grep "myscript.sh" 找到主 shell 进程 PID
- 再运行:sudo perf record -F 99 -e cpu-clock -p $PID -g -- sleep 10
- 然后 sudo perf report -g,看调用栈里哪条命令/哪类操作占 CPU 最多
- 若看到大量 /bin/bash → execve → /usr/bin/grep,就说明 grep 是瓶颈;换成 awk '/pattern/{print}' 可省掉 fork 开销
避免常见低效模式:从脚本写法入手
很多慢不是因为“功能复杂”,而是重复做了无谓的事:
- 别在循环里反复执行 $(date +%s)、$(hostname),提前赋值给变量
- 用 for file in * 替代 for file in $(ls)(后者会触发 word splitting 和子 shell)
- 合并多次 grep:grep -E 'a|b|c' 比三次单独 grep 快得多
- 统计行数优先用 wc -l,而不是 cat file | grep xxx | wc -l(少一次管道和进程)
- 复杂文本处理超过几十行,果断换 awk 或 jq,别硬撑用 Shell


















