Hubot是一个通用的聊天机器人,能和很多聊天软件集成,比如slack、rockchat、telegram、企业微信、IRC等。

公司用的是企业微信,之前用群机器人和 prometheus 集成,发送各种告警信息,但是群机器人无法接收消息;同时我们想集成进去很多自定义命令,比如发送指令就开始 jenkins build,发送 ansible 指令执行,发送流量图就自动把机房的流量图发过来,这个群机器人就用不成了。所以必须再直接一些,构建一个企业微信的应用。

一、企业微信安装前准备

安装前需要在企业微信中拿到4个信息:

  1. WECHATWORK_CORP_ID
  2. WECHATWORK_APP_AGENT_ID
  3. WECHATWORK_APP_SECRET
  4. WECHATWORK_AES_KEY

首先联系企业微信管理员新增一个应用:

image-20211222144935256

在“管理后台-我的企业”中可以获得地一个信息,企业 ID 信息,CORP_ID :

image-20211222144654696拿拿 在“管理后台-应用管理-点击某具体应用-详情”页中可以获得二、三个信息, APP_AGENT_ID 和 APP_SECRET

image-20211222150424143

第四个 AES_KEY 就比较麻烦了,我们进入这个应用,点击配置的图标:

image-20211222151155307

然后进入,点击启用 API 接收

image-20211222151325525

然后设置一下

image-20211222151552345

然后点击保存,这里必然会失败!没有关系,因为我们还没有装hubot呢。我们把这三个地方先记录下来,随后再来点击保存。

二、Hubot 安装前准备

1、注意上面地址:URL 地址是 https ,然后 hubot 的缺省地址是 http://xxx:8080 ,这样如果前面没有证书卸载的设备,就得搭建一个Nginx(haproxy、traefik)来代理 https 443端口到8080。

2、Hubot 是支持 Coffeescript 和 nodejs 的,从它的 Adapters 网页看

https://hubot.github.com/docs/adapters/development/

里面都是 coffee 味的单箭头函数,导致不太熟悉的八戒以为在 wechatwork module导出的时候也应该用单箭头函数,结果就悲剧了。

所以务必清楚,Adapter 的语法是 js,普通自建自动回复script可以用coffeescript,后面会详细说这一点。

3、安装Hubot必须新建一个普通用户,不能用 root 装

用 root 会导致 nodejs 一堆报错,八戒新建了一个用户 bot,家目录/home/bot,然后再在这下面建立/home/bot/myhubot,在这个目录下安装。

理由是这个如果直接装在这个用户的 home 目录下,会导致这个用户只能有这一个用途了,目录结构太浅,一堆文件

4、Hubot的变量引入都是通过环境变量引入的

所以无论什么wechatwork还是jenkins,都需要通过环境变量导入变量

三、安装Hubot

首先安装nvm,参看文章 Nodejs多版本的安装与管理

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash

安装的时候最好加个 https_proxy 代理,因为这个 shell 脚本不翻墙很难下下来。

然后务必关了代理,退出终端并重新进入,安装 nodejs 的最新版本

nvm ls-remote
nvm install v16.13.1
nvm list

image-20211222154655729

确认一下,nodejs 的版本缺省是 v16.13.1

这里千万不要手欠把 npm 的源换成国内的腾讯等,就是国外源

然后安装hubot,并初始化

su - bot
npm install -g yo generator-hubot

mkdir /home/bot/myhubot
cd /home/bot/myhubot
yo hubot

会问几个问题:

  • Ower:写自己邮箱就行
  • Bot name: bot
  • Description: rendoumi corp
  • Bot adapter: campfire

注意最后一个,选campfire就好,我们稍后再装wechatwork

                     _____________________________  
                    /                             \ 
   //\              |      Extracting input for    |
  ////\    _____    |   self-replication process   |
 //////\  /_____\   \                             / 
 ======= |[^_/\_]|   /----------------------------  
  |   | _|___@@__|__                                
  +===+/  ///     \_\                               
   | |_\ /// HUBOT/\\                             
   |___/\//      /  \\                            
         \      /   +---+                            
          \____/    |   |                            
           | //|    +===+                            
            \//      |xx|                            

? Owner zhangranrui@rendoumi.com
? Bot name bot
? Description rendoumi corp
? Bot adapter campfire

然后就会是漫长的等待:

image-20211222155430133

最后会报几个警告,不用管,忽略即可。

