业务场景

公司是做体育测试相关的产品,有大量的现场业务视频要传回公司留存,但是由于现场网络,像素等原因,无法通过公网传输,只能拍摄完成后存入移动硬盘带回公司上传服务器,并上传阿里OSS云存储。



文章目录

  • 前言
  • 一、项目流程
  • 二、实现步骤
  • 1.配置环境
  • 2.编写物理机脚本
  • 3.编写Python发送脚本
  • 4.编写虚拟机脚本
  • 5.测试并验证结果
  • 6.创建自动执行拷贝
  • 总结



前言

我们公司的环境是物理服务器上搭建的KVM,创建的Centos7虚拟机。(公司比较穷得会过日子)

本项目需要安装一些插件,请自行安装。插件有:Ansible、Python3.7、Expect。


一、项目流程

因为虚拟机不能直接识别物理机的USB设备,所以我们要把U盘从物理机挂载到虚拟机上,我们还要创建相应的设备文件给虚拟机,让他可以识别USB设备。从而实现后面一系列的自动操作,大体流程如下:

USB设备插入物理服务器   →  检测有设备接入挂载到虚拟机  →  拷贝数据到虚拟机 → 从虚拟机上传到阿里云OSS

KVM复制文件到主机_linux

二、实现步骤

1.配置环境

创建飞书机器人(请看我之前的飞书相关文章)

地址:每天禅道超时任务、超时未开始任务发送飞书提醒_默^默的博客-CSDN博客

安装cp 命令显示拷贝进度条

地址:cp命令显示进度条_为Linux的cp和mv命令添加进度条_yi美小能手的博客-CSDN博客

服务器挂载阿里云OSS存储到服务器(我是挂载到虚拟机)

 

Ansible 跟虚拟机之间进行认证

命令:ssh-keygen  //生成秘钥   一直回车就行

KVM复制文件到主机_KVM复制文件到主机_02

将秘钥拷贝到被管理服务器上

命令:ssh-copy-id  -i ~/.ssh/id_rsa.pub -p 22 user@被管理的服务器IP

编辑配置文件:vim /etc/ansible/hosts

KVM复制文件到主机_运维_03

 验证通信是否完成

KVM复制文件到主机_python_04

编写yml文件:vim tviewer.yml

---
- hosts: server
  remote_user: root
  tasks:
   - name: Project
     shell: /bin/bash /root/script/mount.sh  # 虚拟机中脚本存放路径自行修改
     register: result
   - debug: var=result

2.编写物理机脚本

注意所有脚本及文件在同一目录下,本次实验是固有环境,其他环境使用需要改动。

本次实验脚本路径:/root/script

KVM复制文件到主机_linux_05

KVM复制文件到主机_linux_06

 

首先创一个初始状态文件

echo "当前设备状态: 1" > ./status.txt

编写监控USB端口脚本

vim jk_usb.sh

代码如下(示例):

#!/bin/bash
# Monitor USB device

# 检测当前是否有USB设备接入
# 获取USB端口 idVendor,idProduct

while :
do
    idven=`awk -F '[,=]' '/New USB device found, idVendor/{print $3}' /var/log/messages | tail -1`
    idpro=`awk -F '[,=]' '/New USB device found, idVendor/{print $5}' /var/log/messages | tail -1`

    if [ -z $idven ];then
       echo "未检测到USB接口有U盘接入!"
    else
       echo "\"$idven$idpro\" USB接口有U盘接入!" 
       break
    fi
    sleep 20
done

编写传送USB设备文件脚本

vim monitor_usb.sh

代码如下(示例):

#!/bin/bash
# Monitor USB device

# 创建虚拟机需要的USB设备文件
if [ ! -f /opt/usb.xml ];then
   touch /opt/usb.xml
   echo -e "<hostdev mode='subsystem' type='usb' managed='yes'>\n\
        <source>\n\
               <vendor id='0x$idven'/>\n\
               <product id='0x$idpro'/>\n\
        </source>\n</hostdev>" >/opt/usb.xml
else
   echo "文件已存在!" >/dev/null
fi

