shell脚本定时推送钉钉战报

news2024/11/28 6:37:48

一、目的与演示效果

解析服务端返回的如下字符串,获取今日数据、历史数据,实现钉钉定时推送战报效果。

{
    "code": "00000",
    "msg": "",
    "success": true,
    "data": {
        "2023-07-19": [
            "1673945805117063168",
            "1671561317942689792",
            "1658787124574552064",
            "1675750158471659520"
        ],
        "2023-07-20": [
            "1673945805117063168",
            "1671561317942689792",
            "1658787124574552064",
            "1675750158471659520"
        ]
    },
    "ref": null
}
image-20230720135026012

二、请求网络

1、curl获取数据并赋值变量

在shell中直接使用curl http://www.baidu.com会出现下载器,因此我们拼接一个-s

对于接收数据的变量api_result:其后面的等号前后都不要有空格。

对于要执行的函数:用反单引号包裹起来

api_result=`curl -s http://www.baidu.com`

也可以使用eval函数来执行。以下为等价写法:

api_result=`eval 'curl -s http://www.baidu.com'`

2、带参数

对于整个地址用引号(单、双都可)拼接起来,要不然不识别拼接的参数。示例:

api_result=`eval 'curl -s "http://www.baidu.com?s=1&c=ANDROID"'`

等价eval写法:

api_result=`curl -s 'http://www.baidu.com?s=1&c=ANDROID'`

3、封装网络请求方法

对于请求网络,往往是为了拿到里层的data数据。因此可以考虑封装方法来复用。这里含有以下知识点:

1、方法参数传递使用$1 $2 $3等,代表第一个参数、第二个参数的意思。

调用的时候把参数放方法后面,中间以空格连接即可。

2、echo为返回,不要用return,return只能返回数字类型。

#!/bin/bash
# 请求网络,拿到里层data数据
# {"code":"00000","msg":"","success":true,"data":{"2023-07-12":["1679009176166203392"]},"ref":null}
checkUploadResult(){
  api_result=`eval $1` # 执行api_result,拿到返回的结果
  data=$(echo $api_result | jq -r '.data')
  echo $data
}
# 调用方法
androidTotalTodo=`checkUploadResult "curl -s 'http:/www.baidu.com?s=1&c=ANDROID'"`

三、json解析

shell的json解析,这里以jq解析为主,以封装的getJsonValuesByAwk解析为辅。主要是jq解析获取key的时候要求key不能是数字

1、根据key获取value (key非数字)

【key非数字】从json数据api_result中取data,即可这样写

api_result='{"code":"00000","msg":"","success":true,"data":{"2023-07-12":["1679009176166203392"]},"ref":null}'
data=$(echo $api_result | jq -r '.data')
echo $data

# 打印数据:{ "2023-07-12": [ "1679009176166203392" ] }

【key为数字】这个时候使用jq解析会报错

json='{"2023-07-12":["1679009176166203392"],"2023-07-13":["1679009176166203392"]}'
data=$(echo $json | jq -r '.2023-07-12')
echo $data
# 打印数据:-18.7977

然后我们使用getJsonValuesByAwk解析就正常了

