在日常开发与运维中,Shell 脚本仍然是我们处理文本、调度任务和管理系统的重要工具。但如何写出健壮、高效、可维护的脚本?本文分享我如何借助 DeepSeek 这类 AI 辅助工具优化 Shell 脚本的真实实践。
我负责维护一个基于 Shell 的数据预处理流水线,其中一个关键环节是解析 Nginx 日志,提取特定错误并统计频率。原始脚本由多位同事迭代开发,存在以下问题:
cat access.log | grep "ERROR" | awk '{print $6}' | sort | uniq -c | sort -nr
我向 DeepSeek 输入了原始脚本并询问优化建议。它快速指出了几个关键问题:
cat
:可直接用 grep
读取文件awk
操作减少进程创建#!/bin/bash
set -eo pipefail
LOG_FILE="${1:-access.log}"
TEMP_FILE="$(mktemp)"
# 使用单个 awk 调用完成提取和统计
awk '/ERROR/ {print $6}' "$LOG_FILE" \
| sort \
| uniq -c \
| sort -nr > "$TEMP_FILE"
# 检查是否成功生成数据
if [[ ! -s "$TEMP_FILE" ]]; then
echo "No ERROR messages found" >&2
exit 1
fi
# 输出结果
cat "$TEMP_FILE"
# 清理临时文件
trap 'rm -f "$TEMP_FILE"' EXIT
关键改进:
cat
和 grep
调用set -eo pipefail
确保错误传播mktemp
创建安全临时文件对于超大型日志文件(GB 级别),即使是优化后的单线程处理仍然较慢。我进一步向 DeepSeek 咨询并行处理方案。
#!/bin/bash
set -eo pipefail
LOG_FILE="${1:-access.log}"
NUM_CORES=$(nproc)
TEMP_DIR="$(mktemp -d)"
# 分割大文件
split -n "l/$NUM_CORES" "$LOG_FILE" "${TEMP_DIR}/log_part."
# 并行处理每个分片
process_part() {
local part_file="$1"
awk '/ERROR/ {print $6}' "$part_file" \
| sort \
| uniq -c
}
export -f process_part
find "$TEMP_DIR" -name "log_part.*" \
| parallel -j "$NUM_CORES" process_part \
| awk '{count[$2] += $1} END {for (key in count) print count[key], key}' \
| sort -nr
# 清理
trap 'rm -rf "$TEMP_DIR"' EXIT
性能提升:
parallel
工具实现多核并行split
分割输入文件长期维护的脚本需要良好的结构。我基于 DeepSeek 的建议建立了脚本框架:
scripts/
├── lib/
│ ├── logging.sh # 日志功能
│ └── validation.sh # 参数验证
├── config.sh # 配置文件
└── main.sh # 主入口
#!/bin/bash
# lib/logging.sh
set -euo pipefail
LOG_LEVEL="${LOG_LEVEL:-INFO}"
log() {
local level="$1"
shift
local message="$*"
local timestamp=$(date +"%Y-%m-%d %H:%M:%S")
# 级别过滤
case "$LOG_LEVEL" in
DEBUG) ;;
INFO) [[ "$level" == "DEBUG" ]] && return ;;
WARN) [[ "$level" == "DEBUG" || "$level" == "INFO" ]] && return ;;
ERROR) [[ "$level" != "ERROR" ]] && return ;;
esac
echo "[${timestamp}] [${level}] ${message}" >&2
}
# 示例用法
# source lib/logging.sh
# log "INFO" "Processing started"
通过这次优化实践,我总结了几点重要经验:
time
命令比较不同方案的实际性能最有价值的 DeepSeek 提示:
"考虑使用 awk 的关联数组直接计数,避免多次排序操作"
这引导我最终采用了更高效的实现:
awk '/ERROR/ {count[$6]++} END {for (key in count) print count[key], key}' | sort -nr
Shell 脚本优化是一个平衡艺术:在性能、可读性和健壮性之间找到最佳平衡点。借助 DeepSeek 这样的 AI 辅助工具,我们能够快速获得专业建议,但最终决策仍需基于实际场景和深入理解。
优化前后的性能对比(百万行日志):
最重要的是,现在的脚本不仅运行更快,也更易于维护和扩展。这正是技术优化的真正价值所在。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。