diff --git a/README.md b/README.md index 4887bd4..10686a7 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,8 @@ upc_resent/ │ ├── crond_tcp.py.tpl # TCP保活检查模板 │ ├── crond_udp.py.tpl # UDP保活检查模板 │ ├── sender_tcp.py.tpl # TCP发送模块模板 -│ └── sender_udp.py.tpl # UDP发送模块模板 +│ ├── sender_udp.py.tpl # UDP发送模块模板 +│ └── control.sh.tpl # 控制脚本模板 ├── scripts/ │ └── generate.py # 代码生成器 ├── bin/ # 生成的监听服务文件(自动生成) @@ -23,7 +24,7 @@ upc_resent/ │ └── {device_id}.py # 各设备监听服务 ├── crond/ # 生成的保活检查文件(自动生成) ├── log/ # 日志目录 -├── start.sh # 启动脚本(自动生成) +├── control.sh # 服务控制脚本(自动生成) ├── crontab.txt # 定时任务配置(自动生成) └── cutlog.sh # 日志清理脚本 ``` @@ -77,8 +78,17 @@ python3 scripts/generate.py ### 3. 部署与启动 ```bash +# 查看服务状态 +./control.sh status + # 启动所有服务 -./start.sh +./control.sh start + +# 停止所有服务 +./control.sh stop + +# 重启所有服务 +./control.sh restart # 配置定时任务(保活) crontab crontab.txt @@ -273,6 +283,26 @@ python3 scripts/generate.py python3 scripts/generate.py --help ``` +## 服务控制脚本 + +`control.sh` 提供以下命令: + +| 命令 | 说明 | +|-----|------| +| `start` | 启动所有服务 | +| `stop` | 停止所有服务 | +| `restart` | 重启所有服务 | +| `status` | 查看服务运行状态 | + +示例: + +```bash +./control.sh status +./control.sh start +./control.sh stop +./control.sh restart +``` + ## 日志文件 | 文件 | 说明 | @@ -284,7 +314,7 @@ python3 scripts/generate.py --help ## 注意事项 -1. **不要直接修改** `bin/` 和 `crond/` 下的文件,这些文件是自动生成的,重新生成时会覆盖。 +1. **不要直接修改** `bin/`、`crond/` 和 `control.sh`,这些文件是自动生成的,重新生成时会覆盖。 2. **修改配置后必须重新运行** `python3 scripts/generate.py` 才能生效。 @@ -293,3 +323,5 @@ python3 scripts/generate.py --help 4. UDP 是无连接协议,设备可能不会返回响应,这是正常现象。 5. 部署到生产环境前,请将 `base_dir` 修改为实际的部署路径(如 `/opt/upc_resent`)。 + +6. 控制脚本使用 `pgrep` 来查找进程,确保系统中没有同名脚本冲突。 diff --git a/bin/192.168.8.125.py b/bin/192.168.8.125.py deleted file mode 100644 index 9419b4e..0000000 --- a/bin/192.168.8.125.py +++ /dev/null @@ -1,126 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- - -import socket -import os -import time -import logging -import sys -# reload(sys) 和 sys.setdefaultencoding('utf-8') 在 Python 3 中不再需要 - -if __name__ == '__main__': - - #======修改以下参数====== - TmsServerIp='192.168.8.9' #TMS服务器IP,用于绑定服务,等待外部指令 - TmsPor='10129' #TMS服务器端口,用于绑定服务,等待外部指令 - upc_dev_ip="192.168.8.125" #自动化控制设备IP - upc_dev_port="502" #自动化控制设备端口 - # 注意:Senderfile 指向的 sender.py 脚本也需要是 Python 3 版本! - Senderfile='/opt/upc_resent/bin/sender.py' #发送程序位置 - Logfile='/opt/upc_resent/log/192.168.8.125.log' #日志文件位置 - pythonpath="/usr/bin/python3" # Python 3 执行文件的位置,可在操作系统中使用which python3命令获取 - #======================== - - BUFSIZE = 1024 - - # 配置日志,只执行一次 - logging.basicConfig(filename=Logfile,filemode="a", level=logging.DEBUG) - ISOTIMEFORMAT='%Y-%m-%d %X' - - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - try: - sock.bind((TmsServerIp, int(TmsPor))) #启动TMS本地服务,等待外部设备发送指令 - sock.listen(500) - except OSError as e: # 在 Python 3 中使用 OSError 替代 socket.error - logstr="!!!!!ERROR!!!!!"+time.strftime( ISOTIMEFORMAT, time.localtime( time.time() ) )+" 无法绑定端口 %s:%s - %s" % (TmsServerIp, TmsPor, e) - logging.error(logstr) - print(logstr) # Python 3 print 函数 - sys.exit(1) # 绑定失败则退出 - - logging.info("服务启动,监听 %s:%s" % (TmsServerIp, TmsPor)) - - while True: - connection,address = sock.accept() - try: - connection.settimeout(5) #GDC系统长连接 - # 接收到的数据是 bytes,需要解码成 str 进行比较 - buf_bytes = connection.recv(BUFSIZE) - buf = buf_bytes.decode('utf-8').strip() # 解码成 str 并移除空白符 - - operation = "nodata" # 默认值,如果没有匹配的命令 - - datetime_str=time.strftime( ISOTIMEFORMAT, time.localtime( time.time() ) ) - logstr="==="+datetime_str+"收到客户端"+ address[0]+":"+str(address[1])+"发送的指令: '" +str(buf)+"'" - logging.info(logstr) - - # 根据接收到的外部命令,映射到单个内部操作指令 - if buf == 'open': - operation = 'openall4' - elif buf == 'close': - operation = 'closeall4' - elif buf == 'open1': - operation = 'open1' - elif buf == 'close1': - operation = 'close1' - elif buf == 'open2': - operation = 'open2' - elif buf == 'close2': - operation = 'close2' - elif buf == 'open3': - operation = 'open3' - elif buf == 'close3': - operation = 'close3' - elif buf == 'open4': - operation = 'open4' - elif buf == 'close4': - operation = 'close4' - elif buf == 'open5': # 新增 5-8 路的命令映射 - operation = 'open5' - elif buf == 'close5': - operation = 'close5' - elif buf == 'open6': - operation = 'open6' - elif buf == 'close6': - operation = 'close6' - elif buf == 'open7': - operation = 'open7' - elif buf == 'close7': - operation = 'close7' - elif buf == 'open8': - operation = 'open8' - elif buf == 'close8': - operation = 'close8' - elif buf == 'guanggao-guan': # 外部命令 'guanggao-guan' 映射到 'closeall4' (全关) - operation = 'closeall4' - # else: operation 保持为 "nodata" - - if operation == "nodata": - logstr="==="+datetime_str+" 未知指令: '" +str(buf)+"'" - logging.warning(logstr) - print(logstr) # Python 3 print 函数 - # 给客户端一个反馈,需要编码成 bytes - connection.send(('Unknown command: %s' % buf).encode('utf-8')) - else: - logstr="==="+datetime_str+" 映射到内部指令: '" +str(operation)+"'" - logging.info(logstr) - # 直接执行一次外部脚本 - os_command=str(pythonpath)+" " +Senderfile+ " " + str(upc_dev_ip)+" "+str(upc_dev_port)+" "+str(operation)+" "+str(Logfile) - logging.info("执行外部命令: %s" % os_command) - os.system(os_command) # 执行发送指令的脚本 - # 成功处理后给客户端反馈,需要编码成 bytes - connection.send(('Command %s processed as %s' % (buf, operation)).encode('utf-8')) - except socket.timeout: - datetime_str=time.strftime( ISOTIMEFORMAT, time.localtime( time.time() ) ) - logstr="==="+datetime_str+" 客户端连接超时: "+ address[0]+":"+str(address[1])+"===" - logging.warning(logstr) - print('time out') # Python 3 print 函数 - except Exception as e: # 捕获其他可能的异常 - datetime_str=time.strftime( ISOTIMEFORMAT, time.localtime( time.time() ) ) - logstr="==="+datetime_str+" 处理客户端 "+ address[0]+":"+str(address[1])+" 请求时发生错误: "+str(e)+"===" - logging.error(logstr, exc_info=True) # 记录异常详情 - print("Error processing request:", e) # Python 3 print 函数 - # 给客户端一个错误反馈,需要编码成 bytes - connection.send(('Error processing command: %s' % str(e)).encode('utf-8')) - finally: - connection.close() # 确保每次连接都被关闭 - diff --git a/bin/192.168.8.73.py b/bin/192.168.8.73.py deleted file mode 100644 index 0eb29d0..0000000 --- a/bin/192.168.8.73.py +++ /dev/null @@ -1,126 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- - -import socket -import os -import time -import logging -import sys -# reload(sys) 和 sys.setdefaultencoding('utf-8') 在 Python 3 中不再需要 - -if __name__ == '__main__': - - #======修改以下参数====== - TmsServerIp='192.168.8.9' #TMS服务器IP,用于绑定服务,等待外部指令 - TmsPor='10079' #TMS服务器端口,用于绑定服务,等待外部指令 - upc_dev_ip="192.168.8.73" #自动化控制设备IP - upc_dev_port="502" #自动化控制设备端口 - # 注意:Senderfile 指向的 sender.py 脚本也需要是 Python 3 版本! - Senderfile='/opt/upc_resent/bin/sender.py' #发送程序位置 - Logfile='/opt/upc_resent/log/192.168.8.73.log' #日志文件位置 - pythonpath="/usr/bin/python3" # Python 3 执行文件的位置,可在操作系统中使用which python3命令获取 - #======================== - - BUFSIZE = 1024 - - # 配置日志,只执行一次 - logging.basicConfig(filename=Logfile,filemode="a", level=logging.DEBUG) - ISOTIMEFORMAT='%Y-%m-%d %X' - - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - try: - sock.bind((TmsServerIp, int(TmsPor))) #启动TMS本地服务,等待外部设备发送指令 - sock.listen(500) - except OSError as e: # 在 Python 3 中使用 OSError 替代 socket.error - logstr="!!!!!ERROR!!!!!"+time.strftime( ISOTIMEFORMAT, time.localtime( time.time() ) )+" 无法绑定端口 %s:%s - %s" % (TmsServerIp, TmsPor, e) - logging.error(logstr) - print(logstr) # Python 3 print 函数 - sys.exit(1) # 绑定失败则退出 - - logging.info("服务启动,监听 %s:%s" % (TmsServerIp, TmsPor)) - - while True: - connection,address = sock.accept() - try: - connection.settimeout(5) #GDC系统长连接 - # 接收到的数据是 bytes,需要解码成 str 进行比较 - buf_bytes = connection.recv(BUFSIZE) - buf = buf_bytes.decode('utf-8').strip() # 解码成 str 并移除空白符 - - operation = "nodata" # 默认值,如果没有匹配的命令 - - datetime_str=time.strftime( ISOTIMEFORMAT, time.localtime( time.time() ) ) - logstr="==="+datetime_str+"收到客户端"+ address[0]+":"+str(address[1])+"发送的指令: '" +str(buf)+"'" - logging.info(logstr) - - # 根据接收到的外部命令,映射到单个内部操作指令 - if buf == 'open': - operation = 'openall4' - elif buf == 'close': - operation = 'closeall4' - elif buf == 'open1': - operation = 'open1' - elif buf == 'close1': - operation = 'close1' - elif buf == 'open2': - operation = 'open2' - elif buf == 'close2': - operation = 'close2' - elif buf == 'open3': - operation = 'open3' - elif buf == 'close3': - operation = 'close3' - elif buf == 'open4': - operation = 'open4' - elif buf == 'close4': - operation = 'close4' - elif buf == 'open5': # 新增 5-8 路的命令映射 - operation = 'open5' - elif buf == 'close5': - operation = 'close5' - elif buf == 'open6': - operation = 'open6' - elif buf == 'close6': - operation = 'close6' - elif buf == 'open7': - operation = 'open7' - elif buf == 'close7': - operation = 'close7' - elif buf == 'open8': - operation = 'open8' - elif buf == 'close8': - operation = 'close8' - elif buf == 'guanggao-guan': # 外部命令 'guanggao-guan' 映射到 'closeall4' (全关) - operation = 'closeall4' - # else: operation 保持为 "nodata" - - if operation == "nodata": - logstr="==="+datetime_str+" 未知指令: '" +str(buf)+"'" - logging.warning(logstr) - print(logstr) # Python 3 print 函数 - # 给客户端一个反馈,需要编码成 bytes - connection.send(('Unknown command: %s' % buf).encode('utf-8')) - else: - logstr="==="+datetime_str+" 映射到内部指令: '" +str(operation)+"'" - logging.info(logstr) - # 直接执行一次外部脚本 - os_command=str(pythonpath)+" " +Senderfile+ " " + str(upc_dev_ip)+" "+str(upc_dev_port)+" "+str(operation)+" "+str(Logfile) - logging.info("执行外部命令: %s" % os_command) - os.system(os_command) # 执行发送指令的脚本 - # 成功处理后给客户端反馈,需要编码成 bytes - connection.send(('Command %s processed as %s' % (buf, operation)).encode('utf-8')) - except socket.timeout: - datetime_str=time.strftime( ISOTIMEFORMAT, time.localtime( time.time() ) ) - logstr="==="+datetime_str+" 客户端连接超时: "+ address[0]+":"+str(address[1])+"===" - logging.warning(logstr) - print('time out') # Python 3 print 函数 - except Exception as e: # 捕获其他可能的异常 - datetime_str=time.strftime( ISOTIMEFORMAT, time.localtime( time.time() ) ) - logstr="==="+datetime_str+" 处理客户端 "+ address[0]+":"+str(address[1])+" 请求时发生错误: "+str(e)+"===" - logging.error(logstr, exc_info=True) # 记录异常详情 - print("Error processing request:", e) # Python 3 print 函数 - # 给客户端一个错误反馈,需要编码成 bytes - connection.send(('Error processing command: %s' % str(e)).encode('utf-8')) - finally: - connection.close() # 确保每次连接都被关闭 - diff --git a/bin/dev1.py b/bin/dev1.py deleted file mode 100755 index b4c2a55..0000000 --- a/bin/dev1.py +++ /dev/null @@ -1,124 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- -# Auto-generated from template. DO NOT EDIT DIRECTLY! -# Device: 设备73-TCP (dev1) - -import socket -import os -import time -import logging -import sys - -# ====== 配置参数(从配置文件读取)====== -TMS_SERVER_IP = '192.168.8.9' -TMS_PORT = 10079 -UPC_DEV_IP = '192.168.8.73' -UPC_DEV_PORT = '502' -SENDER_FILE = '/home/smart/pythonPJ/upc_resent/bin/sender_tcp.py' -LOG_FILE = '/home/smart/pythonPJ/upc_resent/log/dev1.log' -PYTHON_PATH = '/usr/bin/python3' -DEVICE_ID = 'dev1' -# ========================= - -BUFSIZE = 1024 - -# 配置日志 -logging.basicConfig(filename=LOG_FILE, filemode="a", level=logging.DEBUG) -ISOTIMEFORMAT = '%Y-%m-%d %X' - -# 命令映射表 -COMMAND_MAPPINGS = { - "open": "openall4", - "close": "closeall4", - "guanggao-guan": "closeall4", - "open1": "open1", - "close1": "close1", - "open2": "open2", - "close2": "close2", - "open3": "open3", - "close3": "close3", - "open4": "open4", - "close4": "close4", - "open5": "open5", - "close5": "close5", - "open6": "open6", - "close6": "close6", - "open7": "open7", - "close7": "close7", - "open8": "open8", - "close8": "close8", - } - - -def process_command(buf): - """处理接收到的命令,返回对应的操作指令""" - buf = buf.strip() - if buf in COMMAND_MAPPINGS: - return COMMAND_MAPPINGS[buf] - return "nodata" - - -def main(): - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - try: - sock.bind((TMS_SERVER_IP, int(TMS_PORT))) - sock.listen(500) - except OSError as e: - logstr = "!!!!!ERROR!!!!!" + time.strftime(ISOTIMEFORMAT, time.localtime(time.time())) + \ - " 无法绑定端口 %s:%s - %s" % (TMS_SERVER_IP, TMS_PORT, e) - logging.error(logstr) - print(logstr) - sys.exit(1) - - logging.info("服务启动,监听 %s:%s" % (TMS_SERVER_IP, TMS_PORT)) - print(f"[{DEVICE_ID}] 服务启动,监听 {TMS_SERVER_IP}:{TMS_PORT}") - - while True: - connection, address = sock.accept() - try: - connection.settimeout(5) - buf_bytes = connection.recv(BUFSIZE) - buf = buf_bytes.decode('utf-8').strip() - - datetime_str = time.strftime(ISOTIMEFORMAT, time.localtime(time.time())) - logstr = "===" + datetime_str + " 收到客户端 " + address[0] + ":" + str(address[1]) + \ - " 发送的指令: '" + str(buf) + "'" - logging.info(logstr) - print(logstr) - - operation = process_command(buf) - - if operation == "nodata": - logstr = "===" + datetime_str + " 未知指令: '" + str(buf) + "'" - logging.warning(logstr) - print(logstr) - connection.send(('Unknown command: %s' % buf).encode('utf-8')) - else: - logstr = "===" + datetime_str + " 映射到内部指令: '" + str(operation) + "'" - logging.info(logstr) - print(logstr) - - os_command = str(PYTHON_PATH) + " " + SENDER_FILE + " " + \ - str(UPC_DEV_IP) + " " + str(UPC_DEV_PORT) + " " + \ - str(operation) + " " + str(LOG_FILE) - logging.info("执行外部命令: %s" % os_command) - os.system(os_command) - connection.send(('Command %s processed as %s' % (buf, operation)).encode('utf-8')) - except socket.timeout: - datetime_str = time.strftime(ISOTIMEFORMAT, time.localtime(time.time())) - logstr = "===" + datetime_str + " 客户端连接超时: " + address[0] + ":" + str(address[1]) + "===" - logging.warning(logstr) - print('time out') - except Exception as e: - datetime_str = time.strftime(ISOTIMEFORMAT, time.localtime(time.time())) - logstr = "===" + datetime_str + " 处理客户端 " + address[0] + ":" + str(address[1]) + \ - " 请求时发生错误: " + str(e) + "===" - logging.error(logstr, exc_info=True) - print("Error processing request:", e) - connection.send(('Error processing command: %s' % str(e)).encode('utf-8')) - finally: - connection.close() - - -if __name__ == '__main__': - main() diff --git a/bin/dev2.py b/bin/dev2.py deleted file mode 100755 index c23c488..0000000 --- a/bin/dev2.py +++ /dev/null @@ -1,124 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- -# Auto-generated from template. DO NOT EDIT DIRECTLY! -# Device: 设备125-TCP (dev2) - -import socket -import os -import time -import logging -import sys - -# ====== 配置参数(从配置文件读取)====== -TMS_SERVER_IP = '192.168.8.9' -TMS_PORT = 10129 -UPC_DEV_IP = '192.168.8.125' -UPC_DEV_PORT = '502' -SENDER_FILE = '/home/smart/pythonPJ/upc_resent/bin/sender_tcp.py' -LOG_FILE = '/home/smart/pythonPJ/upc_resent/log/dev2.log' -PYTHON_PATH = '/usr/bin/python3' -DEVICE_ID = 'dev2' -# ========================= - -BUFSIZE = 1024 - -# 配置日志 -logging.basicConfig(filename=LOG_FILE, filemode="a", level=logging.DEBUG) -ISOTIMEFORMAT = '%Y-%m-%d %X' - -# 命令映射表 -COMMAND_MAPPINGS = { - "open": "openall4", - "close": "closeall4", - "guanggao-guan": "closeall4", - "open1": "open1", - "close1": "close1", - "open2": "open2", - "close2": "close2", - "open3": "open3", - "close3": "close3", - "open4": "open4", - "close4": "close4", - "open5": "open5", - "close5": "close5", - "open6": "open6", - "close6": "close6", - "open7": "open7", - "close7": "close7", - "open8": "open8", - "close8": "close8", - } - - -def process_command(buf): - """处理接收到的命令,返回对应的操作指令""" - buf = buf.strip() - if buf in COMMAND_MAPPINGS: - return COMMAND_MAPPINGS[buf] - return "nodata" - - -def main(): - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - try: - sock.bind((TMS_SERVER_IP, int(TMS_PORT))) - sock.listen(500) - except OSError as e: - logstr = "!!!!!ERROR!!!!!" + time.strftime(ISOTIMEFORMAT, time.localtime(time.time())) + \ - " 无法绑定端口 %s:%s - %s" % (TMS_SERVER_IP, TMS_PORT, e) - logging.error(logstr) - print(logstr) - sys.exit(1) - - logging.info("服务启动,监听 %s:%s" % (TMS_SERVER_IP, TMS_PORT)) - print(f"[{DEVICE_ID}] 服务启动,监听 {TMS_SERVER_IP}:{TMS_PORT}") - - while True: - connection, address = sock.accept() - try: - connection.settimeout(5) - buf_bytes = connection.recv(BUFSIZE) - buf = buf_bytes.decode('utf-8').strip() - - datetime_str = time.strftime(ISOTIMEFORMAT, time.localtime(time.time())) - logstr = "===" + datetime_str + " 收到客户端 " + address[0] + ":" + str(address[1]) + \ - " 发送的指令: '" + str(buf) + "'" - logging.info(logstr) - print(logstr) - - operation = process_command(buf) - - if operation == "nodata": - logstr = "===" + datetime_str + " 未知指令: '" + str(buf) + "'" - logging.warning(logstr) - print(logstr) - connection.send(('Unknown command: %s' % buf).encode('utf-8')) - else: - logstr = "===" + datetime_str + " 映射到内部指令: '" + str(operation) + "'" - logging.info(logstr) - print(logstr) - - os_command = str(PYTHON_PATH) + " " + SENDER_FILE + " " + \ - str(UPC_DEV_IP) + " " + str(UPC_DEV_PORT) + " " + \ - str(operation) + " " + str(LOG_FILE) - logging.info("执行外部命令: %s" % os_command) - os.system(os_command) - connection.send(('Command %s processed as %s' % (buf, operation)).encode('utf-8')) - except socket.timeout: - datetime_str = time.strftime(ISOTIMEFORMAT, time.localtime(time.time())) - logstr = "===" + datetime_str + " 客户端连接超时: " + address[0] + ":" + str(address[1]) + "===" - logging.warning(logstr) - print('time out') - except Exception as e: - datetime_str = time.strftime(ISOTIMEFORMAT, time.localtime(time.time())) - logstr = "===" + datetime_str + " 处理客户端 " + address[0] + ":" + str(address[1]) + \ - " 请求时发生错误: " + str(e) + "===" - logging.error(logstr, exc_info=True) - print("Error processing request:", e) - connection.send(('Error processing command: %s' % str(e)).encode('utf-8')) - finally: - connection.close() - - -if __name__ == '__main__': - main() diff --git a/bin/dev3.py b/bin/dev3.py deleted file mode 100755 index 0db408f..0000000 --- a/bin/dev3.py +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- -# Auto-generated from template. DO NOT EDIT DIRECTLY! -# Device: 设备UDP示例 (dev3) - UDP Protocol - -import socket -import os -import time -import logging -import sys - -# ====== 配置参数(从配置文件读取)====== -TMS_SERVER_IP = '192.168.8.9' -TMS_PORT = 10080 -UPC_DEV_IP = '192.168.8.200' -UPC_DEV_PORT = 502 -SENDER_FILE = '/home/smart/pythonPJ/upc_resent/bin/sender_udp.py' -LOG_FILE = '/home/smart/pythonPJ/upc_resent/log/dev3.log' -PYTHON_PATH = '/usr/bin/python3' -DEVICE_ID = 'dev3' -# ========================= - -BUFSIZE = 1024 - -# 配置日志 -logging.basicConfig(filename=LOG_FILE, filemode="a", level=logging.DEBUG) -ISOTIMEFORMAT = '%Y-%m-%d %X' - -# 命令映射表 -COMMAND_MAPPINGS = { - "open": "openall4", - "close": "closeall4", - "guanggao-guan": "closeall4", - "open1": "open1", - "close1": "close1", - "open2": "open2", - "close2": "close2", - "open3": "open3", - "close3": "close3", - "open4": "open4", - "close4": "close4", - "open5": "open5", - "close5": "close5", - "open6": "open6", - "close6": "close6", - "open7": "open7", - "close7": "close7", - "open8": "open8", - "close8": "close8", - } - - -def process_command(buf): - """处理接收到的命令,返回对应的操作指令""" - buf = buf.strip() - if buf in COMMAND_MAPPINGS: - return COMMAND_MAPPINGS[buf] - return "nodata" - - -def main(): - # 创建 UDP socket - sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - try: - sock.bind((TMS_SERVER_IP, int(TMS_PORT))) - except OSError as e: - logstr = "!!!!!ERROR!!!!!" + time.strftime(ISOTIMEFORMAT, time.localtime(time.time())) + \ - " 无法绑定UDP端口 %s:%s - %s" % (TMS_SERVER_IP, TMS_PORT, e) - logging.error(logstr) - print(logstr) - sys.exit(1) - - logging.info("UDP服务启动,监听 %s:%s" % (TMS_SERVER_IP, TMS_PORT)) - print(f"[{DEVICE_ID}] UDP服务启动,监听 {TMS_SERVER_IP}:{TMS_PORT}") - - while True: - try: - # UDP 使用 recvfrom 接收数据,同时获取客户端地址 - buf_bytes, client_addr = sock.recvfrom(BUFSIZE) - buf = buf_bytes.decode('utf-8').strip() - - datetime_str = time.strftime(ISOTIMEFORMAT, time.localtime(time.time())) - logstr = "===" + datetime_str + " 收到UDP客户端 " + client_addr[0] + ":" + str(client_addr[1]) + \ - " 发送的指令: '" + str(buf) + "'" - logging.info(logstr) - print(logstr) - - operation = process_command(buf) - - if operation == "nodata": - logstr = "===" + datetime_str + " 未知指令: '" + str(buf) + "'" - logging.warning(logstr) - print(logstr) - # 发送UDP响应 - sock.sendto(('Unknown command: %s' % buf).encode('utf-8'), client_addr) - else: - logstr = "===" + datetime_str + " 映射到内部指令: '" + str(operation) + "'" - logging.info(logstr) - print(logstr) - - # 执行发送指令的脚本 - os_command = str(PYTHON_PATH) + " " + SENDER_FILE + " " + \ - str(UPC_DEV_IP) + " " + str(UPC_DEV_PORT) + " " + \ - str(operation) + " " + str(LOG_FILE) - logging.info("执行外部命令: %s" % os_command) - os.system(os_command) - - # 发送UDP响应 - sock.sendto(('Command %s processed as %s' % (buf, operation)).encode('utf-8'), client_addr) - except Exception as e: - datetime_str = time.strftime(ISOTIMEFORMAT, time.localtime(time.time())) - logstr = "===" + datetime_str + " 处理UDP请求时发生错误: " + str(e) + "===" - logging.error(logstr, exc_info=True) - print("Error processing UDP request:", e) - - -if __name__ == '__main__': - main() diff --git a/bin/sender.py b/bin/sender.py deleted file mode 100755 index 7f8c673..0000000 --- a/bin/sender.py +++ /dev/null @@ -1,140 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- -# Auto-generated from template. DO NOT EDIT DIRECTLY! - -import sys -import socket -import time -import logging -import telnetlib - - -def tcp_command_send(upc_addr, upc_command, data): - """负责发送数据和接收一次响应""" - timeout = 2 - socket.setdefaulttimeout(timeout) - try: - client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - logging.debug(f"尝试连接到 {upc_addr[0]}:{upc_addr[1]}...") - client.connect(upc_addr) - logging.debug(f"成功连接到 {upc_addr[0]}:{upc_addr[1]}。") - - logging.info(f"正在发送命令 '{upc_command}' 到 {upc_addr}: {data!r} (原始字节)") - client.send(data) - logging.debug(f"数据发送完成。") - - recv_buffer_size = 1024 - response_bytes = b'' - try: - logging.debug(f"尝试从 {upc_addr} 接收响应数据...") - response_bytes = client.recv(recv_buffer_size) - if response_bytes: - logging.info(f"从 {upc_addr} 收到原始响应字节: {response_bytes!r}") - try: - response_str = response_bytes.decode('utf-8', errors='ignore') - logging.info(f"从 {upc_addr} 收到解码响应字符串: '{response_str}'") - except Exception as decode_e: - logging.warning(f"解码从 {upc_addr} 收到的响应时发生错误: {decode_e}") - else: - logging.info(f"从 {upc_addr} 未收到响应数据 (连接可能已关闭或设备未发送)。") - except socket.timeout: - logging.warning(f"从 {upc_addr} 接收响应超时。") - except OSError as recv_e: - logging.error(f"从 {upc_addr} 接收响应时发生网络错误: {recv_e}") - - client.close() - logging.debug(f"连接关闭。") - return True - except OSError as e: - logging.error(f"命令 '{upc_command}' 发送至 {upc_addr} 失败: {e}") - return False - - -# 指令定义表(从配置文件读取) -COMMAND_DEFINITIONS = { - "open1": "000100000008010F006400010001", - "close1": "000100000008010F006400010000", - "open2": "000100000008010F006500010001", - "close2": "000100000008010F006500010000", - "open3": "000100000008010F006600010001", - "close3": "000100000008010F006600010000", - "open4": "000100000008010F006700010001", - "close4": "000100000008010F006700010000", - "openall4": "000100000008010F00640004000F", - "closeall4": "000100000008010F006400040000", - "open5": "000100000008010F006800010001", - "close5": "000100000008010F006800010000", - "open6": "000100000008010F006900010001", - "close6": "000100000008010F006900010000", - "open7": "000100000008010F006A00010001", - "close7": "000100000008010F006A00010000", - "open8": "000100000008010F006B00010001", - "close8": "000100000008010F006B00010000", - "getstat": "fe010000000429C6", - "getstat01": "fe010100000429C6", -} - - -def upc_send_command(upc_addr, upc_command, log_file): - """将命令发送给终端设备""" - data = None - - # 查找指令定义 - if upc_command in COMMAND_DEFINITIONS: - hex_str = COMMAND_DEFINITIONS[upc_command] - data = bytes.fromhex(hex_str) - - if data is None: - datetime_str = time.strftime(ISOTIMEFORMAT, time.localtime(time.time())) - logstr = f"{datetime_str} 未知命令: {upc_command},没有对应的数据可发送。" - logging.warning(logstr) - print(logstr) - else: - i = 1 - while i <= 3: # 尝试发送3次 - if tcp_command_send(upc_addr, upc_command, data): - datetime_str = time.strftime(ISOTIMEFORMAT, time.localtime(time.time())) - logstr = f"{datetime_str} {upc_command}命令第{i}次发送成功" - logging.info(logstr) - return - else: - datetime_str = time.strftime(ISOTIMEFORMAT, time.localtime(time.time())) - logstr = f"{datetime_str} {upc_command}命令第{i}次发送失败,3秒后进行第{i+1}次尝试" - logging.warning(logstr) - time.sleep(3) - i = i + 1 - - datetime_str = time.strftime(ISOTIMEFORMAT, time.localtime(time.time())) - logstr = f"{datetime_str} {upc_command}命令在3次尝试后发送均失败!" - logging.error(logstr) - - -if __name__ == '__main__': - ISOTIMEFORMAT = '%Y-%m-%d %X' - - UPC_DEV_IP = sys.argv[1] - UPC_DEV_PORT = sys.argv[2] - upc_command = sys.argv[3] - LOG_FILE = sys.argv[4] - - logging.basicConfig(filename=LOG_FILE, filemode="a", level=logging.DEBUG) - UPC_ADDR = (UPC_DEV_IP, int(UPC_DEV_PORT)) - - # 验证端口是否能Telnet通 - try: - logging.debug(f"尝试通过 Telnet 检查端口 {UPC_ADDR[0]}:{UPC_ADDR[1]} 可访问性...") - tn = telnetlib.Telnet(UPC_DEV_IP, UPC_DEV_PORT) - tn.close() - logging.debug(f"端口 {UPC_ADDR[0]}:{UPC_ADDR[1]} Telnet 检查通过。") - except OSError as e: - datetime_str = time.strftime(ISOTIMEFORMAT, time.localtime(time.time())) - logstr = f"!!!!!ERROR!!!!!{datetime_str} {UPC_ADDR} 端口无法访问,请检查设备或网络连接: {e}!!!!!" - logging.error(logstr) - print(logstr) - except Exception as e: - datetime_str = time.strftime(ISOTIMEFORMAT, time.localtime(time.time())) - logstr = f"!!!!!ERROR!!!!!{datetime_str} {UPC_ADDR} Telnet检查时发生未知错误: {e}!!!!!" - logging.error(logstr, exc_info=True) - print(logstr) - else: - upc_send_command(UPC_ADDR, upc_command, LOG_FILE) diff --git a/bin/sender_tcp.py b/bin/sender_tcp.py deleted file mode 100755 index 7f8c673..0000000 --- a/bin/sender_tcp.py +++ /dev/null @@ -1,140 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- -# Auto-generated from template. DO NOT EDIT DIRECTLY! - -import sys -import socket -import time -import logging -import telnetlib - - -def tcp_command_send(upc_addr, upc_command, data): - """负责发送数据和接收一次响应""" - timeout = 2 - socket.setdefaulttimeout(timeout) - try: - client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - logging.debug(f"尝试连接到 {upc_addr[0]}:{upc_addr[1]}...") - client.connect(upc_addr) - logging.debug(f"成功连接到 {upc_addr[0]}:{upc_addr[1]}。") - - logging.info(f"正在发送命令 '{upc_command}' 到 {upc_addr}: {data!r} (原始字节)") - client.send(data) - logging.debug(f"数据发送完成。") - - recv_buffer_size = 1024 - response_bytes = b'' - try: - logging.debug(f"尝试从 {upc_addr} 接收响应数据...") - response_bytes = client.recv(recv_buffer_size) - if response_bytes: - logging.info(f"从 {upc_addr} 收到原始响应字节: {response_bytes!r}") - try: - response_str = response_bytes.decode('utf-8', errors='ignore') - logging.info(f"从 {upc_addr} 收到解码响应字符串: '{response_str}'") - except Exception as decode_e: - logging.warning(f"解码从 {upc_addr} 收到的响应时发生错误: {decode_e}") - else: - logging.info(f"从 {upc_addr} 未收到响应数据 (连接可能已关闭或设备未发送)。") - except socket.timeout: - logging.warning(f"从 {upc_addr} 接收响应超时。") - except OSError as recv_e: - logging.error(f"从 {upc_addr} 接收响应时发生网络错误: {recv_e}") - - client.close() - logging.debug(f"连接关闭。") - return True - except OSError as e: - logging.error(f"命令 '{upc_command}' 发送至 {upc_addr} 失败: {e}") - return False - - -# 指令定义表(从配置文件读取) -COMMAND_DEFINITIONS = { - "open1": "000100000008010F006400010001", - "close1": "000100000008010F006400010000", - "open2": "000100000008010F006500010001", - "close2": "000100000008010F006500010000", - "open3": "000100000008010F006600010001", - "close3": "000100000008010F006600010000", - "open4": "000100000008010F006700010001", - "close4": "000100000008010F006700010000", - "openall4": "000100000008010F00640004000F", - "closeall4": "000100000008010F006400040000", - "open5": "000100000008010F006800010001", - "close5": "000100000008010F006800010000", - "open6": "000100000008010F006900010001", - "close6": "000100000008010F006900010000", - "open7": "000100000008010F006A00010001", - "close7": "000100000008010F006A00010000", - "open8": "000100000008010F006B00010001", - "close8": "000100000008010F006B00010000", - "getstat": "fe010000000429C6", - "getstat01": "fe010100000429C6", -} - - -def upc_send_command(upc_addr, upc_command, log_file): - """将命令发送给终端设备""" - data = None - - # 查找指令定义 - if upc_command in COMMAND_DEFINITIONS: - hex_str = COMMAND_DEFINITIONS[upc_command] - data = bytes.fromhex(hex_str) - - if data is None: - datetime_str = time.strftime(ISOTIMEFORMAT, time.localtime(time.time())) - logstr = f"{datetime_str} 未知命令: {upc_command},没有对应的数据可发送。" - logging.warning(logstr) - print(logstr) - else: - i = 1 - while i <= 3: # 尝试发送3次 - if tcp_command_send(upc_addr, upc_command, data): - datetime_str = time.strftime(ISOTIMEFORMAT, time.localtime(time.time())) - logstr = f"{datetime_str} {upc_command}命令第{i}次发送成功" - logging.info(logstr) - return - else: - datetime_str = time.strftime(ISOTIMEFORMAT, time.localtime(time.time())) - logstr = f"{datetime_str} {upc_command}命令第{i}次发送失败,3秒后进行第{i+1}次尝试" - logging.warning(logstr) - time.sleep(3) - i = i + 1 - - datetime_str = time.strftime(ISOTIMEFORMAT, time.localtime(time.time())) - logstr = f"{datetime_str} {upc_command}命令在3次尝试后发送均失败!" - logging.error(logstr) - - -if __name__ == '__main__': - ISOTIMEFORMAT = '%Y-%m-%d %X' - - UPC_DEV_IP = sys.argv[1] - UPC_DEV_PORT = sys.argv[2] - upc_command = sys.argv[3] - LOG_FILE = sys.argv[4] - - logging.basicConfig(filename=LOG_FILE, filemode="a", level=logging.DEBUG) - UPC_ADDR = (UPC_DEV_IP, int(UPC_DEV_PORT)) - - # 验证端口是否能Telnet通 - try: - logging.debug(f"尝试通过 Telnet 检查端口 {UPC_ADDR[0]}:{UPC_ADDR[1]} 可访问性...") - tn = telnetlib.Telnet(UPC_DEV_IP, UPC_DEV_PORT) - tn.close() - logging.debug(f"端口 {UPC_ADDR[0]}:{UPC_ADDR[1]} Telnet 检查通过。") - except OSError as e: - datetime_str = time.strftime(ISOTIMEFORMAT, time.localtime(time.time())) - logstr = f"!!!!!ERROR!!!!!{datetime_str} {UPC_ADDR} 端口无法访问,请检查设备或网络连接: {e}!!!!!" - logging.error(logstr) - print(logstr) - except Exception as e: - datetime_str = time.strftime(ISOTIMEFORMAT, time.localtime(time.time())) - logstr = f"!!!!!ERROR!!!!!{datetime_str} {UPC_ADDR} Telnet检查时发生未知错误: {e}!!!!!" - logging.error(logstr, exc_info=True) - print(logstr) - else: - upc_send_command(UPC_ADDR, upc_command, LOG_FILE) diff --git a/bin/sender_udp.py b/bin/sender_udp.py deleted file mode 100755 index 09297aa..0000000 --- a/bin/sender_udp.py +++ /dev/null @@ -1,128 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- -# Auto-generated from template. DO NOT EDIT DIRECTLY! - -import sys -import socket -import time -import logging - - -def udp_command_send(upc_addr, upc_command, data, timeout=2): - """通过UDP发送数据并接收响应""" - sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - sock.settimeout(timeout) - - try: - logging.debug(f"尝试发送UDP数据到 {upc_addr[0]}:{upc_addr[1]}...") - - logging.info(f"正在发送UDP命令 '{upc_command}' 到 {upc_addr}: {data!r} (原始字节)") - sock.sendto(data, upc_addr) - logging.debug(f"UDP数据发送完成。") - - # 尝试接收响应 - recv_buffer_size = 1024 - try: - logging.debug(f"等待从 {upc_addr} 接收UDP响应...") - response_bytes, addr = sock.recvfrom(recv_buffer_size) - if response_bytes: - logging.info(f"从 {addr} 收到UDP原始响应字节: {response_bytes!r}") - try: - response_str = response_bytes.decode('utf-8', errors='ignore') - logging.info(f"从 {addr} 收到UDP解码响应字符串: '{response_str}'") - except Exception as decode_e: - logging.warning(f"解码UDP响应时发生错误: {decode_e}") - else: - logging.info(f"未收到UDP响应数据。") - except socket.timeout: - logging.warning(f"接收UDP响应超时(设备可能不返回响应,这通常是正常的)。") - except OSError as recv_e: - logging.error(f"接收UDP响应时发生网络错误: {recv_e}") - - sock.close() - logging.debug(f"UDP socket关闭。") - return True - except OSError as e: - logging.error(f"UDP命令 '{upc_command}' 发送至 {upc_addr} 失败: {e}") - return False - finally: - try: - sock.close() - except: - pass - - -# 指令定义表(从配置文件读取) -COMMAND_DEFINITIONS = { - "open1": "000100000008010F006400010001", - "close1": "000100000008010F006400010000", - "open2": "000100000008010F006500010001", - "close2": "000100000008010F006500010000", - "open3": "000100000008010F006600010001", - "close3": "000100000008010F006600010000", - "open4": "000100000008010F006700010001", - "close4": "000100000008010F006700010000", - "openall4": "000100000008010F00640004000F", - "closeall4": "000100000008010F006400040000", - "open5": "000100000008010F006800010001", - "close5": "000100000008010F006800010000", - "open6": "000100000008010F006900010001", - "close6": "000100000008010F006900010000", - "open7": "000100000008010F006A00010001", - "close7": "000100000008010F006A00010000", - "open8": "000100000008010F006B00010001", - "close8": "000100000008010F006B00010000", - "getstat": "fe010000000429C6", - "getstat01": "fe010100000429C6", -} - - -def upc_send_command(upc_addr, upc_command, log_file): - """将命令发送给终端设备""" - data = None - - # 查找指令定义 - if upc_command in COMMAND_DEFINITIONS: - hex_str = COMMAND_DEFINITIONS[upc_command] - data = bytes.fromhex(hex_str) - - if data is None: - datetime_str = time.strftime(ISOTIMEFORMAT, time.localtime(time.time())) - logstr = f"{datetime_str} 未知命令: {upc_command},没有对应的数据可发送。" - logging.warning(logstr) - print(logstr) - else: - i = 1 - while i <= 3: # 尝试发送3次 - if udp_command_send(upc_addr, upc_command, data): - datetime_str = time.strftime(ISOTIMEFORMAT, time.localtime(time.time())) - logstr = f"{datetime_str} {upc_command}命令第{i}次发送成功" - logging.info(logstr) - return - else: - datetime_str = time.strftime(ISOTIMEFORMAT, time.localtime(time.time())) - logstr = f"{datetime_str} {upc_command}命令第{i}次发送失败,3秒后进行第{i+1}次尝试" - logging.warning(logstr) - time.sleep(3) - i = i + 1 - - datetime_str = time.strftime(ISOTIMEFORMAT, time.localtime(time.time())) - logstr = f"{datetime_str} {upc_command}命令在3次尝试后发送均失败!" - logging.error(logstr) - - -if __name__ == '__main__': - ISOTIMEFORMAT = '%Y-%m-%d %X' - - UPC_DEV_IP = sys.argv[1] - UPC_DEV_PORT = int(sys.argv[2]) - upc_command = sys.argv[3] - LOG_FILE = sys.argv[4] - - logging.basicConfig(filename=LOG_FILE, filemode="a", level=logging.DEBUG) - UPC_ADDR = (UPC_DEV_IP, UPC_DEV_PORT) - - # UDP 是无连接的,无需像TCP那样预先检查端口连通性 - # 直接发送数据 - logging.info(f"UDP模式:准备发送命令到 {UPC_ADDR}") - upc_send_command(UPC_ADDR, upc_command, LOG_FILE) diff --git a/config/devices.json b/config/devices.json index 7b23a84..c174608 100644 --- a/config/devices.json +++ b/config/devices.json @@ -1,6 +1,6 @@ { "global": { - "tms_server_ip": "192.168.8.9", + "tms_server_ip": "192.168.139.133", "python_path": "/usr/bin/python3", "base_dir": "/home/smart/pythonPJ/upc_resent" }, @@ -51,9 +51,7 @@ "open7": "000100000008010F006A00010001", "close7": "000100000008010F006A00010000", "open8": "000100000008010F006B00010001", - "close8": "000100000008010F006B00010000", - "getstat": "fe010000000429C6", - "getstat01": "fe010100000429C6" + "close8": "000100000008010F006B00010000" }, "mappings": { "open": "openall4", diff --git a/control.sh b/control.sh new file mode 100755 index 0000000..b77937e --- /dev/null +++ b/control.sh @@ -0,0 +1,236 @@ +#!/bin/bash +# Auto-generated control script +# Usage: ./control.sh {start|stop|restart|status} + +BASE_DIR="/home/smart/pythonPJ/upc_resent" +PYTHON_PATH="/usr/bin/python3" + +# 设备列表: ID 名称 协议 +DEVICES=( + "dev1" "设备73-TCP" "TCP" + "dev2" "设备125-TCP" "TCP" + "dev3" "设备UDP示例" "UDP" +) + +# 颜色定义 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +show_help() { + echo "Usage: $0 {start|stop|restart|status}" + echo "" + echo "Commands:" + echo " start 启动所有服务" + echo " stop 停止所有服务" + echo " restart 重启所有服务" + echo " status 查看服务状态" +} + +check_root() { + if [[ $EUID -ne 0 ]]; then + echo -e "${YELLOW}Warning: 建议使用 root 权限运行${NC}" + fi +} + +start_service() { + local device_id=$1 + local device_name=$2 + local protocol=$3 + local script_path="$BASE_DIR/bin/$device_id.py" + + # 检查进程是否已存在(使用更精确的匹配) + local pid=$(pgrep -f "${PYTHON_PATH}.*${script_path}" | head -1) + if [[ -n "$pid" ]]; then + echo -e "[${YELLOW}SKIP${NC}] $device_name ($device_id) - ${protocol} 已在运行 (PID: $pid)" + return 0 + fi + + echo -n "[START] $device_name ($device_id) - ${protocol} ... " + nohup $PYTHON_PATH "$script_path" > /dev/null 2>&1 & + sleep 1 + + # 检查是否启动成功 + pid=$(pgrep -f "${PYTHON_PATH}.*${script_path}" | head -1) + if [[ -n "$pid" ]]; then + echo -e "${GREEN}OK${NC} (PID: $pid)" + return 0 + else + echo -e "${RED}FAILED${NC}" + return 1 + fi +} + +stop_service() { + local device_id=$1 + local device_name=$2 + local protocol=$3 + local script_path="$BASE_DIR/bin/$device_id.py" + + # 使用更精确的匹配模式 + local pids=$(pgrep -f "${PYTHON_PATH}.*${script_path}") + if [[ -z "$pids" ]]; then + echo -e "[${YELLOW}SKIP${NC}] $device_name ($device_id) - 未运行" + return 0 + fi + + # 获取第一个匹配的 PID + local pid=$(echo "$pids" | head -1) + echo -n "[STOP] $device_name ($device_id) - ${protocol} (PID: $pid) ... " + + # 结束所有匹配的进程 + echo "$pids" | while read -r p; do + kill "$p" 2>/dev/null + done + + # 等待进程结束 + local i + for i in {1..10}; do + sleep 0.5 + pids=$(pgrep -f "${PYTHON_PATH}.*${script_path}" || true) + if [[ -z "$pids" ]]; then + break + fi + done + + # 检查是否还有残留进程 + pids=$(pgrep -f "${PYTHON_PATH}.*${script_path}" || true) + if [[ -n "$pids" ]]; then + # 强制结束残留进程 + echo "$pids" | while read -r p; do + kill -9 "$p" 2>/dev/null + done + sleep 0.5 + fi + + # 最终检查 + pids=$(pgrep -f "${PYTHON_PATH}.*${script_path}" || true) + if [[ -z "$pids" ]]; then + echo -e "${GREEN}OK${NC}" + return 0 + else + echo -e "${RED}FAILED${NC}" + return 1 + fi +} + +status_service() { + local device_id=$1 + local device_name=$2 + local protocol=$3 + local script_path="$BASE_DIR/bin/$device_id.py" + + local pid=$(pgrep -f "${PYTHON_PATH}.*${script_path}" | head -1) + if [[ -n "$pid" ]]; then + echo -e "${GREEN}[RUNNING]${NC} $device_name ($device_id) - ${protocol} (PID: $pid)" + return 0 + else + echo -e "${RED}[STOPPED]${NC} $device_name ($device_id) - ${protocol}" + return 1 + fi +} + +cmd_start() { + echo "=======================================" + echo "启动 UPC Resent 服务" + echo "=======================================" + check_root + echo "" + + local count=0 + local device_id device_name protocol + for ((i=0; i<${#DEVICES[@]}; i+=3)); do + device_id="${DEVICES[i]}" + device_name="${DEVICES[i+1]}" + protocol="${DEVICES[i+2]}" + + if start_service "$device_id" "$device_name" "$protocol"; then + ((count++)) + fi + done + + echo "" + echo "=======================================" + echo "启动完成: $count/$((${#DEVICES[@]}/3)) 个服务" + echo "=======================================" +} + +cmd_stop() { + echo "=======================================" + echo "停止 UPC Resent 服务" + echo "=======================================" + echo "" + + local count=0 + local device_id device_name protocol + for ((i=0; i<${#DEVICES[@]}; i+=3)); do + device_id="${DEVICES[i]}" + device_name="${DEVICES[i+1]}" + protocol="${DEVICES[i+2]}" + + if stop_service "$device_id" "$device_name" "$protocol"; then + ((count++)) + fi + done + + echo "" + echo "=======================================" + echo "停止完成: $count/$((${#DEVICES[@]}/3)) 个服务" + echo "=======================================" +} + +cmd_restart() { + cmd_stop + echo "" + sleep 1 + cmd_start +} + +cmd_status() { + echo "=======================================" + echo "UPC Resent 服务状态" + echo "=======================================" + echo "" + + local running=0 + local stopped=0 + local device_id device_name protocol + + for ((i=0; i<${#DEVICES[@]}; i+=3)); do + device_id="${DEVICES[i]}" + device_name="${DEVICES[i+1]}" + protocol="${DEVICES[i+2]}" + + if status_service "$device_id" "$device_name" "$protocol"; then + ((running++)) + else + ((stopped++)) + fi + done + + echo "" + echo "=======================================" + echo "运行中: $running, 已停止: $stopped, 总计: $((${#DEVICES[@]}/3))" + echo "=======================================" +} + +# 主逻辑 +case "${1:-}" in + start) + cmd_start + ;; + stop) + cmd_stop + ;; + restart) + cmd_restart + ;; + status) + cmd_status + ;; + *) + show_help + exit 1 + ;; +esac diff --git a/crond/upcrond-192.168.8.125.py b/crond/upcrond-192.168.8.125.py deleted file mode 100644 index 51ea9c3..0000000 --- a/crond/upcrond-192.168.8.125.py +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- - -import time -import logging -import os -import socket -import sys # sys 模块用于 sys.exit(),虽然这里没有直接使用,但通常在脚本中需要 - -# --- 配置日志 --- -# 确保日志文件路径正确 -LOG_FILE = '/opt/upc_resent/log/upc-192.168.8.125.log' -# 定义时间格式,将被 logging.basicConfig 的 datefmt 使用 -ISOTIMEFORMAT = '%Y-%m-%d %X' - -# 配置日志,确保只执行一次 -# format 中包含了时间戳 %(asctime)s,所以不需要手动在日志字符串中添加 datetime -logging.basicConfig(filename=LOG_FILE, filemode="a", level=logging.DEBUG, - format='%(asctime)s - %(levelname)s - %(message)s', datefmt=ISOTIMEFORMAT) -# --- 日志配置结束 --- - - -def IsOpen(ip, port): - """ - 检查指定IP和端口是否可达。 - 如果端口不可达,则记录警告并尝试重启另一个Python脚本。 - """ - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.settimeout(1) # 设置连接超时为1秒,避免无限期阻塞 - try: - logging.debug(f"尝试连接到 {ip}:{port}...") - s.connect((ip, int(port))) - s.shutdown(socket.SHUT_RDWR) # 使用 SHUT_RDWR 代替数字 2,更具可读性 - - print(f"端口 {port} is open") # Python 3 print 函数 - logging.info(f"端口 {port} is open") - return True - except (OSError, socket.timeout) as e: # 捕获具体的网络错误和超时 - print(f"端口 {port} is down") # Python 3 print 函数 - logging.warning(f"端口 {port} 检查失败: {e},尝试重启程序") - - # --- 重启命令 --- - # 确保这里的 python3 路径和脚本路径正确 - # 这里的脚本名 "192.168.8.125.py" 看起来是硬编码的,请确认是否正确 - restart_command = "/usr/bin/python3 /opt/upc_resent/bin/192.168.8.125.py &" - logging.info(f"执行重启命令: {restart_command}") - os.system(restart_command) - # --- 重启命令结束 --- - - return False - except ValueError: # 捕获 int(port) 转换失败的情况 - print(f"错误: 端口 '{port}' 不是有效的数字。") - logging.error(f"端口 '{port}' 不是有效的数字。") - return False - finally: - s.close() # 确保无论成功或失败,socket 都会被关闭 - - -if __name__ == '__main__': - # --- 目标设备IP和端口 --- - # 这些值在原脚本中是硬编码的,如果需要从命令行参数获取,请修改 - target_ip = '192.168.8.9' - target_port = 10129 - # --- 目标设备IP和端口结束 --- - - logging.info(f"启动端口检查程序,检查 {target_ip}:{target_port}") - IsOpen(target_ip, target_port) - - diff --git a/crond/upcrond-192.168.8.73.py b/crond/upcrond-192.168.8.73.py deleted file mode 100644 index ba1f171..0000000 --- a/crond/upcrond-192.168.8.73.py +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- - -import time -import logging -import os -import socket -import sys # sys 模块用于 sys.exit(),虽然这里没有直接使用,但通常在脚本中需要 - -# --- 配置日志 --- -# 确保日志文件路径正确 -LOG_FILE = '/opt/upc_resent/log/upc-192.168.8.73.log' -# 定义时间格式,将被 logging.basicConfig 的 datefmt 使用 -ISOTIMEFORMAT = '%Y-%m-%d %X' - -# 配置日志,确保只执行一次 -# format 中包含了时间戳 %(asctime)s,所以不需要手动在日志字符串中添加 datetime -logging.basicConfig(filename=LOG_FILE, filemode="a", level=logging.DEBUG, - format='%(asctime)s - %(levelname)s - %(message)s', datefmt=ISOTIMEFORMAT) -# --- 日志配置结束 --- - - -def IsOpen(ip, port): - """ - 检查指定IP和端口是否可达。 - 如果端口不可达,则记录警告并尝试重启另一个Python脚本。 - """ - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.settimeout(1) # 设置连接超时为1秒,避免无限期阻塞 - try: - logging.debug(f"尝试连接到 {ip}:{port}...") - s.connect((ip, int(port))) - s.shutdown(socket.SHUT_RDWR) # 使用 SHUT_RDWR 代替数字 2,更具可读性 - - print(f"端口 {port} is open") # Python 3 print 函数 - logging.info(f"端口 {port} is open") - return True - except (OSError, socket.timeout) as e: # 捕获具体的网络错误和超时 - print(f"端口 {port} is down") # Python 3 print 函数 - logging.warning(f"端口 {port} 检查失败: {e},尝试重启程序") - - # --- 重启命令 --- - # 确保这里的 python3 路径和脚本路径正确 - # 这里的脚本名 "192.168.8.125.py" 看起来是硬编码的,请确认是否正确 - restart_command = "/usr/bin/python3 /opt/upc_resent/bin/192.168.8.73.py &" - logging.info(f"执行重启命令: {restart_command}") - os.system(restart_command) - # --- 重启命令结束 --- - - return False - except ValueError: # 捕获 int(port) 转换失败的情况 - print(f"错误: 端口 '{port}' 不是有效的数字。") - logging.error(f"端口 '{port}' 不是有效的数字。") - return False - finally: - s.close() # 确保无论成功或失败,socket 都会被关闭 - - -if __name__ == '__main__': - # --- 目标设备IP和端口 --- - # 这些值在原脚本中是硬编码的,如果需要从命令行参数获取,请修改 - target_ip = '192.168.8.9' - target_port = 10079 - # --- 目标设备IP和端口结束 --- - - logging.info(f"启动端口检查程序,检查 {target_ip}:{target_port}") - IsOpen(target_ip, target_port) - - diff --git a/crond/upcrond-dev1.py b/crond/upcrond-dev1.py deleted file mode 100755 index d134d61..0000000 --- a/crond/upcrond-dev1.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- -# Auto-generated from template. DO NOT EDIT DIRECTLY! -# Device: 设备73-TCP (dev1) - -import time -import logging -import os -import socket -import sys - -# ====== 配置参数(从配置文件读取)====== -TARGET_IP = '192.168.8.9' -TARGET_PORT = 10079 -LOG_FILE = '/home/smart/pythonPJ/upc_resent/log/crond-dev1.log' -RESTART_COMMAND = "/usr/bin/python3 /home/smart/pythonPJ/upc_resent/bin/dev1.py &" -DEVICE_ID = 'dev1' -# ========================= - -ISOTIMEFORMAT = '%Y-%m-%d %X' - -logging.basicConfig(filename=LOG_FILE, filemode="a", level=logging.DEBUG, - format='%(asctime)s - %(levelname)s - %(message)s', datefmt=ISOTIMEFORMAT) - - -def is_port_open(ip, port): - """检查指定IP和端口是否可达""" - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.settimeout(1) - try: - logging.debug(f"尝试连接到 {ip}:{port}...") - s.connect((ip, int(port))) - s.shutdown(socket.SHUT_RDWR) - print(f"[{DEVICE_ID}] 端口 {port} is open") - logging.info(f"端口 {port} is open") - return True - except (OSError, socket.timeout) as e: - print(f"[{DEVICE_ID}] 端口 {port} is down") - logging.warning(f"端口 {port} 检查失败: {e},尝试重启程序") - logging.info(f"执行重启命令: {RESTART_COMMAND}") - os.system(RESTART_COMMAND) - return False - except ValueError: - print(f"错误: 端口 '{port}' 不是有效的数字。") - logging.error(f"端口 '{port}' 不是有效的数字。") - return False - finally: - s.close() - - -if __name__ == '__main__': - logging.info(f"[{DEVICE_ID}] 启动端口检查程序,检查 {TARGET_IP}:{TARGET_PORT}") - print(f"[{DEVICE_ID}] 启动端口检查程序,检查 {TARGET_IP}:{TARGET_PORT}") - is_port_open(TARGET_IP, TARGET_PORT) diff --git a/crond/upcrond-dev2.py b/crond/upcrond-dev2.py deleted file mode 100755 index 6dad76e..0000000 --- a/crond/upcrond-dev2.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- -# Auto-generated from template. DO NOT EDIT DIRECTLY! -# Device: 设备125-TCP (dev2) - -import time -import logging -import os -import socket -import sys - -# ====== 配置参数(从配置文件读取)====== -TARGET_IP = '192.168.8.9' -TARGET_PORT = 10129 -LOG_FILE = '/home/smart/pythonPJ/upc_resent/log/crond-dev2.log' -RESTART_COMMAND = "/usr/bin/python3 /home/smart/pythonPJ/upc_resent/bin/dev2.py &" -DEVICE_ID = 'dev2' -# ========================= - -ISOTIMEFORMAT = '%Y-%m-%d %X' - -logging.basicConfig(filename=LOG_FILE, filemode="a", level=logging.DEBUG, - format='%(asctime)s - %(levelname)s - %(message)s', datefmt=ISOTIMEFORMAT) - - -def is_port_open(ip, port): - """检查指定IP和端口是否可达""" - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.settimeout(1) - try: - logging.debug(f"尝试连接到 {ip}:{port}...") - s.connect((ip, int(port))) - s.shutdown(socket.SHUT_RDWR) - print(f"[{DEVICE_ID}] 端口 {port} is open") - logging.info(f"端口 {port} is open") - return True - except (OSError, socket.timeout) as e: - print(f"[{DEVICE_ID}] 端口 {port} is down") - logging.warning(f"端口 {port} 检查失败: {e},尝试重启程序") - logging.info(f"执行重启命令: {RESTART_COMMAND}") - os.system(RESTART_COMMAND) - return False - except ValueError: - print(f"错误: 端口 '{port}' 不是有效的数字。") - logging.error(f"端口 '{port}' 不是有效的数字。") - return False - finally: - s.close() - - -if __name__ == '__main__': - logging.info(f"[{DEVICE_ID}] 启动端口检查程序,检查 {TARGET_IP}:{TARGET_PORT}") - print(f"[{DEVICE_ID}] 启动端口检查程序,检查 {TARGET_IP}:{TARGET_PORT}") - is_port_open(TARGET_IP, TARGET_PORT) diff --git a/crond/upcrond-dev3.py b/crond/upcrond-dev3.py deleted file mode 100755 index 464e478..0000000 --- a/crond/upcrond-dev3.py +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- -# Auto-generated from template. DO NOT EDIT DIRECTLY! -# Device: 设备UDP示例 (dev3) - UDP Protocol - -import time -import logging -import os -import socket -import sys -import subprocess - -# ====== 配置参数(从配置文件读取)====== -TARGET_IP = '192.168.8.9' -TARGET_PORT = 10080 -LOG_FILE = '/home/smart/pythonPJ/upc_resent/log/crond-dev3.log' -RESTART_COMMAND = "/usr/bin/python3 /home/smart/pythonPJ/upc_resent/bin/dev3.py &" -DEVICE_ID = 'dev3' -# ========================= - -ISOTIMEFORMAT = '%Y-%m-%d %X' - -logging.basicConfig(filename=LOG_FILE, filemode="a", level=logging.DEBUG, - format='%(asctime)s - %(levelname)s - %(message)s', datefmt=ISOTIMEFORMAT) - - -def is_udp_port_open(ip, port): - """ - 检查UDP端口是否可用。 - UDP是无连接的,这里通过检查端口是否被占用或发送测试数据来判断。 - """ - try: - # 尝试绑定到该端口,如果成功说明端口未被占用(服务未启动) - # 如果失败说明端口已被占用(服务正在运行) - test_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - test_sock.settimeout(1) - test_sock.bind((ip, int(port))) - test_sock.close() - - # 如果绑定成功,说明服务未启动 - print(f"[{DEVICE_ID}] UDP端口 {port} 未被占用,服务可能未运行") - logging.warning(f"UDP端口 {port} 未被占用,服务可能未运行,尝试重启程序") - logging.info(f"执行重启命令: {RESTART_COMMAND}") - os.system(RESTART_COMMAND) - return False - except OSError as e: - # 绑定失败,说明端口已被占用,服务正在运行 - if "Address already in use" in str(e) or "98" in str(e): - print(f"[{DEVICE_ID}] UDP端口 {port} is open (已被占用,服务运行中)") - logging.info(f"UDP端口 {port} is open (服务运行中)") - return True - else: - print(f"[{DEVICE_ID}] 检查UDP端口 {port} 时发生错误: {e}") - logging.error(f"检查UDP端口 {port} 时发生错误: {e}") - return False - - -def check_process_running(): - """通过进程名检查服务是否正在运行""" - try: - # 检查是否有对应设备的Python进程在运行 - cmd = f"ps aux | grep '{DEVICE_ID}.py' | grep -v grep" - result = subprocess.run(cmd, shell=True, capture_output=True, text=True) - if result.returncode == 0 and result.stdout.strip(): - print(f"[{DEVICE_ID}] 进程检查: 服务正在运行") - logging.info(f"进程检查: 服务正在运行") - return True - else: - print(f"[{DEVICE_ID}] 进程检查: 服务未运行") - logging.warning(f"进程检查: 服务未运行,尝试重启") - logging.info(f"执行重启命令: {RESTART_COMMAND}") - os.system(RESTART_COMMAND) - return False - except Exception as e: - print(f"[{DEVICE_ID}] 进程检查失败: {e}") - logging.error(f"进程检查失败: {e}") - return False - - -if __name__ == '__main__': - logging.info(f"[{DEVICE_ID}] 启动UDP端口检查程序,检查 {TARGET_IP}:{TARGET_PORT}") - print(f"[{DEVICE_ID}] 启动UDP端口检查程序,检查 {TARGET_IP}:{TARGET_PORT}") - - # 对于UDP,优先使用进程检查方式 - check_process_running() diff --git a/log/192.168.8.125.log b/log/192.168.8.125.log deleted file mode 100644 index 30d2642..0000000 Binary files a/log/192.168.8.125.log and /dev/null differ diff --git a/log/192.168.8.73.log b/log/192.168.8.73.log deleted file mode 100644 index 55d401c..0000000 --- a/log/192.168.8.73.log +++ /dev/null @@ -1,5 +0,0 @@ -INFO:root:服务启动,监听 192.168.8.9:10079 -INFO:root:===2026-03-21 20:14:40收到客户端192.168.9.71:56925发送的指令: 'close1' -INFO:root:===2026-03-21 20:14:40 映射到内部指令: 'close1' -INFO:root:执行外部命令: /usr/bin/python3 /opt/upc_resent/bin/sender.py 192.168.8.73 502 close1 /opt/upc_resent/log/192.168.8.73.log -INFO:root:2026-03-21 20:14:40 close1命令第1次发送成功 diff --git a/log/upc-192.168.8.125.log b/log/upc-192.168.8.125.log deleted file mode 100644 index 8af09bf..0000000 --- a/log/upc-192.168.8.125.log +++ /dev/null @@ -1,3 +0,0 @@ -2026-03-21 21:06:19 - INFO - 启动端口检查程序,检查 192.168.8.9:10129 -2026-03-21 21:06:19 - DEBUG - 尝试连接到 192.168.8.9:10129... -2026-03-21 21:06:19 - INFO - 端口 10129 is open diff --git a/scripts/generate.py b/scripts/generate.py index 5b50118..2c7c9f2 100644 --- a/scripts/generate.py +++ b/scripts/generate.py @@ -210,27 +210,34 @@ def generate_crontab(devices, global_config): return output_file -def generate_start_script(devices, global_config): - """生成启动脚本""" - lines = ['#!/bin/bash'] - lines.append('# Auto-generated start script') - lines.append('') - lines.append('# 启动所有监听服务') +def generate_control_script(devices, global_config): + """生成控制脚本 (start/stop/restart/status)""" + template_file = 'templates/control.sh.tpl' + with open(template_file, 'r', encoding='utf-8') as f: + template = f.read() + + device_list = [] for device in devices: - if not device.get('enabled', True): - lines.append(f"# {device['name']} ({device['id']}) - 已禁用") - continue - protocol = device.get('protocol', 'tcp').upper() - script_path = f"{global_config['base_dir']}/bin/{device['id']}.py" - lines.append(f"echo '启动 {device['name']} ({device['id']}) - {protocol}...'") - lines.append(f"su root -c \"{global_config['python_path']} {script_path} &\"") + if device.get('enabled', True): + device_list.append({ + 'id': device['id'], + 'name': device['name'], + 'protocol': device.get('protocol', 'tcp').upper() + }) - lines.append('') - lines.append('echo "所有服务已启动"') + # 构建设备列表字符串 + device_defs = "\n".join([ + f" \"{d['id']}\" \"{d['name']}\" \"{d['protocol']}\"" + for d in device_list + ]) - content = '\n'.join(lines) + '\n' - output_file = 'start.sh' + # 替换模板变量(使用 replace 避免与 bash 变量冲突) + content = template.replace('{base_dir}', global_config['base_dir']) + content = content.replace('{python_path}', global_config['python_path']) + content = content.replace('{device_defs}', device_defs) + + output_file = 'control.sh' with open(output_file, 'w', encoding='utf-8') as f: f.write(content) @@ -383,15 +390,15 @@ def main(): print("\n[生成配置文件]") generated_files.append(generate_crontab(config['devices'], global_config)) - # 4. 生成启动脚本 - generated_files.append(generate_start_script(devices, global_config)) + # 4. 生成控制脚本 + generated_files.append(generate_control_script(devices, global_config)) print("\n" + "=" * 50) print(f"[✓] 代码生成完成!共生成 {len(generated_files)} 个文件") print("=" * 50) print(f"\n部署目录: {global_config['base_dir']}") print("\n使用方法:") - print(f" 1. 启动服务: ./{generated_files[-1]}") + print(f" 1. 控制服务: ./{generated_files[-1]} {{start|stop|restart|status}}") print(f" 2. 配置 crontab: crontab crontab.txt") print("\n支持的协议:") protocols = set(d.get('protocol', 'tcp').upper() for d in devices) diff --git a/start.sh b/start.sh deleted file mode 100755 index ea7bb98..0000000 --- a/start.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -# Auto-generated start script - -# 启动所有监听服务 -echo '启动 设备73-TCP (dev1) - TCP...' -su root -c "/usr/bin/python3 /home/smart/pythonPJ/upc_resent/bin/dev1.py &" -echo '启动 设备125-TCP (dev2) - TCP...' -su root -c "/usr/bin/python3 /home/smart/pythonPJ/upc_resent/bin/dev2.py &" -echo '启动 设备UDP示例 (dev3) - UDP...' -su root -c "/usr/bin/python3 /home/smart/pythonPJ/upc_resent/bin/dev3.py &" - -echo "所有服务已启动" diff --git a/templates/control.sh.tpl b/templates/control.sh.tpl new file mode 100644 index 0000000..31a2349 --- /dev/null +++ b/templates/control.sh.tpl @@ -0,0 +1,234 @@ +#!/bin/bash +# Auto-generated control script +# Usage: ./control.sh {start|stop|restart|status} + +BASE_DIR="{base_dir}" +PYTHON_PATH="{python_path}" + +# 设备列表: ID 名称 协议 +DEVICES=( +{device_defs} +) + +# 颜色定义 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +show_help() { + echo "Usage: $0 {start|stop|restart|status}" + echo "" + echo "Commands:" + echo " start 启动所有服务" + echo " stop 停止所有服务" + echo " restart 重启所有服务" + echo " status 查看服务状态" +} + +check_root() { + if [[ $EUID -ne 0 ]]; then + echo -e "${YELLOW}Warning: 建议使用 root 权限运行${NC}" + fi +} + +start_service() { + local device_id=$1 + local device_name=$2 + local protocol=$3 + local script_path="$BASE_DIR/bin/$device_id.py" + + # 检查进程是否已存在(使用更精确的匹配) + local pid=$(pgrep -f "${PYTHON_PATH}.*${script_path}" | head -1) + if [[ -n "$pid" ]]; then + echo -e "[${YELLOW}SKIP${NC}] $device_name ($device_id) - ${protocol} 已在运行 (PID: $pid)" + return 0 + fi + + echo -n "[START] $device_name ($device_id) - ${protocol} ... " + nohup $PYTHON_PATH "$script_path" > /dev/null 2>&1 & + sleep 1 + + # 检查是否启动成功 + pid=$(pgrep -f "${PYTHON_PATH}.*${script_path}" | head -1) + if [[ -n "$pid" ]]; then + echo -e "${GREEN}OK${NC} (PID: $pid)" + return 0 + else + echo -e "${RED}FAILED${NC}" + return 1 + fi +} + +stop_service() { + local device_id=$1 + local device_name=$2 + local protocol=$3 + local script_path="$BASE_DIR/bin/$device_id.py" + + # 使用更精确的匹配模式 + local pids=$(pgrep -f "${PYTHON_PATH}.*${script_path}") + if [[ -z "$pids" ]]; then + echo -e "[${YELLOW}SKIP${NC}] $device_name ($device_id) - 未运行" + return 0 + fi + + # 获取第一个匹配的 PID + local pid=$(echo "$pids" | head -1) + echo -n "[STOP] $device_name ($device_id) - ${protocol} (PID: $pid) ... " + + # 结束所有匹配的进程 + echo "$pids" | while read -r p; do + kill "$p" 2>/dev/null + done + + # 等待进程结束 + local i + for i in {1..10}; do + sleep 0.5 + pids=$(pgrep -f "${PYTHON_PATH}.*${script_path}" || true) + if [[ -z "$pids" ]]; then + break + fi + done + + # 检查是否还有残留进程 + pids=$(pgrep -f "${PYTHON_PATH}.*${script_path}" || true) + if [[ -n "$pids" ]]; then + # 强制结束残留进程 + echo "$pids" | while read -r p; do + kill -9 "$p" 2>/dev/null + done + sleep 0.5 + fi + + # 最终检查 + pids=$(pgrep -f "${PYTHON_PATH}.*${script_path}" || true) + if [[ -z "$pids" ]]; then + echo -e "${GREEN}OK${NC}" + return 0 + else + echo -e "${RED}FAILED${NC}" + return 1 + fi +} + +status_service() { + local device_id=$1 + local device_name=$2 + local protocol=$3 + local script_path="$BASE_DIR/bin/$device_id.py" + + local pid=$(pgrep -f "${PYTHON_PATH}.*${script_path}" | head -1) + if [[ -n "$pid" ]]; then + echo -e "${GREEN}[RUNNING]${NC} $device_name ($device_id) - ${protocol} (PID: $pid)" + return 0 + else + echo -e "${RED}[STOPPED]${NC} $device_name ($device_id) - ${protocol}" + return 1 + fi +} + +cmd_start() { + echo "=======================================" + echo "启动 UPC Resent 服务" + echo "=======================================" + check_root + echo "" + + local count=0 + local device_id device_name protocol + for ((i=0; i<${#DEVICES[@]}; i+=3)); do + device_id="${DEVICES[i]}" + device_name="${DEVICES[i+1]}" + protocol="${DEVICES[i+2]}" + + if start_service "$device_id" "$device_name" "$protocol"; then + ((count++)) + fi + done + + echo "" + echo "=======================================" + echo "启动完成: $count/$((${#DEVICES[@]}/3)) 个服务" + echo "=======================================" +} + +cmd_stop() { + echo "=======================================" + echo "停止 UPC Resent 服务" + echo "=======================================" + echo "" + + local count=0 + local device_id device_name protocol + for ((i=0; i<${#DEVICES[@]}; i+=3)); do + device_id="${DEVICES[i]}" + device_name="${DEVICES[i+1]}" + protocol="${DEVICES[i+2]}" + + if stop_service "$device_id" "$device_name" "$protocol"; then + ((count++)) + fi + done + + echo "" + echo "=======================================" + echo "停止完成: $count/$((${#DEVICES[@]}/3)) 个服务" + echo "=======================================" +} + +cmd_restart() { + cmd_stop + echo "" + sleep 1 + cmd_start +} + +cmd_status() { + echo "=======================================" + echo "UPC Resent 服务状态" + echo "=======================================" + echo "" + + local running=0 + local stopped=0 + local device_id device_name protocol + + for ((i=0; i<${#DEVICES[@]}; i+=3)); do + device_id="${DEVICES[i]}" + device_name="${DEVICES[i+1]}" + protocol="${DEVICES[i+2]}" + + if status_service "$device_id" "$device_name" "$protocol"; then + ((running++)) + else + ((stopped++)) + fi + done + + echo "" + echo "=======================================" + echo "运行中: $running, 已停止: $stopped, 总计: $((${#DEVICES[@]}/3))" + echo "=======================================" +} + +# 主逻辑 +case "${1:-}" in + start) + cmd_start + ;; + stop) + cmd_stop + ;; + restart) + cmd_restart + ;; + status) + cmd_status + ;; + *) + show_help + exit 1 + ;; +esac diff --git a/templates/crond_udp.py.tpl b/templates/crond_udp.py.tpl index 61eb9f4..bc3add8 100644 --- a/templates/crond_udp.py.tpl +++ b/templates/crond_udp.py.tpl @@ -59,9 +59,13 @@ def check_process_running(): """通过进程名检查服务是否正在运行""" try: # 检查是否有对应设备的Python进程在运行 - cmd = f"ps aux | grep '{{DEVICE_ID}}.py' | grep -v grep" - result = subprocess.run(cmd, shell=True, capture_output=True, text=True) - if result.returncode == 0 and result.stdout.strip(): + # 注意:需要排除 crond 脚本自身的进程 (upcrond-{{DEVICE_ID}}.py) + cmd = f"ps aux | grep '{{DEVICE_ID}}.py' | grep -v grep | grep -v upcrond" + # 兼容 Python 3.6: 使用 PIPE 代替 capture_output + result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + # 兼容 Python 3.6: 手动解码输出 + stdout = result.stdout.decode('utf-8') if result.stdout else '' + if result.returncode == 0 and stdout.strip(): print(f"[{{DEVICE_ID}}] 进程检查: 服务正在运行") logging.info(f"进程检查: 服务正在运行") return True diff --git a/upcstart.sh b/upcstart.sh deleted file mode 100644 index fa029f3..0000000 --- a/upcstart.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -su root -c "/usr/bin/python /opt/upc_resent/bin/192.168.8.73.py &" -su root -c "/usr/bin/python /opt/upc_resent/bin/192.168.8.125.py &"