### 方法简要说明:
### 1. 是先查找一个字符串:带双引号的key。如果没找到,则直接返回defaultValue。
### 2. 查找最近的冒号,找到后认为值的部分开始了,直到在层数上等于0时找到这3个字符:,}]。
### 3. 如果有多个同名key,则依次全部打印(不论层级,只按出现顺序)
### @author lux feary
###
### 3 params: json, key, defaultValue
function getJsonValuesByAwk() {
    awk -v json="$1" -v key="$2" -v defaultValue="$3" 'BEGIN{
        foundKeyCount = 0
        while (length(json) > 0) {
            # pos = index(json, "\""key"\""); ## 这行更快一些,但是如果有value是字符串,且刚好与要查找的key相同,会被误认为是key而导致值获取错误
            pos = match(json, "\""key"\"[ \\t]*?:[ \\t]*");
            if (pos == 0) {if (foundKeyCount == 0) {print defaultValue;} exit 0;}

            ++foundKeyCount;
            start = 0; stop = 0; layer = 0;
            for (i = pos + length(key) + 1; i <= length(json); ++i) {
                lastChar = substr(json, i - 1, 1)
                currChar = substr(json, i, 1)

                if (start <= 0) {
                    if (lastChar == ":") {
                        start = currChar == " " ? i + 1: i;
                        if (currChar == "{" || currChar == "[") {
                            layer = 1;
                        }
                    }
                } else {
                    if (currChar == "{" || currChar == "[") {
                        ++layer;
                    }
                    if (currChar == "}" || currChar == "]") {
                        --layer;
                    }
                    if ((currChar == "," || currChar == "}" || currChar == "]") && layer <= 0) {
                        stop = currChar == "," ? i : i + 1 + layer;
                        break;
                    }
                }
            }

            if (start <= 0 || stop <= 0 || start > length(json) || stop > length(json) || start >= stop) {
                if (foundKeyCount == 0) {print defaultValue;} exit 0;
            } else {
                print substr(json, start, stop - start);
            }

            json = substr(json, stop + 1, length(json) - stop)
        }
    }'
}

json='{"2023-07-12":["1679009176166203392"],"2023-07-13":["1679009176166203392"]}'
data=`getJsonValuesByAwk "$json" '2023-07-12' '没有数据'`
echo $data

# 打印数据:["1679009176166203392"]

2、获取数组长度

list='["1679009176166203392"]'
arr=($(echo $list | tr -d '[],'))
echo "${#arr[@]}"

# 打印数据:1

3、删除json中的某个key

json='{"2023-07-12":["1679009176166203392"],"2023-07-13":["1679009176166203392"]}'
json=$(echo "$json" | jq 'del(.["2023-07-12"])')
echo "$json"

# 打印数据:
#{
#  "2023-07-13": [
#    "1679009176166203392"
#  ]
#}

4、删除空格与引号

钉钉要求文案中不能有空格与引号,否则推送报错。

# 删除空格
dingtalkResult="${dingtalkResult// /}"
# 删除引号"
dingtalkResult=${dingtalkResult//"\""/}

5、判断数据是否为空

比如对未声明的变量json。前面判断是否是字符串null,后边"-z"选项来检查变量是否为空。

#!/bin/bash

# null字符串或者空
if [ "$json" = "null" ] || [ -z "$json" ]; then
    echo '数据空'
else
    echo '数据不空'
fi

# 打印数据:数据空

四、钉钉推送

提供两种,一种是带At一种不带

# 钉钉通知
notifyDingTalk(){
  curl "https://oapi.dingtalk.com/robot/send?access_token=$DKEY" \
    -H 'Content-Type: application/json' \
    -d '{
          "msgtype": "text",
          "text": {
                   "content": "'$1'"
               },
      }'
}

# 钉钉通知带at
notifyDingTalkWithAt(){
  curl "https://oapi.dingtalk.com/robot/send?access_token=$DKEY" \
    -H 'Content-Type: application/json' \
    -d '{
          "msgtype": "text",
          "text": {
                   "content": "'$1'"
               },
               "at": {
                   "atMobiles": [
                       "1875819063x",
                       "1580366544x"
                   ],
                   "isAtAll": false
               }
      }'
}

使用如下

notifyDingTalk '这是发给钉钉的文案'
notifyDingTalkWithAt '这是发给钉钉的文案'

配置安全文案即可

image-20230720145547407

五、jenkins配置

jenkins配置定时器如下

H 17 * * *

会提示构建时间

image-20230720145414686

六、源码

敏感信息部分以xxx打码,替换自己的后不影响运行。

#!/bin/bash

# 当前时间(示例:2023-07-15)
cur_time=`date +"%F"`
#钉钉key
DKEY="65f276f7747278212d5fb85729117037bb62485b7573eb6b1ba028acf2ef6xxx"

