今日在公司项目中用到了自动运维的脚本,用来每分钟执行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中定时监控。