bosha/ptel

支持协商的 PHP telnet

dev-master 2015-03-18 12:02 UTC

This package is not auto-updated.

Last update: 2024-09-28 17:24:52 UTC


README

使用 PHP 编写的 Telnet 协议的另一种实现。这个类是为我的日常用例创建并使用的,因此可能包含错误。如果您发现了它们 - 提交问题,或者随时联系我。

安装

Composer

在项目根目录下运行以下命令

composer require "bosha/ptel": "dev-master"

或者手动添加到 composer.json 中

"require": {
    "bosha/ptel": "dev-master"
}

然后使用它

<?php

require_once(__DIR__."/../vendor/autoload.php");

$telnet = new PTel\PTel();

手动

导航到您的项目位置,并运行以下命令

git clone https://github.com/bosha/PTel.git
mv PTel PTel_orig
mv PTel_orig/src/PTel PTel
rm -rf PTel_orig

将其添加到您的代码中

<?php

require_once("PTel/PTel.php");
require_once("PTel/SocketClientException.php");
require_once("PTel/TelnetException.php");

$telnet = new PTel();

之后 - 您可以创建类的实例,并使用它。

使用 PTel

使用

创建新实例后,您需要连接到设备并登录

try {
  $telnet = new PTel();
  $telnet->connect("mysupercisco.hostname.com");
  $telnet->login("bosha", "mysupersecurepassword");
} catch (Exception $e) { print_r($e); }

登录成功后 - 您可以进行诸如从设备发送和接收信息等基本操作

$telnet->send("show version");
echo $telnet->recvAll();

还有一些额外的命令可能很有用

// Getting output of command:
$cisco_log = $telnet->getOutputOf("show logging");

// Searching for something in output stream to make application logic:
$telnet->send("copy running start");
if ($telnet->find("OK")) {
  echo "Configuration successful saved!"
}

// Some basic "expect" logic:
try {
  $telnet->send("enable");
  $telnet->expect('(P|p)ass((W|w)ord|)(:|)', "enablesecretpassword"); // Regular expressions supported
  if ($telnet->find("#")) {
    echo "Enable successful!"
  } else {
    echo "Looks like enable password are wrong!"
  }
} catch (Exception $e) {
    throw new BadPasswordException('Enable failed!');
}

// If you know that command execution can take a long - you can wait for some output from socket:
try {
  $telnet->send("copy running start");
  $telnet->waitReply(10); // Will not wait longer than 10 seconds
} catch (Exception $e) { print_r($e); }
// Or wait for some text. For example - prompt:
try {
  $telnet->send("copy running start");
  $telnet->waitFor($telnet->prompt); // $prompt - public variable with prompt
} catch (Exception $e) { print_r($e); }

通常,登录成功后,提示符将自动从设备输出中剪裁。当前提示符可以根据需要返回和更改

if ($telnet->getPrompt() !== ">#") {
  $telnet->setPrompt(">#");
}

提示符用于确定命令执行的结束,因此如果您使用诸如 getOutputOf - 您需要确保提示符已正确配置。

还可以指定一些额外的 telnet 协商选项

// Terminal speed
$telnet->setTermSpeed(38000, 38000);

// Terminal type
$telnet->setTerm("xterm);

如果设备使用一些不寻常的页面分隔符,可以通过更改 $page_delimiter 变量来指定它们。换行字符(回车)也可以通过更改 $retcarriage 变量来更改。

扩展

如果需要一些尚未实现的功能,或者为了满足您的需求重写现有方法,PTel 可以很容易地进行扩展。

class Cisco_Telnet extends PTel
{

  public function login($user, $pass, $timeout = 10) {
    try {
      $this->expect('CustomUserNameRequest:', $user);
      $this->expect('CustomPasswordRequest:', $pass);
    } catch (Exception $e) {
      throw new Exception('Could not find password request. Login failed.');
    }

    $timestart = time();
    $buff = '';
    while (true) {
      $buff = $this->recvLine();
      $timerun = time() - $timestart;

      if (preg_match("/wrong!)/i", $buff)) {
        throw new Exception("Username or password wrong! Login failed");
      }

      if (preg_match("/]>>>/", $buff)) {
        break;
      }

      if ($timerun >= $maxtimeout) {
        throw new Exception("Could not get reply from device. Login failed.");
      }
    }

    $lines = explode("\n", $this->getBuffer());
    $prompt = array_slice($lines, -1);
    $this->prompt = $prompt[0];
    return true;
  }
  
  public function enable($enpass) {
    try {
      $this->send("enable");
      $this->expect('EnablePasswordRequest:', "enablesecretpassword");
      if ($telnet->find("#")) {
        $lines = explode("\n", $this->getBuffer());
        $prompt = array_slice($lines, -1);
        $this->prompt = $prompt[0] 
      } else {
        throw new Exception("Login fail [ bad password ] !");
      }
    } catch (Exception $e) {
      throw new BadPasswordException('Enable failed!');
    }
  }

}