# 获取USB端口 idVendor,idProduct
while :
do
    sh /root/script/jk_usb.sh
    idven=`awk -F '[,=]' '/New USB device found, idVendor/{print $3}' /var/log/messages | tail -1`
    idpro=`awk -F '[,=]' '/New USB device found, idVendor/{print $5}' /var/log/messages | tail -1`
    oldid=`awk -F '[=/x'\'']' '/vendor/{print $4}' /opt/usb.xml`
    oldip=`awk -F '[=/x'\'']' '/product/{print $4}' /opt/usb.xml`

    # 检查当前设备使用状态
    cat status.txt | grep "0"

    if [ $? -eq 0 ];then
       echo "当前 \"$oldid$oldip\" 设备正在使用中。。。"
    else
       echo "更换设备请稍后。。。"
       # 替换上一次idVendor,idProduct
       cp -r /opt/usb.xml /opt/bak_usb.xml
       sed -i '3 s/'0x$oldid'/'\0x$idven'/g' /opt/usb.xml
       sed -i '4 s/'0x$oldip'/'\0x$idpro'/g' /opt/usb.xml
       # 清空系统日志消息
       cat /dev/null >/var/log/messages
       # 删除上次发送的yml文件
       virsh detach-device dianxin_video /opt/usb.xml >/dev/null
       # 发送到虚拟机设备文件
       virsh attach-device dianxin_video /opt/usb.xml
       #远程登录虚拟机执行脚本
       ansible-playbook /root/script/tviewer.yml
fi
sleep 20

3.编写Python发送脚本

本地日志提示python脚本

vim feishugerenlocal_cpg.py

代码如下(示例):

#!/usr/bin/python3
# encoding: utf-8
import json
import requests
import sys

messages = sys.argv[1]
content = "视频拷贝到本地日志: \n %s" % messages

def gettenant_access_token():
    # 获取应用token
    tokenurl = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal/"
    headers = {"Content-Type": "application/json"}
    data = {
        "app_id": "cli_a1960ffb******", # 飞书应用的ID 
        "app_secret": "121cF*****" # 飞书应用的Secret
    }
    request = requests.post(url=tokenurl, headers=headers, json=data)
    response = json.loads(request.content)['tenant_access_token']
    return response


def getuserid(tenant_access_token):
    # 获取User_ID
    mobiles = "18888666664" #个人飞书登录的手机号
    userurl = "https://open.feishu.cn/open-apis/user/v1/batch_get_id?mobiles=%s" % mobiles
    headers = {"Authorization": "Bearer %s" % tenant_access_token}
    request = requests.get(url=userurl, headers=headers)
    response = json.loads(request.content)['data']['mobile_users'][mobiles][0]['user_id']
    print(json.loads(request.content))
    return response


def sendmes(user_id, tenant_access_token):
    sendurl = "https://open.feishu.cn/open-apis/message/v4/send/"
    headers = {"Authorization": "Bearer %s" % tenant_access_token, "Content-Type": "application/json"}

    # 给个人发送消息
    data = {"user_id": user_id,
            "msg_type": "text",
            "content": {
                "text": "<at user_id=\"%s\">test</at>\n \n %s" % (user_id, content)
            }
                }
    requests.post(url=sendurl, headers=headers, json=data)


tenant_access_token = gettenant_access_token()
user_id = getuserid(tenant_access_token)
sendmes(user_id, tenant_access_token)

拷贝到OSS存储的日志脚本

vim feishugerenoss_cpg.py

代码如下(示例):

#!/usr/bin/python3
# encoding: utf-8
import json
import requests
import sys

messages = sys.argv[1]
content = "视频拷贝到OSS日志: \n %s" % messages

def gettenant_access_token():
    # 获取应用token
    tokenurl = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal/"
    headers = {"Content-Type": "application/json"}
    data = {
        "app_id": "cli_a1960ffb******", # 飞书应用的ID 
        "app_secret": "111CF*****" # 飞书应用的Secret
    }
    request = requests.post(url=tokenurl, headers=headers, json=data)
    response = json.loads(request.content)['tenant_access_token']
    return response


def getuserid(tenant_access_token):
    # 获取User_ID
    mobiles = "18888666664" #个人飞书登录的手机号
    userurl = "https://open.feishu.cn/open-apis/user/v1/batch_get_id?mobiles=%s" % mobiles
    headers = {"Authorization": "Bearer %s" % tenant_access_token}
    request = requests.get(url=userurl, headers=headers)
    response = json.loads(request.content)['data']['mobile_users'][mobiles][0]['user_id']
    print(json.loads(request.content))
    return response


def sendmes(user_id, tenant_access_token):
    sendurl = "https://open.feishu.cn/open-apis/message/v4/send/"
    headers = {"Authorization": "Bearer %s" % tenant_access_token, "Content-Type": "application/json"}

    # 给个人发送消息
    data = {"user_id": user_id,
            "msg_type": "text",
            "content": {
                "text": "<at user_id=\"%s\">test</at>\n \n %s" % (user_id, content)
            }
                }
    requests.post(url=sendurl, headers=headers, json=data)


