解决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
相关产品推荐
相关产品推荐