npm notice created a lockfile as package-lock.json. You should commit this file.
+ hubot-help@1.0.1
+ hubot-google-images@0.2.7
+ hubot-rules@1.0.0
+ hubot-shipit@0.2.1
+ hubot-redis-brain@1.0.0
+ hubot-google-translate@0.2.1
+ hubot-diagnostics@1.0.0
+ hubot-scripts@2.17.2
+ hubot@3.3.2
+ hubot-maps@0.0.3
+ hubot-heroku-keepalive@1.0.3
+ hubot-pugme@0.1.1
added 99 packages from 53 contributors and audited 99 packages in 20.176s

2 packages are looking for funding
  run `npm fund` for details

found 1 low severity vulnerability
  run `npm audit fix` to fix them, or `npm audit` for details

我们先跑一下,简单测一下功能,我们的bot name输入的是bot

cd /home/bot/myhubot

./bin/hubot

#进入后
bot ping

#得到回应
PONG

这样就装好了 hubot,我们做一下修改,去掉 heroku 和 redis,否则会不停丢出报错信息,但是不要用 npm 去删除这两个包,放着那里备用也不占多少空间的

cd /home/bot/myhubot

vi external-scripts.json
[
  "hubot-diagnostics",
  "hubot-help",
  "hubot-heroku-keepalive",
  "hubot-google-images",
  "hubot-google-translate",
  "hubot-pugme",
  "hubot-maps",
  "hubot-redis-brain",
  "hubot-rules",
  "hubot-shipit"
]

#去掉下面两行
hubot-heroku-keepalive
hubot-redis-brain

三、安装微信 Adapter

Adapter 插件,hubot是一套系统,通过各种插件跟各种聊天软件进行交互

微信插件原始地址:https://github.com/billtt/hubot-wechatwork

八戒稍微改了一下:https://github.com/zhangrr/hubot-wechatwork

主要是添加了个自动回应和添加了一些调试信息,否则不知道加载成不成功。

#先装那个老的
cd /home/bot/myhubot
npm install hubot-wechatwork

#覆盖掉老的模块
cd /home/bot/myhubot/node_modules
git clone https://github.com/zhangrr/hubot-wechatwork

启动之前普及一下 hubot 基本知识,hubot 中变量的传入都是通过环境变量导入的,启动测试一下wechatwork

export WECHATWORK_CORP_ID=aaaa
export WECHATWORK_APP_AGENT_ID=bbbb
export WECHATWORK_APP_SECRET=cccc
export WECHATWORK_AES_KEY=dddd

cd /home/bot/myhubot
./bin/hubot -a wechatwork

看到信息,INFO Yunwei: loading wechatwork Adapter,说明启动没啥毛病

image-20211228152907465

然后我们回到企业微信这个应用的应用管理,点击保存接收消息服务器配置,这次就应该能成功了。

测试一下,我们在企业微信中,对这个应用机器人私聊,发个 hi:

image-20211228153139262

再发个help,会冒出一堆信息

image-20211228153351091

然后我们可以试试指令,再发个ping,机器人回PONG,这就算正常工作了

image-20211228153542953

同时我们在终端也可以看到接收到的消息

image-20211228153847963

要注意的命令:

wechatwork 有一条命令 chat create CHATID USER1,USER2,USER3,…

解释一下,是用来建立一个企业微信群聊的,群主默认是第一个人:

chatid 是指一个群聊的 id 号,格式是字母+数字,比如yunwei001,这个一旦创建就无法销毁,会永远保存在企业微信那里,切切记住!!!

user1,user2 这种是员工企业微信的id,通常是用户名全称,比如 zhangrenren,liudaqiang

所以说的时候务必要小心,万万记住 chatid 一旦建立就无法收回。

之后可以调用 sendChatMessage 来给群聊发送消息。

image-20211228163631248

四、准备systemd启动hubot

这样不能每次用个终端启动 hubot 吧,写个 systemd 文件来处理吧

由于我们用到了nvm,这里确实需要一些技巧,cat /etc/systemd/system/hubot.service

[Unit]
Description=Hubot
Requires=network.target
After=network.target

[Service]
Type=simple
WorkingDirectory=/home/bot/myhubot
User=bot

Restart=always
TimeoutStartSec=10
RestartSec=10

; Configure Hubot environment variables, use quotes around vars with whitespace as shown below.
; Environment="HUBOT_SLACK_TOKEN=SLACK_TOKEN"
; Environment="HUBOT_JENKINS_AUTH=pe:x837491lkaflajksdf7"
; Environment="HUBOT_JENKINS_URL=http://192.168.1.90:8080/"
Environment="NODE_VERSION=default"
Environment="WECHATWORK_CORP_ID=aaaa"
Environment="WECHATWORK_APP_AGENT_ID=bbbb"
Environment="WECHATWORK_APP_SECRET=cccc"
Environment="WECHATWORK_AES_KEY=dddd"