# 默认为null字符串
emptyValue=null

### 方法简要说明:
### 1. 是先查找一个字符串:带双引号的key。如果没找到,则直接返回defaultValue。
### 2. 查找最近的冒号,找到后认为值的部分开始了,直到在层数上等于0时找到这3个字符:,}]。
### 3. 如果有多个同名key,则依次全部打印(不论层级,只按出现顺序)
### @author lux feary
###
### 3 params: json, key, defaultValue
function getJsonValuesByAwk() {
    awk -v json="$1" -v key="$2" -v defaultValue="$3" 'BEGIN{
        foundKeyCount = 0
        while (length(json) > 0) {
            # pos = index(json, "\""key"\""); ## 这行更快一些,但是如果有value是字符串,且刚好与要查找的key相同,会被误认为是key而导致值获取错误
            pos = match(json, "\""key"\"[ \\t]*?:[ \\t]*");
            if (pos == 0) {if (foundKeyCount == 0) {print defaultValue;} exit 0;}

            ++foundKeyCount;
            start = 0; stop = 0; layer = 0;
            for (i = pos + length(key) + 1; i <= length(json); ++i) {
                lastChar = substr(json, i - 1, 1)
                currChar = substr(json, i, 1)

                if (start <= 0) {
                    if (lastChar == ":") {
                        start = currChar == " " ? i + 1: i;
                        if (currChar == "{" || currChar == "[") {
                            layer = 1;
                        }
                    }
                } else {
                    if (currChar == "{" || currChar == "[") {
                        ++layer;
                    }
                    if (currChar == "}" || currChar == "]") {
                        --layer;
                    }
                    if ((currChar == "," || currChar == "}" || currChar == "]") && layer <= 0) {
                        stop = currChar == "," ? i : i + 1 + layer;
                        break;
                    }
                }
            }

            if (start <= 0 || stop <= 0 || start > length(json) || stop > length(json) || start >= stop) {
                if (foundKeyCount == 0) {print defaultValue;} exit 0;
            } else {
                print substr(json, start, stop - start);
            }

            json = substr(json, stop + 1, length(json) - stop)
        }
    }'
}

# 请求网络,拿到里层data数据
# {"code":"00000","msg":"","success":true,"data":{"2023-07-12":["1679009176166203392","1676130723649683456","1675059618608447488","1674345317023219712","1672586086360154112","1673586172305211392","1673950865947492352","1675757864595095552","1670766831293562880","1674976668499968000","1676513810044813312","1676512377715163136","1675146378722017280","1673687264389103616","1675283959501684736","1674213349681922048","1675545501522591744","1674269196629966848","1669551312678813696","1675366041963855872","1675445816296341504","1668133451263508480","1673610261883387904","1673945805117063168","1671561317942689792","1658787124574552064","1675750158471659520"]},"ref":null}
checkUploadResult(){
  api_result=`eval $1` # 执行api_result,拿到返回的结果
  data=$(echo $api_result | jq -r '.data')
  echo $data
}

# 获取今天的数据
getTodayList(){
  json=`getJsonValuesByAwk "$1" $cur_time $emptyValue`
  echo $json
}

getArrayLengthFromString(){
  # null或者null字符串
  if [ "$1" = "null" ] || [ -z "$1" ]; then
      echo 0
  else
    arr=($(echo "$1" | tr -d '[],'))
    echo "${#arr[@]}"
  fi
}

# 删除今日数据
deleteTodayData(){
  # null或者null字符串
  if [ "$1" = "null" ] || [ -z "$1" ]; then
      echo {}
  else
    # 转正常json
      # 使用 jq 命令将 JSON 字符串变量转换为 JSON 变量
      # json=$(echo "$1" | jq .)
      # 删除今日数据
      json=$(echo "$json" | jq 'del(.["'$cur_time'"])')
      echo "$json"
  fi
}

