使用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>&- 关闭读

 

posted @   布叔喂丶  阅读(83)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示