利用shell脚本结合jenkins定期发送值周通知到企业微信
最近项目有个需求是要每天把值周名单发到企业微信机器人上
主要实现步骤大概是
- 利用jenkins定时触发任务,远程执行服务器的shell脚本
- shell脚本实现发送消息到企业微信
- shell脚本实现判断当前是否周一,周一实现值周人员轮换
大概的逻辑图如下:

下面就是shell脚本的实现逻辑,可以先直接执行脚本,查看企业微信机器人收到的消息,代码是每周一进行轮换,可以自定义
1 #!/bin/bash 2 # 值周轮换通知脚本(工作日每日触发,周二轮换) 3 # 存储路径: /shier/duty_notifier/duty_notifier.sh 4 5 # 配置区域 ======================= 6 # 企业微信机器人Webhook URL 7 WEBHOOK_URL="https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxx你的企业微信机器人" 8 9 # 日志文件位置 10 LOG_FILE="/shier/duty_notifier/duty-notifier.log" 11 12 # 人员名单直接内嵌在脚本中 13 declare -A ROSTER=( 14 ["策划"]="designer1,designer2,designer3,designer4,designer5," 15 ["服务器"]="server1,server2,server3,server4" 16 ["客户端"]="client1,client2,client3,client4,client5" 17 ["QA"]="qa1,qa2,qa3" 18 ) 19 20 # 轮换索引文件(单个文件存储所有状态) 21 INDEX_FILE="/shier/duty_notifier/duty_index" 22 # ================================ 23 24 # 全局关联数组 25 declare -gA current_index 26 27 # 日志函数 28 log() { 29 echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE" 30 } 31 32 # 获取当前星期几 (1-7, 1=周一) 33 get_weekday() { 34 date +%u 35 } 36 37 # 确保目录和文件存在 38 ensure_directory() { 39 # 创建目录(如果不存在) 40 mkdir -p "/shier/duty_notifier" 41 42 # 创建日志文件(如果不存在) 43 if [ ! -f "$LOG_FILE" ]; then 44 touch "$LOG_FILE" 45 chmod 644 "$LOG_FILE" 46 log "创建日志文件: $LOG_FILE" 47 fi 48 49 # 创建索引文件(如果不存在) 50 if [ ! -f "$INDEX_FILE" ]; then 51 touch "$INDEX_FILE" 52 chmod 600 "$INDEX_FILE" 53 log "创建初始索引文件: $INDEX_FILE" 54 fi 55 } 56 57 # 加载当前索引 58 load_index() { 59 # 确保目录和文件存在 60 ensure_directory 61 62 # 清空当前索引 63 current_index=() 64 65 # 如果索引文件存在且非空,加载内容 66 if [ -s "$INDEX_FILE" ]; then 67 log "加载索引文件: $INDEX_FILE" 68 while IFS='=' read -r key value; do 69 # 跳过空行和无效行 70 [[ -z "$key" ]] && continue 71 [[ -z "$value" ]] && continue 72 73 # 将值转换为整数 74 current_index["$key"]=$((value)) 75 log "加载索引: $key = $value" 76 done < "$INDEX_FILE" 77 else 78 log "索引文件为空,创建默认索引" 79 fi 80 81 # 确保所有职能都有索引值 82 for department in "${!ROSTER[@]}"; do 83 if [ -z "${current_index[$department]+x}" ]; then 84 current_index["$department"]=0 85 log "初始化部门索引: $department=0" 86 fi 87 done 88 } 89 90 # 更新索引文件 91 save_index() { 92 # 确保目录和文件存在 93 ensure_directory 94 95 log "保存索引到文件: $INDEX_FILE" 96 97 # 创建临时文件 98 temp_file="$(mktemp)" 99 100 # 写入所有索引状态 101 for department in "${!ROSTER[@]}"; do 102 echo "$department=${current_index[$department]}" >> "$temp_file" 103 log "保存索引: $department=${current_index[$department]}" 104 done 105 106 # 替换原文件 107 mv -f "$temp_file" "$INDEX_FILE" 108 log "索引文件已更新" 109 110 # 验证保存结果 111 if [ -f "$INDEX_FILE" ]; then 112 log "索引文件内容:" 113 cat "$INDEX_FILE" | tee -a "$LOG_FILE" 114 else 115 log "错误: 索引文件保存失败" 116 fi 117 } 118 119 # 发送企业微信通知 120 send_notification() { 121 local message=$1 122 123 # 替换换行符为企业微信兼容格式 124 local wechat_msg 125 wechat_msg="$(echo -e "$message" | sed 's/$/\\n/' | tr -d '\n' | sed 's/\\n$//')" 126 127 # 构造JSON请求体 128 local json_data=$(cat <<EOF 129 { 130 "msgtype": "text", 131 "text": { 132 "content": "$wechat_msg", 133 "mentioned_list": ["@all"] 134 } 135 } 136 EOF 137 ) 138 139 # 发送请求 140 log "发送通知到企业微信" 141 local response=$(curl -s -H "Content-Type: application/json" -d "$json_data" "$WEBHOOK_URL") 142 143 # 检查响应 144 if echo "$response" | grep -q '"errcode":0'; then 145 log "通知发送成功" 146 return 0 147 else 148 log "通知发送失败: $response" 149 return 1 150 fi 151 } 152 153 # 获取当前值周人员(无日志版本) 154 get_current_duty() { 155 declare -A duty_people=() 156 157 for department in "${!ROSTER[@]}"; do 158 # 解析人员数组 159 IFS=',' read -ra people <<< "${ROSTER[$department]}" 160 161 # 获取当前索引(确保数值类型) 162 local idx=${current_index[$department]} 163 idx=$((idx)) 164 165 # 检查索引有效性 166 local count=${#people[@]} 167 if [ $idx -ge $count ]; then 168 idx=0 169 current_index[$department]=0 170 fi 171 172 # 获取当前值班人员 173 duty_people["$department"]=${people[$idx]} 174 done 175 176 # 返回结果数组 177 for key in "${!duty_people[@]}"; do 178 echo "$key:${duty_people[$key]}" 179 done 180 } 181 182 # 构建通知消息(纯净版) 183 build_message() { 184 local weekday=$(get_weekday) 185 local day_name="" 186 187 case $weekday in 188 1) day_name="星期一" ;; 189 2) day_name="星期二" ;; 190 3) day_name="星期三" ;; 191 4) day_name="星期四" ;; 192 5) day_name="星期五" ;; 193 *) day_name="工作日" ;; 194 esac 195 196 local message="📢 ${day_name} 值周提醒\n" 197 message+="=================\n" 198 message+="⭐️ 本周值周安排 ⭐️\n\n" 199 200 # 获取值周人员 201 local duty_info=$(get_current_duty) 202 203 # 添加各职能的值周人员 204 while IFS=':' read -r department person; do 205 message+="${department}:${person}\n" 206 done <<< "$duty_info" 207 208 # 添加值周周期说明 209 message+="=================\n" 210 echo -e "$message" 211 } 212 213 # 主逻辑 214 main() { 215 local weekday=$(get_weekday) 216 217 # 周末不执行 218 if [ $weekday -eq 6 ] || [ $weekday -eq 7 ]; then 219 log "今天是周末($weekday),跳过执行" 220 exit 0 221 fi 222 223 log "====== 开始执行值周通知 ($(date +%F)) ======" 224 log "今天是周$weekday" 225 226 # 加载索引 227 load_index 228 229 # 打印当前索引状态 230 log "当前索引状态:" 231 for dept in "${!current_index[@]}"; do 232 log " $dept: ${current_index[$dept]}" 233 done 234 235 # 周二进行轮换 236 if [ $weekday -eq 1 ]; then 237 log "今天是周一,进行值周轮换" 238 239 # 记录轮换前的人员 240 declare -A before_rotation=() 241 for department in "${!ROSTER[@]}"; do 242 IFS=',' read -ra people <<< "${ROSTER[$department]}" 243 # 获取索引值并转换为整数 244 local idx=${current_index[$department]} 245 idx=$((idx)) 246 before_rotation["$department"]="${people[$idx]}" 247 log "轮换前: ${department} = ${people[$idx]}" 248 done 249 250 # 更新所有职能索引 251 for department in "${!ROSTER[@]}"; do 252 # 解析人员数组 253 IFS=',' read -ra people <<< "${ROSTER[$department]}" 254 255 # 获取当前索引并转换为整数 256 local idx=${current_index[$department]} 257 idx=$((idx)) 258 259 # 更新索引(循环) 260 local count=${#people[@]} 261 local new_idx=$(( (idx + 1) % count )) 262 263 # 更新索引 264 current_index[$department]=$new_idx 265 log "轮换: ${department} 索引 $idx → $new_idx" 266 done 267 268 # 保存新索引 269 save_index 270 271 # 记录轮换后的人员 272 for department in "${!ROSTER[@]}"; do 273 IFS=',' read -ra people <<< "${ROSTER[$department]}" 274 # 获取新索引并转换为整数 275 local new_idx=${current_index[$department]} 276 new_idx=$((new_idx)) 277 log "轮换后: ${department} = ${people[$new_idx]}" 278 done 279 else 280 log "非轮换日,保持当前索引" 281 fi 282 283 # 记录当前值周人员(仅日志) 284 for department in "${!ROSTER[@]}"; do 285 IFS=',' read -ra people <<< "${ROSTER[$department]}" 286 local idx=${current_index[$department]} 287 idx=$((idx)) 288 log "当前值周: ${department} = ${people[$idx]}" 289 done 290 291 # 构建并发送通知 292 local message=$(build_message) 293 log "发送值周通知:\n$message" 294 send_notification "$message" 295 296 log "通知任务完成" 297 } 298 299 # 执行主函数 300 main
2:利用jenkins定时触发这个脚本
jenkins触发服务器脚本,可以看我之前的一篇文章,这次还得实现定时触发,只需要在构建触发器选择Build periodically填入规则即可,我这个是每天22点执行,因为shell脚本会过滤周六周日,所以jenkins就不用过滤了


浙公网安备 33010602011771号