You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解决Shell脚本while read读取jq输出字符串拆分致证书校验异常问题

Shell脚本解析带空格证书字段实现过期校验

问题说明

现有存储PKCS12证书配置的test.json文件,需提取每条证书记录的id、name、not_after字段,校验证书not_after过期时间是否距当前时间不足60天,不足则输出告警信息。
原有实现通过jq提取.name、.entry[].not_after字段后管道传入while read循环逐行处理,但带空格的name字段值(如Test Client Name)会被按空白字符拆分为多个片段,导致循环内name、expirydate变量赋值错位、date命令日期解析失败、整数比较逻辑报错,无法输出预期告警。

故障原因

默认jq输出为无明确分隔标识的纯文本,read命令默认以任意空白字符作为字段分隔符,包含空格的name字段会被识别为多个独立字段,后续变量赋值顺序完全错乱。

修复实现

核心思路

使用不会出现在常规字段值中的制表符作为输出分隔符,强制jq输出结构化的分隔内容,同时指定read命令仅按制表符切分字段,保证带空格的名称字段被完整读取。

修复后完整脚本

#!/bin/bash
# 定义告警阈值:60天对应秒数
ALERT_THRESHOLD=$((60 * 24 * 3600))
NOW_TIMESTAMP=$(date +%s)

# jq通过@tsv输出制表符分隔的三列:证书ID、证书名称、过期时间
jq -r '.[] | [.id, .name, .entry[].not_after] | @tsv' test.json | while IFS=$'\t' read -r cert_id cert_name not_after
do
    # 解析过期时间为时间戳,增加错误容错
    expiry_ts=$(date -d "$not_after" +%s 2>/dev/null)
    if [ $? -ne 0 ]; then
        echo "[错误] 证书ID:$cert_id 名称:$cert_name 过期时间格式非法,原始值:$not_after"
        continue
    fi

    remaining_sec=$((expiry_ts - NOW_TIMESTAMP))
    # 小于阈值则触发告警
    if [ $remaining_sec -lt $ALERT_THRESHOLD ]; then
        if [ $remaining_sec -lt 0 ]; then
            echo "[严重告警] 证书已过期 | ID:$cert_id | 名称:$cert_name | 过期时间:$not_after"
        else
            remain_days=$((remaining_sec / 86400))
            echo "[告警] 证书有效期不足60天 | ID:$cert_id | 名称:$cert_name | 剩余天数:$remain_days | 过期时间:$not_after"
        fi
    fi
done

关键配置说明

  • jq端使用@tsv格式化输出,三个字段间自动插入制表符,不受字段内部空格影响
  • read命令前指定IFS=$'\t',将字段分隔符设置为仅制表符,保证带空格的证书名称被完整赋值给cert_name变量,不会出现错位
  • 增加日期解析失败的分支判断,避免非法格式导致脚本整体中断
  • 所有时间统一转换为Unix时间戳做数值比较,规避不同日期字符串格式直接比对的逻辑错误

内容的提问来源于stack exchange,提问作者Karthick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 03:12:19