Shell脚本如何配置容器日志采集:从基础到实战的完整指南
目录导读
容器日志采集的核心挑战
在容器化环境中,Docker或Kubernetes默认的日志驱动(如json-file)会将所有输出写入宿主机特定目录,当容器数量激增时,手动管理日志变得困难,常见痛点包括:

- 日志文件无限增长:默认无轮转策略,磁盘容易爆满。
- 格式混乱:不同容器输出的json、text、syslog格式需要统一解析。
- 权限问题:采集脚本可能无法访问特定容器的日志路径。
Shell脚本的优势在于轻量、无需额外守护进程,且能直接调用Docker API或docker logs命令实现灵活采集。
Shell脚本在日志采集中的角色
Shell脚本适合作为“胶水层”,连接容器运行时与日志后端(如Elasticsearch、Splunk或本地文件),典型工作流:
容器日志 → Shell脚本采集 → 格式化 → 写入文件或发送到远程服务器
适用场景:
- 小型开发环境或边缘节点无需复杂日志平台。
- 作为监控系统启动前的临时采集方案。
- 对日志格式有特殊转换需求(如JSON转CSV)。
环境准备与依赖安装
在编写脚本前,确保宿主机具备以下条件:
# 检查Docker是否运行
docker ps &>/dev/null || { echo "Docker未运行"; exit 1; }
# 安装必要的工具(以Ubuntu为例)
sudo apt-get install -y jq curl # jq用于解析JSON,curl用于发送HTTP请求
关键点:
docker logs命令默认只显示最近日志,需添加--since或--follow实现持续采集。- 使用
docker inspect获取容器日志路径(默认位于/var/lib/docker/containers/<container_id>/<container_id>-json.log)。
基础日志采集脚本编写
以下脚本演示如何定期采集所有运行中容器的日志,并按容器名保存为独立文件:
#!/bin/bash
# 采集所有容器日志到 /var/log/container_logs/
OUTPUT_DIR="/var/log/container_logs"
mkdir -p "$OUTPUT_DIR"
# 获取所有容器ID(忽略退出状态)
docker ps -q | while read -r CID; do
CONTAINER_NAME=$(docker inspect --format '{{.Name}}' "$CID" | sed 's/\///')
# 使用jq提取日志内容(去除时间戳前缀,保持原始输出)
docker logs "$CID" 2>/dev/null | jq -R '{"ts": now, "msg": .}' > "$OUTPUT_DIR/${CONTAINER_NAME}.json"
# 每30秒轮询一次
sleep 30 &
done
# 等待所有后台进程
wait
说明:
- 脚本通过
docker logs抓取标准输出和错误(2>/dev/null隐藏Docker元数据)。 - 使用
jq将每行日志转换为JSON格式,并添加时间戳(now是jq内置函数)。 - 每个容器独立文件,避免混写。
高级配置:动态采集与过滤器
实际生产环境中,往往需要按需采集特定容器或过滤敏感信息,以下脚本实现:
- 基于标签(
log_collect=true)筛选容器。 - 过滤掉包含“DEBUG”且长度小于10的日志条目(节省空间)。
#!/bin/bash
# 高级日志采集:支持标签过滤与内容过滤
FILTER_LABEL="log_collect=true"
OUTPUT_DIR="/var/log/container_logs/filtered"
REGEX_IGNORE='^(DEBUG|TRACE).{0,10}$' # 忽略以DEBUG/TRACE开头且短的日志
docker ps --filter "label=$FILTER_LABEL" -q | while read -r CID; do
docker logs --follow "$CID" 2>/dev/null | while read -r line; do
# 过滤条件
if [[ "$line" =~ $REGEX_IGNORE ]]; then
continue
fi
# 添加元数据
echo "{\"container\": \"$(docker inspect --format '{{.Name}}' "$CID" | sed 's/\///')\", \"log\": $(jq -Rsa . <<<"$line")}" >> "$OUTPUT_DIR/merged.log"
done
done
重点:
--follow实现实时流式采集,适合监控场景。- 使用
jq -Rsa .对特殊字符(如引号、换行)进行转义,防止JSON破坏。
日志轮转与存储优化
容器日志可能单日产生数GB,轮转策略必不可少,Shell脚本可实现logrotate风格的简单轮转:
#!/bin/bash
# 日志轮转:按文件大小分割(每100MB创建新文件)
MAX_SIZE=104857600 # 100MB
LOG_DIR="/var/log/container_logs"
rotate_file() {
local base="$1"
local count=${2:-1}
if [ -f "${base}.${count}" ]; then
rotate_file "$base" $((count+1))
fi
mv "${base}.json" "${base}.${count}.json" 2>/dev/null
}
cd "$LOG_DIR" || exit 1
for f in *.json; do
if [ $(stat -c%s "$f") -gt $MAX_SIZE ]; then
rotate_file "$(basename "$f" .json)"
fi
done
优化建议:
- 结合
cron每天凌晨执行轮转脚本。 - 压缩旧日志:
gzip -9 *.1.json。 - 设置保留天数:
find . -name '*.json.gz' -mtime +30 -delete。
常见问题与问答
Q1:Shell脚本采集日志与Filebeat/Logstash有什么区别?
- 优势:Shell无需额外内存,适合资源受限的边缘设备;可快速定制,无需学习新工具。
- 劣势:缺乏弹性、重试机制,大规模集群不稳定,生产环境建议使用Filebeat或Fluentd。
Q2:采集的日志中出现了乱码或特殊字符,如何解决?
- 确保使用
jq -Rsa .对输入进行JSON序列化。 - 检查容器内应用编码:
docker exec <container> locale,若为POSIX需设置export LC_ALL=C.UTF-8。
Q3:脚本采集时磁盘I/O过高,如何限制?
- 增加
read -t 1等待时间,降低轮询频率。 - 使用
ionice -c 3降低脚本进程的I/O优先级。
Q4:如何将日志发送到远程服务器(如Elasticsearch)?
- 在脚本中集成
curl:curl -X POST "http://your-es-host:9200/logs/_doc" -H "Content-Type: application/json" -d "$(tail -1 output.log)"。 - 注意批量提交减少请求次数,可使用
数组+curl --data-binary。
Q5:Kubernetes环境下如何采集Pod日志?
- Kubernetes默认使用journald,Shell脚本可通过
kubectl logs代替docker logs。 - 或者直接读取Pod挂载的日志文件(如
/var/log/pods/),需注意权限。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播