ExecStart=/home/bot/.nvm/nvm-exec /home/bot/myhubot/bin/hubot --adapter wechatwork

[Install]
WantedBy=multi-user.target

注意上面,我们指定了环境变量 NODE_VERSION=default,以及最下的 ExecStart,确定用 nvm-exec 引动 node

另外把 wechatwork 所需的4个参数也放进环境变量中,这样重启就可以了

systemctl daemon-reload
systemctl start hubot

五、集成jenkins

准备知识,我们必须在 jenkins 拿到用户名和 token(token是用来代替密码的),用来访问 jenkins

首先登录 jenkins,访问网址:$JENKINS_URL/me/configure,新建一个 API Token,记录下来

image-20211228155054104

用法很简单:token替代密码用于 url 认证即可。

cd /home/bot/myhubot
npm install hubot-jenkins-optimised 

#编辑external-scripts.json
vi external-scripts.json
[
  "hubot-diagnostics",
  "hubot-help",
  "hubot-google-images",
  "hubot-google-translate",
  "hubot-pugme",
  "hubot-maps",
  "hubot-rules",
  "hubot-shipit",
  "hubot-jenkins-optimised"
]

#上面增加了一行
hubot-jenkins-optimised

#编辑 /etc/systemd/system/hubot.service ,添加 jenkins 的环境变量
#jenkins的用户名是pe,所有auth是 "pe:x837491lkaflajksdf7"
......
Environment="HUBOT_JENKINS_AUTH=pe:x837491lkaflajksdf7"
Environment="HUBOT_JENKINS_URL=http://192.168.1.90:8080/"
......

# 重启 hubot
systemctl daemon-reload
systemctl restart hubot

然后我们私聊这个机器人,对它说: jenkins list,就可以看到项目了, jenkins b 3 就可以开始build第三个项目了,所有命令可以通过对机器人说 help 来获得

image-20211228155834837

六、集成ansible

集成 ansible,其实就是集成一个 shell,也很简单

cd /home/bot/myhubot
npm install hubot-script-shellcmd

#编辑external-scripts.json
vi external-scripts.json
[
  "hubot-diagnostics",
  "hubot-help",
  "hubot-google-images",
  "hubot-google-translate",
  "hubot-pugme",
  "hubot-maps",
  "hubot-rules",
  "hubot-shipit",
  "hubot-jenkins-optimised",
  "hubot-script-shellcmd"
]

#上面增加了一行
hubot-script-shellcmd

#把shellcmd目录下的bash目录,复制一份到/home/bot/myhubot/bash
cp -R node_modules/hubot-script-shellcmd/bash ./

#我们把ansible的yml都放到/homebot/myhubot/bash/ansible目录下
cd /home/bot/myhubot/bash
mkdir ansible

#把ansible-playbook的yml都放进去
....

#然后编写命令脚本
cd /home/bot/myhubot/bash/handles

cat < EOF >> fuse
#!/bin/bash

if [ -n "$1" ] ; then 
  if [ -n "$2" ] ; then 
     ansible-playbook /home/bot/myhubot/bash/ansible/check-disk.yml  -e "ip=$1 fs=$2"
  else
     ansible-playbook /home/bot/myhubot/bash/ansible/check-disk.yml  -e "ip=$1 fs=/"
  fi
fi

exit 0
EOF

#给执行权
chmod 755 /home/bot/myhubot/bash/handles/fuse

#重启hubot
systemctl restart hubot

check-disk.yml 的真身,是在远程机器上调用本机才有的rust dust命令,来算出远程机器的某个目录的使用情况

---
- name:  check machine disk space
  hosts: "{{ ip }}"
  gather_facts: false
  vars:
  - ip: "{{ ip }}"
  - fs: "{{ fs }}"
  - ansible_ssh_user: "root"
  - ansible_ssh_pass: "Fuck2021!"
  - ansible_ssh_common_args: "-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
  - host_key_checking: False
  tasks:
  - name: Run a script with arguments (using 'cmd' parameter)
    ansible.builtin.script:
      cmd: /usr/local/bin/dust -bcr {{ fs }}
    register: output

  - debug: var=output.stdout_lines

我们在企业微信对机器说 shell ,就会得到所有命令列表

image-20211228161435568

对它说 shell fuse 172.19.16.1 /export ,就会把本机才有的 dust 命令,拷贝到172.19.16.1的机器上,并对 /export 执行,得到占磁盘空间最大的文件和目录。

image-20211228161857621

参考资料:

https://qydev.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E

http://sd.blackball.lv/library/Automation_and_Monitoring_with_Hubot_(2014).pdf