Linux shell 脚本性能优化方法

1次阅读

应避免循环中调用外部命令如date、hostname,改用变量缓存或$epochrealtime;优先用[[ ]]替代[ ]提升性能;文本处理禁用for line in $(cat file),改用while read流式读取。

Linux shell 脚本性能优化方法

避免在循环里反复调用 datehostname 这类外部命令

每次执行 datehostname 都要 fork 一个新进程,开销远高于变量赋值。脚本里如果在千次级循环中调用,可能拖慢几十倍。

  • 把结果提前存进变量:now=$(date +%s),后面直接用 $now
  • 特别注意日志时间戳场景:别写成 echo "$(date): doing X" 放在循环里
  • 如果必须动态时间(比如每轮记录毫秒级时间),改用 $EPOCHREALTIMEbash 5.0+)或 printf '%(%s.%N)T'(更轻量)

[[ ]] 替代 [ ] 做条件判断

[ ] 是 POSIX 兼容的外部命令(通常是 /usr/bin/[),而 [[ ]] 是 bash/zsh 内置关键字,无 fork 开销,且支持正则、模式匹配和更安全的字符串比较。

  • 错误写法:if [ "$var" = "abc" ]; then —— 引号漏掉或含空格时易出错,且启动子进程
  • 正确写法:if [[ $var == abc ]]; then —— 不强制引号(但建议仍加),不 fork,支持 ===~
  • 注意兼容性:如果脚本需在 dash/sh 下运行,不能用 [[ ]];否则优先用它

批量处理文本别用 for line in $(cat file)

这种写法会先展开整个文件内容为单词列表,遇到空格、制表符、换行符都会被 word-splitting 破坏原始结构,还吃内存。实际性能差,语义也错。

  • 正确方式是用 while read 流式读取:while IFS= read -r line; do ...; done
  • 如果后续要用数组,先用 mapfile -t lines (bash),比 <code>arr=($(cat file)) 安全得多
  • 涉及过滤/转换,优先交给 awksed —— 它们单次遍历、C 实现、不加载全文到 shell 变量中

函数内少用 export全局变量慎用 declare -g

每次 export 都要更新环境块,频繁调用会触发系统调用;declare -g 在函数里修改全局变量看似方便,但会让变量生命周期和依赖关系变得隐晦,调试时难定位修改点。

  • 只对真正需要传给子进程的变量 export(比如 PATH、自定义回调钩子)
  • 函数尽量通过 echo 返回值,或用 local + 参数传引用(如 myfunc result_var,函数内用 printf -v "$1" "%s" "$value"
  • 避免在循环中反复 export VAR=value —— 提前设好,或用子 shell 隔离:(export VAR=newval; cmd)

最常被忽略的是 I/O 和 fork 的叠加效应:一行看着简单的命令,背后可能是五次 exec、三次内存拷贝、两次缓冲区 flush。优化得从“这行会不会 spawn?”“这个变量是不是真要 global?”开始问。

text=ZqhQzanResources