PHP скрипты управления по типу Telnet с использование БД Mysql
По многочисленым прозьбам , и в виду альтернативы отсутствия WiKi, а также как и обещал.
Выкладываю скрипты которые уже успешно работают. ( проверено на моделях DES 3526 & DGS 3324SR )
Немного описания , что и с чем едят.
Данные скрипты запускаются путем запуска BaseDemon.php из под консоли ( у меня он запускается как служба).
Работают с Mysql базой откуда берут команды , а также пишут логи о выполнении. Почему имено Mysql? -> ответ очевиден скрипты работают совместно с самописным биллингом , он в свою очередь и создаёт список команд.
Данное решение себя оправдывает , т.к не использует ни системные файлы ( как было в других решениях , типа telnet и прочего ) , не использует SNMP ( было уже доказано , что работает он немного медленее , а также нельзя многово выполнить ).
Т.е практически все что можно выполнять из под консоли можно выполнять и тут.
( неумею я расписывать описания и прочие , кто знает PHP тот всё поймёт надеюсь =) )
для начала нам необходимо создать 2 таблицы в Mysql ( можно и одну если логи не нужны )
если внимательно посмотреть то будет понятно , специально оставляю кусочек логов и одну из комманд ( ps свичи привязаны по dns поэтому их ip нет )
Mysql Таблица с командами.
Код:
CREATE TABLE `nbotu_comander` (
`id` int(100) unsigned NOT NULL auto_increment,
`comanda` text,
`action` varchar(255) default '0',
`router` varchar(80) default '0',
`router_ip` varchar(15) default NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251;
INSERT INTO `nbotu_comander` (`id`, `comanda`, `action`, `router`, `router_ip`) VALUES("218208", "config access_profile profile_id 100 delete access_id 2149 ", "Удаление ACL <b>2149</b> с маком <b>00-15-58-3E-79-51</b> port 9", "sw.pm14.lan", "172.22.5.254");
Таблица с логами.Код:
CREATE TABLE `nbotu_comand_complete` (
`id` int(100) unsigned NOT NULL auto_increment,
`comanda` text,
`action` text,
`router` varchar(80) default NULL,
`time` varchar(15) default NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251;
INSERT INTO `nbotu_comand_complete` (`id`, `comanda`, `action`, `router`, `time`) VALUES("9709", NULL, "Command: config access_profile profile_id 100 delete access_id 717 --> Success. ", "sw.pm14.lan", "1182602051");
INSERT INTO `nbotu_comand_complete` (`id`, `comanda`, `action`, `router`, `time`) VALUES("9710", NULL, "Command: save --> Saving all configurations to NV-RAM... 0 %[5D 35 %[5D 45 %[5D 70 %[5D 70 %[5D 85 %[5D 95 %[5D100 %[5D100 %[5DDone. ", "sw.pm14.lan", "1182602177");
INSERT INTO `nbotu_comand_complete` (`id`, `comanda`, `action`, `router`, `time`) VALUES("9732", NULL, "Command: clear arptable\n --> Success. \n", "sw.core.lan", "1182641341");
далее сами скрипты , попорядку :
Демон который мы запускаем , он читает базу каждый раз и передаёт команды управляющему скрипту ( он ниже ).
PHP Демон. BaseDemon.phpКод:
<?php
/*
================================================================================
// O.S.D. PHP Bot
================================================================================
// Script name: PHP BASE DEAMON Bot
//
// This program is free software. You can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation.
//
// Перед запуском положите скрипт в папку с php
// Запуск бота происходит из коммандной оболочки примерно так:
// e:\servers\php\php.exe bot.php
================================================================================
//
// Powered by OSD Team (c) 2004-2006
//
================================================================================
*/
include "mysql.php";
$DB = new mysql;
include "swbot.php";
class Daemon
{
private $sw_on = true;
// переменые для подклюений к mysql
private $timeout_sw_data = 60;
private $lasttime_sw_data = 0;
public $lasttime = 0;
private $timeout = 30;
public $save_lasttime = array();
public $save_timeout = 7200;
// Переменные для работы с памятью и базой.
private $last_id = 0;
private $time = 1;
public $debug = false;
public function _construct()
{
$this->lastitme = time();
$this->lasttimedata = time();
}
public function run()
{
global $DB;
print "\n\n
+-----------------+
| NBOTU DAEMON |
|-----------------|
| Powered by: |
| Kair.Net |
|-----------------|
| (c) 2005-2007 |
+-----------------+
";
$exit = 0;
echo "start While \n";
while($exit==0)
{
set_time_limit(2400);
$lt = $this->lasttime+$this->timeout;
$t = time();
if($lt < $t)
{
$this->lasttime = time();
// $this->GetARP_Data();
// $this->GetDHCP_Data();
// $this->GetDNS_Data();
$this->GetSW_Data();
// $this->sysmsg($read);
}
$DB->close_db();
sleep($this->timeout);
}
echo "End While \n";
$DB->close_db();
sleep(10);
}
//=====================================================
private function GetSW_Data()
{
global $DB,$SWBOT;
$lt = $this->save_lasttime['sw.core.lan']+$this->save_timeout;
$t = time();
if($lt < $t)
{
$this->save_lasttime['sw.core.lan'] = time();
echo "start Insert ".$this->save_lasttime['sw.core.lan']." \n";
$DB->query("INSERT INTO nbotu_comander (comanda, action, router) values ('clear arptable \n','clear arptable','sw.core.lan')");
}
$lt = $this->lasttime_sw_data+$this->timeout_sw_data;
$t = time();
if($lt < $t)
{
$this->lasttime_sw_data = time();
if(!$DB->ping())
{
$this->sysmsg("Reconect DB");
$DB->obj = array( 'sql_host' => "nbotu.billing",
'sql_user' => "billing",
'sql_password' => "password",
'sql_db' => "nbotu"
);
$DB->connect();
}
}
if($DB->ping() && $lt < $t && $this->sw_on)
{
$query = $DB->query("SELECT * FROM `nbotu_comander` Where router LIKE 'sw.%.lan' GROUP by router ORDER BY id ASC ");
if($DB->num_rows($query) != 0)
{
$n=0;
$shel_while="";
while ($row = $DB->fetch_array($query))
{
$cmd = '';
$swip = $row['router'];
set_time_limit(180);
$SWBOT = new Bot();
$SWBOT->ip = $swip;
$q = $DB->query("SELECT * FROM `nbotu_comander` Where router = '{$swip}' ORDER BY id ASC ");
while ($res = $DB->fetch_array($q))
{
$cmd .= $res['comanda']."\n";
$n++;
$SWBOT->qid[]=$res['id'];
//$DB->query("DELETE FROM nbotu_comander WHERE id=$res[id]");
}
$lt = $this->save_lasttime[$swip]+$this->save_timeout;
$t = time();
if($lt < $t)
{
$this->save_lasttime[$swip] = time();
echo "start Insert ".$this->save_lasttime[$swip]." \n";
$DB->query("INSERT INTO nbotu_comander (comanda, action, router) values ('save \n','save cf ".time()."','{$row['router']}')");
}
$out=$SWBOT->run($cmd);
unset($SWBOT);
}
$this->sysmsg("Исполнение $n SW запросов");
$actions = 'Обработка '.$n.' SW записей'."\n";
}
$this->sysmsg("SW аписей нет");
}
}
public function sysmsg($msg)
{
echo date("[H:i:s]").": ". convert_cyr_string($msg, 'w - windows-1251','d - x-cp866' )."\n";
}
}
$Daemon = new Daemon();
$Daemon->run();
?>
собственно сам управляющий скрипт , получает команды , подключается к свичам ( авторизуется ) , исполняет команды и пишет в лог.
Скрипт подключения к свичу. swbot.phpКод:
<?php
//include "mysql.php";
//$DB = new mysql;
class Bot
{
// Основные свойства.
public $login = 'admin'; // логин
public $pass = 'password'; // пароль
// Открытые свойства для работы с сокетами.
public $host = '';
public $port = 23;
public $ip = '';
public $qid=array();
// Закрытые свойства для работы с сокетами.
private $sock;
private $buffer = '';
private $lenght = 0;
private $soctimeout = 600;
// Переменные для работы с памятью и базой.
private $time = 1;
private $lasttime = 0;
public $debug =false; //true ; //
public function _construct()
{
$this->lastitme = time();
$this->lasttimetopicconec = time();
}
public function run($acl)
{
global $DB;
print "\n\n
+-----------------+
| Switch PHP Bot |
|-----------------|
| Powered by: |
| Vano™ |
|-----------------|
| (c) 2007 |
+-----------------+
";
if($this->connect()!=false)
{
$exit = 0;
while($exit==0)
{
sleep(1);
if(!$this->Login())
{
print "FAIL! \n";
break;
}
$this->SockWrite("disable clipaging \n");
/* //пример ACL
$acl ='
config access_profile profile_id 100 add access_id 10 ethernet source_mac 00-E0-91-0B-2B-D3 port 24 permit
config access_profile profile_id 100 delete access_id 10
config access_profile profile_id 100 delete access_id 23
';*/
$this->SockWrite($acl."\n");
$this->SockWrite("logout \n");
sleep(90);
set_time_limit(60);
$read = @socket_read($this->sock,10240,PHP_BINARY_READ);
echo "start While \n";
$this->sysmsg($read);
$this->get_console($read);
//$GetCmd->GetServerCMD($read);
sleep(1);
foreach($this->qid as $k=>$v)
{
$DB->query("DELETE FROM nbotu_comander WHERE id=$v");
}
echo "end \n";
break;
}
//$DB->close_db();
$this->SockClose();
}
else{echo "Not Connect \n";}
}
//=====================================================
private function connect()
{
$this->SockCreate() or die('Cant Create');
//=====================PRINT===========================
print "-------------------\nConnecting to server... ({$this->ip}:{$this->port})\n-------------------\n";
//=====================================================
if(!$this->SockConnect()) return false;
sleep(3);
$read = $this->SockRead(1024,PHP_BINARY_READ);
//=====================PRINT===========================
print "----Server:--------\n{$read}\n-------------------\n\n";
//=====================================================
print "Ready.\n";
echo "-------------------\n";
return true;
}
private function SockCreate()
{
$this->sock = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
socket_set_option($this->sock,SOL_SOCKET,SO_RCVTIMEO,array("sec"=>$this->soctimeout,"usec"=>0));
return $this->sock;
}
private function SockBind()
{
$this->sock = socket_bind($this->sock,'172.22.100.1',6667);
}
private function SockConnect()
{
return @socket_connect($this->sock, $this->ip, $this->port);
}
private function SockRead($limit,$flag)
{
$read = socket_read($this->sock,$limit,$flag);
return trim($read);
}
public function SockWrite($buffer)
{
$this->buffer = $buffer;
$this->lenght = strlen($this->buffer);
return socket_write($this->sock, $this->buffer,$this->lenght);
}
private function SockClose()
{
return socket_close($this->sock);
}
private function Login()
{
$this->SockWrite("{$this->login}\n");
while($read = @socket_read($this->sock,1024,PHP_BINARY_READ))
{
$readarr = explode("\r",$read);
foreach($readarr as $nread)
{
$parent ="/^(username|password|fail!|^D[EG]S-[0-9SR]{4,6}):?[0-9]*#?/is";
if(preg_match_all($parent,$nread, $matches))
{
switch(strtolower($matches[1][0]))
{
case 'username':
$this->SockWrite("{$this->login}\n");
print "----LOGIN:--------\n";
break;
case 'password':
$this->SockWrite("{$this->pass}\n");
print "----PASS:---------\n";
break;
case 'fail!':
print "----Fail Login:--------\n";
$if++;
if($if==3){return false;}
break;
case 'des-3526':
case 'des-3550':
case 'dgs-3324sr':
print "----Login OK:--------\n";
return true ;
break;
default:
break;
}
}
}
}
}
public function get_console($msg)
{
global $DB;
$parent ="/([A-Z0-9\-]+\:[\d]?#)/is";
$msg = preg_replace($parent,'[razdelitel]',$msg);
$cmdarray = explode('[razdelitel]',$msg);
foreach($cmdarray as $k=>$v)
{
//echo $v."-------------------------------------";
$subarray = explode("\r",$v);
foreach($subarray as $k=>$v)
{
$v = str_replace("\r",'',$v);
$v = str_replace("\n",'',$v);
if($v=='') unset($subarray[$k]);
}
$newsubarray = '';
foreach($subarray as $k=>$v) $newsubarray[] = $subarray[$k];
$cnt = count($newsubarray);
$cnt--;
$out[] = array($newsubarray[$cnt-1],$newsubarray[$cnt]);
}
unset($out[count($out)-1]);
unset($out[count($out)-1]);
unset($out[0]);
foreach($out as $k=>$v)
if($v[0]=='' && $v[1]=='') unset($out[$k]);
foreach($out as $k=>$v)
{
$DB->query("INSERT INTO `nbotu_comand_complete` ( `action`,`router`,`time`) values ('{$v[0]} --> {$v[1]}','{$this->ip}','".time()."')");
// return $v[0].' --> '.$v[1]."\n";
}
}
public function sysmsg($msg)
{
echo date("[H:i:s]").": ". convert_cyr_string($msg, 'w - windows-1251','d - x-cp866' )."\n";
}
}
//$SWBOT = new Bot();
?>
На всякий случай наипростейший mysql клас.
Mysql класс. mysql.phpКод:
<?php
/*
================================================================================
// Powered by OSD Team Web Portal System v 1.0.2
================================================================================
// Script name: MySQL file
// Script file name: mysql.php
// Script Author: Dexter
// Date: 02/03/2005
//
// This program is free software. You can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation.
//
//
// На территории Российской Федерации порядок воспроизведения,
// распространения и модификации программного обеспечения регулируется
// Законом РФ "О правовой охране программ для ЭВМ и баз данных" от 23.09.1992г.
// N 3523-1 и Законом РФ "Об авторском праве и смежных правах" от 09.07.1993г.
// N 5351-1.
//
================================================================================
//
// Powered by OSD Team (c) 2004-2006
//
================================================================================
*/
//==============================================================================
// Класс для работы с базой данных MySQL приделан к Daemon PHPBOT
//==============================================================================
class mysql
{
var $obj=array( 'sql_host' => "",
'sql_user' => "root",
'sql_password' => "",
'sql_db' => ""
);
var $connection_id = "";
var $query_str = "";
var $f_array = array();
var $f_row = array();
var $total_query = "0";
//--------------------------------------------------------------------------
// Функция для подключения к базе данных MySQL
//--------------------------------------------------------------------------
function connect()
{
global $Daemon;
$this->connection_id = @mysql_connect( $this->obj["sql_host"],
$this->obj["sql_user"],
$this->obj["sql_password"]
);
if ( !@mysql_select_db($this->obj['sql_db'], $this->connection_id) )
{
$Daemon->sysmsg( "ОШИБКА: Не могу присоединится к базе ".$this->obj['sql_db'] );
}
}
public function ping()
{
return @mysql_ping($this->connection_id);
}
//--------------------------------------------------------------------------
// Функция запроса к базе данных MySQL
//--------------------------------------------------------------------------
function query( $query )
{
global $Daemon;
$this->query_str = @mysql_query( $query , $this->connection_id );
$this->total_query = $this->total_query + 1;
if( !$this->query_str )
{
$Daemon->sysmsg( "ОШИБКА: Не могу выполнить запрос ".$this->query_str.mysql_error()."\n Запрос: ".$query );
}
return $this->query_str;
}
//--------------------------------------------------------------------------
// Функция получения массива результата
//--------------------------------------------------------------------------
function fetch_array($query_str = "")
{
if ($query_str == "")
{
$query_str = $this->query_str;
}
$this->f_array = mysql_fetch_array($query_str);
return $this->f_array;
}
//--------------------------------------------------------------------------
// Функция получения массива результата без имен.
//--------------------------------------------------------------------------
function row($query_str = "")
{
if ($query_str == "")
{
$query_str = $this->query_str;
}
$this->f_row = mysql_fetch_row($query_str);
return $this->f_row;
}
//--------------------------------------------------------------------------
// Функция получения кол-ва полей таблицы
//--------------------------------------------------------------------------
function num_rows()
{
return mysql_num_rows( $this->query_str );
}
//--------------------------------------------------------------------------
// Функция получения последнего уникального ID
//--------------------------------------------------------------------------
function insert_id()
{
return mysql_insert_id();
}
//--------------------------------------------------------------------------
// Функция для отключения от MySQL
//--------------------------------------------------------------------------
function close_db()
{
return @mysql_close($this->connection_id);
}
}
?>
Вобщемто пока всё , выложил как есть , хотя хотел доработать.
Если кто-то хочет помочь в разработке всегда рад , а также если вы хотите внести изменения , напишите какие и для чего , возможно я вам не дам наступить на уже существующие грабли, а также хочу развить проект до нормального состояния и возмжно даже статьи для Faq.
Напишу сразу Использовать PHP 5 !!!!
На вопросы у меня не работает отвечу , неверю т.к см. строку №3 данного сообщения !