标签: 交换机Switch

  • Linux系统中使用PHP脚本定时监控交换机端口流量并添加删除修改交换机规则控制流量

    Linux系统中使用PHP脚本定时监控交换机端口流量并添加删除修改交换机规则控制流量

    今日在公司项目中用到了自动运维的脚本,用来每分钟执行php脚本监控交换机,如果交换机流量过大则添加出口,如果过小则减少出口。用到了一些技术性的东西。

    具体代码实例如下:

    <?php
    /**********************************************
     * 监听交换机端口流量并切换规则
     * 当端口流量大于阀值则顺序执行A系列命令
     * 当端口流量小于阀值则倒序执行B系列命令
     * Author:Jerry
     * EMail : admin#laoji.org
     * Data :2019/5/30
     ***********************************************/
    //  开始运行脚本预输出
    $stime=microtime(true); 
    echo str_repeat('-', 120).PHP_EOL;
    ini_set('date.timezone','Asia/Shanghai');
    echo '当前时间:'.date("Y-m-d H:i:s").PHP_EOL;
    //  执行命令得出端口流量值
    $cmd = '/usr/bin/snmpwalk -v2c -c power@idc 192.168.108.108 1.3.6.1.2.1.31.1.1.1.10.5';
    //  流量阀值
    $valve = '1000';
    // 交换机信息配置
    $ip = '192.168.108.108';
    $port = '23';
    $user = 'puer';
    $passwd = 'puer123';
    
    //  命令集,cmdA 添加规则集,cmdD删除规则集
    $cmdA = array(
        array(  'ip route-static vpn-instance baishanyun2041 0.0.0.0 0.0.0.0 192.168.108.137 public description UPLINK-20180525',
                'ip route-static vpn-instance baishanyun2041 0.0.0.0 0.0.0.0 192.168.108.141 public description UPLINK-20180525'
            ),
        array(  'ip route-static vpn-instance baishanyun1029 0.0.0.0 0.0.0.0 192.168.108.137 public description UPLINK-20180525',
                'ip route-static vpn-instance baishanyun1029 0.0.0.0 0.0.0.0 192.168.108.141 public description UPLINK-20180525'
            ),
        array(  'ip route-static vpn-instance baishanyun1030 0.0.0.0 0.0.0.0 192.168.108.137 public description UPLINK-20180525',
                'ip route-static vpn-instance baishanyun1030 0.0.0.0 0.0.0.0 192.168.108.141 public description UPLINK-20180525'
            ),
        array(  'ip route-static vpn-instance baishanyun1033 0.0.0.0 0.0.0.0 192.168.108.137 public description UPLINK-20180525',
                'ip route-static vpn-instance baishanyun1033 0.0.0.0 0.0.0.0 192.168.108.141 public description UPLINK-20180525'
            )    
    );
    $cmdD = array(
        array(  'UNDO ip route-static vpn-instance baishanyun2041 0.0.0.0 0.0.0.0 192.168.108.137 public',
                'UNDO ip route-static vpn-instance baishanyun2041 0.0.0.0 0.0.0.0 192.168.108.141 public'
            ),
        array(  'UNDO ip route-static vpn-instance baishanyun1029 0.0.0.0 0.0.0.0 192.168.108.137 public',
                'UNDO ip route-static vpn-instance baishanyun1029 0.0.0.0 0.0.0.0 192.168.108.141 public'
            ),
        array(  'UNDO ip route-static vpn-instance baishanyun1030 0.0.0.0 0.0.0.0 192.168.108.137 public',
                'UNDO ip route-static vpn-instance baishanyun1030 0.0.0.0 0.0.0.0 192.168.108.141 public'
            ),
        array(  'UNDO ip route-static vpn-instance baishanyun1033 0.0.0.0 0.0.0.0 192.168.108.137 public',
                'UNDO ip route-static vpn-instance baishanyun1033 0.0.0.0 0.0.0.0 192.168.108.141 public'
            ),
    );
    
    //  获取当前流量值
    $return = explode(':', shell_exec($cmd) );
    $traffic = trim($return[count($return) - 1]);
    
    //  开始登录交换机
    $telnet = new telnet("{$ip}", "{$port}");
    echo $telnet->read_till("login: ");
    $telnet->write("{$user}\n");
    echo $telnet->read_till("password: ");
    $telnet->write("{$passwd}\n");
    echo $telnet->read_till(">");
    //echo $telnet->read_till(":> ");
    $telnet->write("sys\n");
    echo $telnet->read_till("]");
    $telnet->write("dis this | inc ip route-static vpn-instance baishanyun\n");
    echo $config = $tmp = $telnet->read_till("]");
    //  获取交换机全部配置
    while( strpos($tmp,'---- More ----') !== false ){
        $telnet->write(" \n"); 
        echo $config .= $tmp = $telnet->read_till("]");
    }
    $traffic = '2000';
    $needCommit = 0 ;
    $cmdAry = array();
    $return = '';
    if( $traffic >= $valve){//流量大于阀值
        $return .= '流量大于阀值'.PHP_EOL;
        $cmdAry = $cmdA;
        for($i=0;$i<count($cmdAry);$i++){
            for( $j=0;$j<count($cmdAry[$i]);$j++){
                if(strpos($config, $cmdAry[$i][$j]) !== false ){
                    $return .=  '规则已存在'.$j.'#'.$i.':'.$cmdAry[$i][$j].PHP_EOL;
                }else{
                    echo $telnet->write($cmdAry[$i][$j]."\n");
                    echo $telnet->read_till("]");
                    $needCommit = 1;
                    $return .= '规则已写入'.$j.'#'.$i.':'.$cmdAry[$i][$j].PHP_EOL;
                    if( $j == (count($cmdAry[$i])-1)){  
                        break 2;
                    }
                    
                }
            }        
        }  
    }else{
        $return .= '流量小于阀值'.PHP_EOL;
        $cmdAry = $cmdD;
        $num = count( $cmdAry ) - 1;
        for( $i=$num;$i>=0;$i--){
            for( $j=0;$j<count($cmdAry[$i]);$j++){
                if( strpos($config, str_replace('UNDO ', '', $cmdAry[$i][$j])) !== false ){
                    $telnet->write($cmdAry[$i][$j]."\n");
                    echo $telnet->read_till("]");        
                    $needCommit = '1';
                    $return .= '规则需删除'.$j.'#.'.$i.':'.$cmdAry[$i][$j].PHP_EOL;      
                    if( $j == (count($cmdAry[$i])-1) ){
                        $goBreak = 1;
                        break 2;
                    }
                }else{
                    $return .= '没有匹配到规则'.$j.'#'.$i.':'.$cmdAry[$i][$j].PHP_EOL;
                }
            
            }
        }
    }
    //  提交commit生效
    if( $needCommit ){
        $telnet->write("commit\n");
        echo $telnet->read_till(']');
        $return .= '规则已commit'.PHP_EOL;
    }
        
     
    echo $telnet->close();
    echo $return;
    
    class Telnet {
        var $sock = NULL;
        function telnet($host,$port) {
            $this->sock = fsockopen($host,$port);
            socket_set_timeout($this->sock,2,0);
        }
        function close() {
            if ($this->sock)  fclose($this->sock);
            $this->sock = NULL;
        }
        function write($buffer) {
            $buffer = str_replace(chr(255),chr(255).chr(255),$buffer);
            fwrite($this->sock,$buffer);
        }
        function getc() {
            return fgetc($this->sock);
        }
        function read_till($what) {
            $buf = '';
            while (1) {
                $IAC = chr(255);
                 
                $DONT = chr(254);
                $DO = chr(253);
                 
                $WONT = chr(252);
                $WILL = chr(251);
                 
                $theNULL = chr(0);
                $c = $this->getc();
                 
                if ($c === false) return $buf;
                if ($c == $theNULL) {
                    continue;
                }
                // if ($c == "1") {
                // continue;
                // }
                if ($c != $IAC) {
                    $buf .= $c;
                    if ($what == (substr($buf,strlen($buf)-strlen($what)))) {
                        return $buf;
                    }
                    else {
                        continue;
                    }
                }
                $c = $this->getc();
                 
                if ($c == $IAC) {
                    $buf .= $c;
                }
                else if (($c == $DO) || ($c == $DONT)) {
                    $opt = $this->getc();
                    // echo "we wont ".ord($opt)."\n";
                    fwrite($this->sock,$IAC.$WONT.$opt);
                }
                elseif (($c == $WILL) || ($c == $WONT)) {
                    $opt = $this->getc();
                    // echo "we dont ".ord($opt)."\n";
                    fwrite($this->sock,$IAC.$DONT.$opt);
                }
                else {
                    // echo "where are we? c=".ord($c)."\n";
                }
            }
        }
    }
    
    $etime=microtime(true);//获取程序执行结束的时间
    $total=$etime-$stime;  //计算差值
    echo PHP_EOL."执行时间:{$total} 秒".PHP_EOL;

    脚本中会自动读取交换机当前配置,并且根据 ---- More ---- 自动输入空格分屏获取全部配置。本需求中cmdA按顺序执行,cmdD则按倒序执行。

    本脚本中可以放置在crontab中定时监控。

WeChat