tenant_access_token = gettenant_access_token()
user_id = getuserid(tenant_access_token)
sendmes(user_id, tenant_access_token)

4.编写虚拟机脚本

vim mount.sh

代码如下(示例):

#!/bin/bash
# Mount the USB flash drive and copy it to the specified directory
# Send flying books when finished

HOST="192.168.168.11" #物理机IP
USER="root"
PASSWARD="Yct3****"
FILE="/root/script/status.txt" #状态文件路径放在物理机脚本同级目录
TOFILE="/root/script/" #物理机脚本目录

#获取挂载盘
diskid=`lsblk | awk '{print $1,$4}' | grep -v ^[A-Z] | grep -E 'G|T' | tail -1 | awk -F '[─ ]' '{print $2}'`
mdir="/dianxin_video"

#先取消一下挂载(不管之前有没有挂载)
umount /video

#挂载U盘
mount /dev/$diskid $mdir
if [ $? = 0 ];then
    echo "挂载成功!" > /root/sh.log
else
    echo "请检查挂载!" > /root/sh.log
    exit 1
fi

#创建状态文件传回物理机
echo "当前设备状态: 0" > /root/script/status.txt
expect -c "
    spawn scp $FILE  $USER@$HOST:$TOFILE
     expect {
        \"*assword\" {set timeout 300; send \"$PASSWARD\r\"; exp_continue;}
        \"yes/no\" {send \"yes\r\";}
    }
expect eof"

#查询U盘SN,创建拷贝目录 (通过SN码区别不同的U盘)
DISKID=`echo  $diskid  | awk  -F  ""  '
{
   for (i=1;i<=NF;i++) 
   {  
     if  ($i ~ /[[:lower:]]/)         
     {
       str=$i
       str1=(str1 str)
     }  
   } 
   print str1
}'`
USBSN=`lsblk -n --nodeps -o name,serial /dev/$DISKID | awk '{print $2}' `
DIR=`date +%Y%m%d`

if [ ! -d /root/video/$USBSN/$DIR ];then
   mkdir -p  /root/video/$USBSN/$DIR
else
   echo "目录已存在!" > /root/sh.log
fi

#拷贝U盘中的文件到本地(指定U盘要拷贝的数据路径,这里是所有数据)
nohup cpg -rg /video/* /root/video/$USBSN/$DIR/ > /root/cp.log 2>&1 &

sleep 1
#发送copy到本地日志
str1=`cat /root/cp.log | tail -1`
string="copy到本地时发生错误请检查!"
grep -E "error|warning|failed" /root/cp.log

#检查到错误信息停止执行发送消息
if [ $? -eq 0  ];then
   python3 /root/script/feishugerenlocal_cpg.py "$string"
   exit 1
else
   python3 /root/script/feishugerenlocal_cpg.py "${str1:5}"
fi
echo "${str1:5}"

#创建oss目录
if [ ! -d /ossfs/视频/$USBSN ];then
    mkdir /ossfs/视频/$USBSN
else
   echo "目录已存在!" > /root/sh.log
fi

#拷贝本地的文件到阿里OSS存储
nohup cpg -rg /root/video/$USBSN/$DIR /ossfs/视频/$USBSN > /root/cp.log 2>&1 &

sleep 1

#发送copy到OSS日志
str2=`cat /root/cp.log | tail -1`
string2="copy到阿里OSS存储时发生错误请检查!"
grep -E "error|warning|failed" /root/cp.log

#检查到错误信息停止执行发送消息
if [ $? -eq 0  ];then
   python3 /root/script/feishugerenoss_cpg.py "$string2"
   exit 1
else
   python3 /root/script/feishugerenoss_cpg.py "${str2:5}"
fi

#完成后返回状态文件传回物理机作为下次查询
echo "当前设备状态: 1" > /root/script/status.txt
expect -c "
    spawn scp $FILE  $USER@$HOST:$TOFILE
     expect {
        \"*assword\" {set timeout 300; send \"$PASSWARD\r\"; exp_continue;}
        \"yes/no\" {send \"yes\r\";}
    }
EPpect eof"

5.测试并验证结果

在物理机上执行

sh monitor_usb.sh

KVM复制文件到主机_经验分享_07

 

KVM复制文件到主机_经验分享_08

拷贝到虚拟机验证结果

 

KVM复制文件到主机_经验分享_09

拷贝到阿里云OSS验证结果

KVM复制文件到主机_python_10

 发送消息至飞书验证结果

KVM复制文件到主机_KVM复制文件到主机_11

6.创建自动执行拷贝

启动命令在物理机执行

nohup sh monitor_usb.sh > cp.log 2>&1 &