使用shell并发执行系统命令
一 解决方案
旧方案为挨个执行shell_exec,串行执行,虽然执行很快,奈何监听命令众多,redis连接有等待时间等,有的还需要执行多次取平均值,所以执行完已超过1min
故,改为并发执行命令,单个命令加timeout,则永远可以在10s左右执行完!
- golang形式,需要在该php-server上安装go环境,虽然简单,但生产环境尽量不乱动配置
- php-swoole形式,同上,一个shell文件而已,没必要挨个server都装拓展
- shell的循环&形式,循环体内正则匹配因为本人不熟悉,直接丢给php文件来处理
二 linux.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | timest=$(date "+%Y-%m-%d %H:%M:%S" ) echo "start: " $timest SERVER=manager-admin DEBUG=0 while getopts ":s:d:" opt do case $opt in s) SERVER= "$OPTARG" ;; d) DEBUG= "$OPTARG" ;; esac done mkfifo /home/log/crontab/linux_status exec 0316<>/home/log/crontab/linux_status rm -rf /home/log/crontab/linux_status for ((n=1;n<=10;n++)); do #10>cmd num ji ke echo >&0316 done for ((i=1;i<=7;i++)); do read -u0316 { if [ $i == 1 ] then #负载 QDATA=$(timeout 10 sar -q 1 5) echo "$QDATA" >> "/home/log/crontab/linux_status_" $SERVER "_compelet_q.cron.log" process_tm=$(date "+%Y-%m-%d %H:%M:%S" ) echo "负载|end: " $process_tm elif [ $i == 2 ] then #CPU CPUDATA=$(timeout 10 sar -u 1 5) echo "$CPUDATA" >> "/home/log/crontab/linux_status_" $SERVER "_compelet_cpu.cron.log" process_tm=$(date "+%Y-%m-%d %H:%M:%S" ) echo "CPU|end: " $process_tm elif [ $i == 3 ] then #内存 MEMDATA=$(timeout 10 sar -r 1 5) echo "$MEMDATA" >> "/home/log/crontab/linux_status_" $SERVER "_compelet_mem.cron.log" process_tm=$(date "+%Y-%m-%d %H:%M:%S" ) echo "内存|end: " $process_tm elif [ $i == 4 ] then #磁盘IO IODATA=$(timeout 10 sar -d 1 5) echo "$IODATA" >> "/home/log/crontab/linux_status_" $SERVER "_compelet_io.cron.log" process_tm=$(date "+%Y-%m-%d %H:%M:%S" ) echo "磁盘IO|end: " $process_tm elif [ $i == 5 ] then #磁盘空间 DISKDATA=$(timeout 10 df -h) echo "$DISKDATA" >> "/home/log/crontab/linux_status_" $SERVER "_compelet_disk.cron.log" process_tm=$(date "+%Y-%m-%d %H:%M:%S" ) echo "磁盘空间|end: " $process_tm elif [ $i == 6 ] then #redis_h5 if [ $SERVER == "manager-admin" ]; then php /home/sh/linux_status/linux_status_redis.php $SERVER h5 fi process_tm=$(date "+%Y-%m-%d %H:%M:%S" ) echo "redis_h5|end: " $process_tm elif [ $i == 7 ] then #redis_admin if [ $SERVER == "manager-admin" ]; then php /home/sh/linux_status/linux_status_redis.php $SERVER admin fi process_tm=$(date "+%Y-%m-%d %H:%M:%S" ) echo "redis_admin|end: " $process_tm else echo "not known" $i fi echo >&0316 }& done wait # echo "linux_status_compelet" exec 0316<&- exec 0316>&- timemid=$(date "+%Y-%m-%d %H:%M:%S" ) echo "mid: " $timemid php /home/sh/linux_status/linux_status.php $SERVER $DEBUG timeend=$(date "+%Y-%m-%d %H:%M:%S" ) echo "end: " $timeend |
三 linux_status_redis.php、linux_status.php
分别为redis连接命令和对并发进程输出文件进行正则匹配,此处略
四 说明
- shell各个进程通信我暂时通过文本,效率低下,因为并发不大暂时未改进
- getopts获取调用脚本的参数-s servername -d 是否debug模式
- mkfifo filepath 创建命名管道,exec 0316<>/home/log/crontab/linux_status创建文件描述符并关联到管道文件
- echo >&0316 read -u0316 类似于golang、swoole的阻塞管道,做并发协程数控制的
- 循环体&为丢到子进程执行,wait等待所有子进程执行完毕,不wait则可能子进程未执行完而父进程直接end了
- exec 0316<&- 关闭文件描述符的写,exec 0316>&- 关闭读
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!