用Shell脚本给串口GSM设备发送短信（PDU方式）---- 全网最全
需求一枚苦逼的运维工程师，需要对维护的设备、网络等实时监控，针对异常及时发送告警告知。分析有互联网情况下，可以实现钉钉告警、邮件告警、微信告警、短信告警；无互联网的情况下，只能短信告警；这里以发送短信为主（环境受限）；环境一台Linux主机，可以是真机，也可以是虚拟机；一个GSM模块（USB 转 串口）（这种模块不贵，几十块钱）一张有效的SIM卡（具体哪家运营商请根据自己的模块决定）2024-10-25T01:48:09.png资料关于GSM模块使用，可以参考商家给的文档，也可以参考下列内容：4G模块AT指令发送中英文短信详细流程 、GPRS用AT命令发送中文短信为什么要使用 USB to 串口 设备，主要考虑安全问题；代码配置文件 config.conf## 串口设备配置 ser_name=\'/dev/ttyUSB0\' ser_port=\'115200\' ## 日志文件配置 ## gsm 实时日志 gsm_log=\'./gsm.log\' ## 启动日志以及send日志 all_log=\'./all.log\'封装类脚本 func.sh## 打印日志 function p_log(){ echo -e \"$(date \'+%F %T\')\\t${1}\" | tee -a ${all_log} } ## 手机号码处理 function num2un(){ ph_num=\"86${1}F\" t_phnum_arr=($(echo -n \"${ph_num}\" | sed \'s/.\\{2\\}/&:/g\' | sed \'s/:$//g\' | tr \':\' \' \')) t_phnum=\'\' for i in ${t_phnum[*]} do a=($(echo -n \"${t_phnum_arr}\" | sed \'s/.\\{1\\}/&:/g\' | sed \'s/:$//g\' | tr \':\' \' \')) t_phnum+=\"${a[1]}${a[0]}\" done echo -n \"${t_phnum}\" } ## 字符串处理( 如果是中文，需要转Unicode ） function msg2un(){ t_str=\"${1}\" t_unicode=\'\' for (( i = 0 ; i < ${#t_str} ; i++ )) do a=\"${t_str:$i:1}\" if [ ${a} == \'\\\' ];then i=$(( $i + 1 )) b=\"${a}${t_str:$i:1}\" t_unicode+=$(printf \'%04x\' \"$(printf \\\"${b}\\\")\") else t_unicode+=$(printf \'%04x\' \"\'${a}\'\") fi done echo -n \"${t_unicode}\" | tr \'a-z\' \'A-Z\' } ## 发送短信 function sendmsg(){ ## avg 1 接收短信的号码 ## avg 2 需要发送的 信息字符串 t_num=$(num2un \"${1}\") t_num=\"0011000D91${t_num}00800\" t_str=$(msg2unicode \"${2}\") t_str_len=$(( ${#t_str} / 2 )) t_str_hex=$(echo -n \"${t_str_len}\" | awk \'{printf(\"%0x\\n\",$0)}\' | tr \'a-z\' \'A-Z\') if [ ${#t_str_hex} -eq 1 ];then t_str_hex=\"0${t_str_hex}\" fi t_str=\"${t_num}${t_str_hex}${t_str}\" at_cmgs=$(( ${#t_str} / 2 )) ## 开始发送 if [ ${at_cmgs} -lt 140 ];then echo -e \"AT+CMGF=0\\r\\n\" | minicom -b ${ser_port} -D ${ser_name} && \\ echo -e \"AT+CSCS=\\\"UCS2\\\"\" | minicom -b ${ser_port} -D ${ser_name} && \\ echo -e \"AT+CMGS=${at_cmgs}\\r\\n\" | minicom -b ${ser_port} -D ${ser_name} && \\ echo -e \"${t_str}\" | minicom -b ${ser_port} -D ${ser_name} && \\ echo -e \"\\032\" | minicom -b ${ser_port} -D ${ser_name} ## 日志打印 sleep 4 if tail -n 2 \"${gsm_log}\" | grep -qw \'OK\' ;then p_log \"Msg \'${2}\' send to $1 sucessfull.\" else p_log \"Msg \'${2}\' send to $1 failed.\" fi else p_log \"Msg \'${2}\' len too long,stop send it.\" && exit 1 fi }主脚本（调用脚本）main.sh#!/bin/bash cd $(dirname $0) . ./config.conf . ./func.sh ## 参数1 接收信息的手机号码 ## 参数2 需要发送的内容 if [ $# -ne 2 ];then p_log \"参数不够或者超限.\" && exit 1 fi if [ ${#1} -ne 11 ];then p_log \"手机号码长度不正确.\" && exit 1 fi ## 判断GSM设备情况 if [[ -n ${ser_name} && -n ${ser_port} && -c ${ser_name} ]];then sendmsg \"${1}\" \"${2}\" else p_log \"GSM信息异常，请检查配置文件 config.conf.\" fi启动脚本 start.sh#!/bin/bash cd $(dirname $0) if [ ! -s \"./config.conf\" ];then echo -e \"$(date \'+%F %T\')\\t配置文件 config.conf 不存在或者为空，停止初始化\" && exit 1 fi if [ ! -s \"./func.sh\" ];then echo -e \"$(date \'+%F %T\')\\t类文件 func.sh 不存在或者为空，停止初始化\" && exit 1 fi . ./config.conf . ./func.sh ## 串口文件判断 if [ ! -c \"${ser_name}\" ];then p_log \"GSM设备 ${ser_name} 无效或者不存在，停止初始化\" && exit 1 fi ## 初始化串口设备 if ! screen -v ;then p_log \"缺少screen工具，请先安装\" && exit 1 fi if ! screen -list | grep -q \"gsmlog\" ;then screen -dmS gsmlog screen -x -S gsmlog -p 0 -X stuff \"cat ${ser_name} | tee -a ${gsmlog}\\n\" && p_log \"GSM串口设备初始化成功.\" else p_log \"GSM串口设备已初始化.\"发送信息测试