# 总计
androidTotalTodo=`checkUploadResult "curl -s 'https://pre-api.xxx.com/na/api/manual/v2/getVideoInfo?s=1&c=ANDROID'"`
androidTotalFinish=`checkUploadResult "curl -s 'https://pre-api.xxx.com/na/api/manual/v2/getVideoInfo?s=2&c=ANDROID'"`
# 今日
androidTodayTodo=`getTodayList "$androidTotalTodo"`
androidTodayFinish=`getTodayList "$androidTotalFinish"`

# 总计
iosTotalListTodo=`checkUploadResult "curl -s 'https://pre-api.xxx.com/na/api/manual/v2/getVideoInfo?s=1&c=IOS'"`
iosTotalListFinish=`checkUploadResult "curl -s 'https://pre-api.xxx.com/na/api/manual/v2/getVideoInfo?s=2&c=IOS'"`
# 今日
iosTodayTodo=`getTodayList "$iosTotalListTodo"`
iosTodayFinish=`getTodayList "$iosTotalListFinish"`

dingtalkResult+="一、今日待上传"
dingtalkResult+="\n1、安卓今日待上传:【"`getArrayLengthFromString "$androidTodayTodo"`"个】\n"$androidTodayTodo
dingtalkResult+="\n2、ios今日待上传:【"`getArrayLengthFromString "$iosTodayTodo"`"个】\n"$iosTodayTodo

dingtalkResult+="\n\n二、今日完成"
dingtalkResult+="\n1、安卓完成上传:【"`getArrayLengthFromString "$androidTodayFinish"`"个】"
dingtalkResult+="\n2、ios完成上传:【"`getArrayLengthFromString "$iosTodayFinish"`"个】"

dingtalkResult+="\n\n三、历史待上传"
androidTotalTodo=`deleteTodayData $androidTotalTodo`
iosTotalListTodo=`deleteTodayData $iosTotalListTodo`

# 使用 jq 命令将 JSON 对象转换为字符串
sum_androidTotalTodo=$(echo "$androidTotalTodo" | jq -c .)
# 判断整数值是否为 0
if [ "${#sum_androidTotalTodo}" -eq 0 ]; then
  dingtalkResult+="\n1、安卓历史待上传统计:{}"
else
  dingtalkResult+="\n1、安卓历史待上传统计:"$androidTotalTodo
fi

# 使用 jq 命令将 JSON 对象转换为字符串
sum_iosTotalListTodo=$(echo "$iosTotalListTodo" | jq -c .)
# 判断整数值是否为 0
if [ "${#sum_iosTotalListTodo}" -eq 0 ]; then
  dingtalkResult+="\n1、ios历史待上传统计:{}"
else
  dingtalkResult+="\n1、ios历史待上传统计:"$iosTotalListTodo
fi

# 删除空格
dingtalkResult="${dingtalkResult// /}"
# 删除引号"
dingtalkResult=${dingtalkResult//"\""/}

# 钉钉通知
notifyDingTalk(){
  curl "https://oapi.dingtalk.com/robot/send?access_token=$DKEY" \
    -H 'Content-Type: application/json' \
    -d '{
          "msgtype": "text",
          "text": {
                   "content": "'$1'"
               },
      }'
}

# 钉钉通知带at
notifyDingTalkWithAt(){
  curl "https://oapi.dingtalk.com/robot/send?access_token=$DKEY" \
    -H 'Content-Type: application/json' \
    -d '{
          "msgtype": "text",
          "text": {
                   "content": "'$1'"
               },
               "at": {
                   "atMobiles": [
                       "18758190xxx",
                       "15803665xxx"
                   ],
                   "isAtAll": false
               }
      }'
}

if test "$androidTodayTodo" != null && test "$iosTodayTodo" != null; then
    notifyDingTalk $cur_time":今天andriod、ios视频都未上传完!以下是具体数据:"
    notifyDingTalk $dingtalkResult
elif test "$androidTodayTodo" != null; then
    notifyDingTalk $cur_time":今天andriod视频未上传完!以下是具体数据:"
    notifyDingTalk $dingtalkResult
