利用shell脚本结合jenkins定期发送值周通知到企业微信

最近项目有个需求是要每天把值周名单发到企业微信机器人上

主要实现步骤大概是

  1. 利用jenkins定时触发任务,远程执行服务器的shell脚本
  2. shell脚本实现发送消息到企业微信
  3. 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就不用过滤了

 

posted @ 2025-07-09 11:57  Hiro-D  阅读(49)  评论(0)    收藏  举报