今日在公司项目中用到了自动运维的脚本,用来每分钟执行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 [email protected] 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("sysn"); echo $telnet->read_till("]"); $telnet->write("dis this | inc ip route-static vpn-instance baishanyunn"); 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("commitn"); 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中定时监控。
评论已关闭