elif test "$iosTodayTodo" != null; then
    notifyDingTalk $cur_time":今天ios视频未上传完!以下是具体数据:"
    notifyDingTalk $dingtalkResult
else
    notifyDingTalk $cur_time"今日视频上传完毕!辛苦了!"
fi

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/777865.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

nacos适配达梦、瀚高、人大金仓数据库及部分源码探究

一.插件实现 1.插件目录结构 2.pom依赖 <dependency><groupId>com.alibaba.nacos</groupId><artifactId>nacos-datasource-plugin</artifactId><version>2.2.4</version></dependency><dependency><groupId>org.s…

自动化测试(二):安卓机初探与Python实现andriod截图实例

目录 1.安卓开发常用术语介绍2. 各种SDK的安装&#xff08;陆续补充ing&#xff09;2.1 JDK的安装2.2 单独安装Android SDK部分组件2.3 Android NDK的安装 3. pythonminicap实现andriod截图实例4. TODO 1.安卓开发常用术语介绍 IDE (Integrated Development Environment) : 集成…

索引的本质与数据结构

点击上方↑“追梦 Java”关注&#xff0c;一起追梦&#xff01; 正确合理的创建索引是提升数据库查询性能的基础&#xff0c;因此针对数据库来说&#xff0c;索引是必须要掌握的。 1 数据库索引的本质 我们一说到索引&#xff0c;如果大家想到是一个类似于字典的目录&#xff0…

Eclipse整合tomcat时要注意的几点

Eclipse整合tomcat时要注意的几点 1、安装目录及jdk 2、参数配置 注意&#xff1a;Arguments的配置&#xff0c;日志输出文件目录及java内存大小设置等&#xff0c;如下&#xff1a; -Dcatalina.base"E:\apache-tomcat-7.0.52" -Dcatalina.home"E:\apache-tomc…

【hadoop】Java API连接(操作)HDFS

Java API连接&#xff08;操作&#xff09;HDFS 直接连接遇到的问题设置执行的用户为root用户使用Java的-D参数来设置环境变量使用chmod的命令赋予权限修改参数配置 直接连接遇到的问题 直接运行下面的代码&#xff0c;会出现权限不够的问题 Test public void test1() throws…

Meta牵手Microsoft推出下一代Llama 2

官方消息 1、今天&#xff0c;我们将介绍 Llama 2 的可用性&#xff0c;这是我们的下一代开源大型语言模型。 2、Llama 2免费用于研究和商业用途。 3、Microsoft和 Meta 正在扩大他们的长期合作伙伴关系&#xff0c;Microsoft 是 Llama 2 的首选合作伙伴。 4、在技术、学术…

[SQL系列] 从头开始学PostgreSQL 自增 权限和时间

[SQL系列] 从头开始学PostgreSQL 事务 锁 子查询_Edward.W的博客-CSDN博客https://blog.csdn.net/u013379032/article/details/131841058上一篇介绍了事务&#xff0c;锁&#xff0c;子查询 事务有点像是原子操作&#xff0c;需要有完整性&#xff0c;要么全都完成了&#xff…

【目标跟踪】2、FairMOT | 平衡多目标跟踪中的目标检测和 Re-ID 任务 | IJCV2021

文章目录 一、背景二、方法2.1 Backbone2.2 检测分支2.3 Re-ID 分支2.4 训练 FairMOT2.5 Online Inference 三、效果3.1 数据集3.2 实现细节3.3 消融实验3.4 最终效果 论文&#xff1a;FairMOT: On the Fairness of Detection and Re-Identification in Multiple Object Tracki…

基于大模型的Text2SQL微调的实战教程

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

(转载)基于 BP_Adaboost 的强分类器设计(matlab实现)

本博客的完整代码获取&#xff1a; https://www.mathworks.com/academia/books/book106283.html 1案例背景 1.1 BP_Adaboost模型 Adaboost算法的思想是合并多个“弱”分类器的输出以产生有效分类。其主要步骤为:首先给出弱学习算法和样本空间(x,y),从样本空间中找出m组训练数…

Postman传递对象参数(包含有集合对象)

postman通常需要传递各式各样的参数&#xff0c;本文主要介绍了Postman传递对象参数(包含有集合对象)&#xff0c;具有一定的参考价值&#xff0c;感兴趣的小伙伴们可以参考一下 项目场景&#xff1a; postman通常需要传递各式各样的参数&#xff0c;这样的话&#xff0c;进行…

自然语言处理与词嵌入

1、词表特征 前面介绍过表征单词的方式是首先建立一个较大的词汇表&#xff08;例如10000&#xff09;&#xff0c;然后使用one-hot的方式对每个单词进行编码。例如单词Man&#xff0c;Woman&#xff0c;King&#xff0c;Queen&#xff0c;Apple&#xff0c;Orange分别出现在词…

Docker数据管理和网络通信 dockerfile

Docker数据管理和网络通信 dockerfile 一&#xff1a;Docker 的数据管理1&#xff0e;数据卷2&#xff0e;数据卷容器 二&#xff1a;端口映射三&#xff1a;容器互联&#xff08;使用centos镜像&#xff09;四&#xff1a;Docker 镜像的创建1&#xff0e;基于现有镜像创建2&am…

C++入门先填坑

C是在C的基础之上&#xff0c;容纳进去了面向对象编程思想&#xff0c;并增加了许多有用的库&#xff0c;以及编程范式等。熟悉C语言之后&#xff0c;对C学习也有一定的帮助。 C入门先填坑系列主要内容会围绕以下方面 补充C语言语法的不足&#xff0c;以及C是如何对C语言设计不…

servlet Filter与spring的OncePerRequestFilter

servlet 规范 javax.servlet Filter 任何的servlet容器都要实现的&#xff0c;例如tomcat、undertow、jetty等等。类似于jdbc规范&#xff0c;制定好了一个约束&#xff0c;各家数据库厂商根据规范开发对应的驱动来实现访问自己的数据库。 spring 对于Filter的自定义实现 所…

NLP(六十)Baichuan-13B-Chat模型使用体验

2023年7月11日&#xff0c;百川智能正式发布参数量130亿的通用大语言模型Baichuan-13B-Base、对话模型Baichuan-13B-Chat及其INT4/INT8两个量化版本。   本文将介绍大模型BaiChuan-13B-Chat的使用体验&#xff0c;其HuggingFace网址为&#xff1a;https://huggingface.co/bai…

【C语言day02】

转义字符 \\ 表示字符\&#xff0c;\123表示字符{&#xff0c;\t表示制表符&#xff0c;这些都是一个字符宏只是替换 替换后NUM的样子是(211)*21/2常量指针与指针常量 const和* 来区别&#xff0c;如果是const * 这样的顺序就是常量指针&#xff0c;所以说他的本质是指针&am…

uni-app:请求后端数据uni.request

完整代码&#xff1a; onLoad() {uni.request({url: getApp().globalData.position Produce/select_employee,data: {username: getApp().globalData.username,},method: POST,dataType: json,success: res > {this.employee_name res.data.info.employee_name;// consol…

uniapp 之 微信小程序、支付宝小程序 对于自定义导航栏的不同

目录 前言 微信小程序 代码 支付宝小程序 首页配置文件 二级菜单页面 配置 总结 不同 相同 前言 小程序都是 uni-app 写的 不是原生 微信小程序 代码 pages.json文件中配置 重点&#xff1a; "navigationStyle": "custom", // 导航栏样式…

安卓开发日记问题记录(隐藏标题栏中的应用名称)

当我们设置了显示标题栏&#xff0c;应用名也会显示出来&#xff0c;这对设置标题栏内容很不方便 可以在activity里的onCreate部分设置这句代码隐藏APP名字 getSupportActionBar().setDisplayShowTitleEnabled(false);或者改变它 getSupportActionBar().setTitle("new …