Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Um dos padrões de projeto mais legais é o State, com ele, um objeto pode mudar seu comportamento em tempo de execução dependendo do estado corrente e cada implementação de estado preocupa-se apenas com o que deve fazer, deixando assim um código limpo e totalmente reutilizável.
/applications/core/interface/imageproxy/imageproxy.php?img=http://www.visualcom.com.br/tutoriais/diagramas/State.png&key=a0878c3fa679907addb626eaff31f303c675b6cc89e91bb64d7e6ead9defa774" alt="Imagem Postada" class="bbc_img">
Cada ConcreteState implementa um comportamento específico permitindo, dessa forma, que novos comportamentos sejam anexados.
No caso de uma conexão SSH:
/applications/core/interface/imageproxy/imageproxy.php?img=http://www.visualcom.com.br/tutoriais/diagramas/SSHState.png&key=fa3f351ce22457b6a38319cca7cac8f2d13345153cd10c301d249c6059588c77" alt="Imagem Postada" class="bbc_img">
Nosso contexto inicia-se como SSHStateClosed, assim que executamos o método open() nosso estado passa a ser SSHStateEstabilished e podemos verificar a assinatura do host e autenticar; Assim que autenticado o estado passa à SSHStateListen para que possamos enviar comandos ao servidor remoto.
Como uma autenticação pode ser de várias formas, deixamos a implementação separada em um objeto específico, dessa forma, podemos autenticar com usuário e senha ou, se for o caso, utilizando certificados digitais (entre outras).
Um comando deveria ser implementado da mesma forma, porém, para simplificar as coisas, vamos trabalhar com strings mesmo:
com/ssh/auth/SSHAuthenticatePassword.php
<?php
/**
* @author João Batista Neto
* @package ssh
* @category ssh, state
*/
namespace comsshauth;
/**
* @see ISSHAuthentication
*/
use comsshinterfacesISSHAuthentication;
/**
* Implementa uma autenticação utilizando nome de usuário e senha
* @author João Batista Neto
* @final
* @package ssh
* @category ssh, state, authentication
*/
final class SSHAuthenticatePassword implements ISSHAuthentication {
/**
* @var string
*/
private $user;
/**
* @var string
*/
private $pswd;
/**
* Constroi o objeto de autenticação
* @param string $user
* @param string $pswd
*/
public function __construct( $user , $pswd ){
$this->user =& $user;
$this->pswd =& $pswd;
}
/**
* Efetua a autenticação
* @param resource $resource
* @throws InvalidArgumentException se o recurso não for válido
*/
public function authenticate( &$resource ){
if ( is_resource( $resource ) ){
return ssh2_auth_password( $resource , $this->user , $this->pswd );throw new InvalidArgumentException( 'Recurso inválido.' );
}
return false;
}
/**
* Recupera o nome do usuário
* @return string
*/
public function getUser(){
return $this->user;
}
}
com/ssh/interfaces/AbstractSSHState.php
<?php
/**
* @author João Batista Neto
* @package ssh
* @subpackage interfaces
* @category ssh, state
*/
namespace comsshinterfaces;
/**
* Interface para um estado de conexão
* @abstract
* @author João Batista Neto
* @package ssh
* @subpackage interfaces
* @category ssh, state
*/
abstract class AbstractSSHState implements ISSHState {
/**
* @var resource
*/
protected $resource;
/**
* Autentica o usuário
* @param ISSHAuthentication $auth
* @param ISSHConnection $context
* @return boolean
* @throws BadMethodCallException se o estado não implementar o método authenticate
*/
public function authenticate( ISSHAuthentication $auth , ISSHConnection $context ){
throw new BadMethodCallException( sprintf( '%s não implementa o método %s' , get_class( $this ) , __METHOD__ ) );
}
/**
* Executa um comando no servidor remoto
* @param string $command
* @param ISSHConnection $context
* @return boolean
* @throws BadMethodCallException se o estado não implementar o método execute
*/
public function execute( $command , ISSHConnection $context ){
throw new BadMethodCallException( sprintf( '%s não implementa o método %s' , get_class( $this ) , __METHOD__ ) );
}
/**
* Recupera a fingerprint do servidor
* @param ISSHConnection $context
* @return string
* @throws BadMethodCallException se o estado não implementar o método execute
*/
public function getFingerprint( ISSHConnection $context ){
throw new BadMethodCallException( sprintf( '%s não implementa o método %s' , get_class( $this ) , __METHOD__ ) );
}
/**
* Abre uma nova conexão
* @param string $host
* @param integer $port
* @param ISSHConnection $context
* @return boolean
* @throws BadMethodCallException se o estado não implementar o método open
*/
public function open( $host , $port = 22 , ISSHConnection $context ){
throw new BadMethodCallException( sprintf( '%s não implementa o método %s' , get_class( $this ) , __METHOD__ ) );
}
/**
* Define o recurso da conexão
* @param resource $resource
* @throws InvalidArgumentException se o recurso não for válido
*/
public function setResource( &$resource ){
if ( !is_resource( $resource ) ){
throw new InvalidArgumentException( 'Recurso inválido.' );
} else {
$this->resource =& $resource;
}
}
}
com/ssh/interfaces/ISSHAuthentication.php
<?php
/**
* @author João Batista Neto
* @package ssh
* @subpackage interfaces
* @category ssh, state
*/
namespace comsshinterfaces;
/**
* Interface para autenticação SSH
* @author João Batista Neto
* @package ssh
* @subpackage interfaces
* @category ssh, state
*/
interface ISSHAuthentication {
/**
* Efetua a autenticação do usuário
* @param resource $resource
*/
public function authenticate( &$resource );
/**
* Recupera o nome do usuário
* @return string
*/
public function getUser();
}
com/ssh/interfaces/ISSHConnection.php
<?php
/**
* @author João Batista Neto
* @package ssh
* @subpackage interfaces
* @category ssh, state
*/
namespace comsshinterfaces;
/**
* Interface para uma conexão SSH
* @author João Batista Neto
* @package ssh
* @subpackage interfaces
* @category ssh, state
*/
interface ISSHConnection {
/**
* Autentica um usuário
* @param ISSHAuthentication $auth
* @return boolean
*/
public function authenticate( ISSHAuthentication $auth );
/**
* Executa um comando no servidor remoto
* @param string $command
* @return boolean
*/
public function execute( $command );
/**
* Recupera a fingerprint do servidor
* @return string
*/
public function getFingerprint();
/**
* Abre uma nova conexão
* @param stirng $host
* @param integer $port
* @return boolean
*/
public function open( $host , $port );
/**
* Modifica o estado da conexão
* @param ISSHState $state
*/
public function changeState( ISSHState $state );
}
com/ssh/interfaces/ISSHState.php
<?php
/**
* @author João Batista Neto
* @package ssh
* @subpackage interfaces
* @category ssh, state
*/
namespace comsshinterfaces;
/**
* Interface para um estado de conexão
* @author João Batista Neto
* @package ssh
* @subpackage interfaces
* @category ssh, state
*/
interface ISSHState {
/**
* Autentica o usuário
* @param ISSHAuthentication $auth
* @param ISSHConnection $context
*/
public function authenticate( ISSHAuthentication $auth , ISSHConnection $context );
/**
* Executa um comando no servidor remoto
* @param string $command
* @param ISSHConnection $context
*/
public function execute( $command , ISSHConnection $context );
/**
* Recupera a fingerprint do servidor
* @param ISSHConnection $context
* @return string
*/
public function getFingerprint( ISSHConnection $context );
/**
* Abre uma nova conexão
* @param string $host
* @param integer $port
* @param ISSHConnection $context
*/
public function open( $host , $port = 22 , ISSHConnection $context );
/**
* Define o recurso da conexão
* @param resource $resource
*/
public function setResource( &$resource );
}
com/ssh/state/SSHStateClosed.php
<?php
/**
* @author João Batista Neto
* @package ssh
* @category ssh, state
*/
namespace comsshstate;
/**
* @see AbstractSSHState
*/
use comsshinterfacesAbstractSSHState;
/**
* @see ISSHConnection
*/
use comsshinterfacesISSHConnection;
/**
* Implementa o estado para uma conexão fechada
* @author João Batista Neto
* @final
* @package ssh
* @category ssh, state
*/
final class SSHStateClosed extends AbstractSSHState {
/**
* @staticvar
* @var ISSHConnection
*/
static private $context;
/**
* Abre uma nova conexão
* @param string $host
* @param integer $port
* @param ISSHConnection $context
* @return boolean
* @throws RuntimeException se não for possível estabelecer a conexão
* @uses SSHStateEstabilished
*/
public function open( $host , $port = 22 , ISSHConnection $context ){
$resource = ssh2_connect( $host , $port , array(
'disconnect' => array( 'SSHStateClosed' , 'disconnect' )
) );
if ( !is_resource( $resource ) ){
throw new RuntimeException( 'Não foi possível estabelecer a conexão.' );
} else {
$estabilished = new SSHStateEstabilished();
$estabilished->setResource( $resource );
self::$context =& $context;
self::$context->changeState( $estabilished );
}
return true;
}
/**
* Muda o estado da conexão para SSHStateClosed caso o servidor envie um disconnect
* @static
*/
static public function disconnect(){
self::$context->changeState( new SSHStateClosed() );
}
}
com/ssh/state/SSHStateEstabilished.php
<?php
/**
* @author João Batista Neto
* @package ssh
* @category ssh, state
*/
namespace comsshstate;
/**
* @see AbstractSSHState
*/
use comsshinterfacesAbstractSSHState;
/**
* @see ISSHConnection
*/
use comsshinterfacesISSHConnection;
/**
* @see ISSHAuthentication
*/
use comsshinterfacesISSHAuthentication;
/**
* Implementa o estado para uma conexão estabelecida
* @author João Batista Neto
* @final
* @package ssh
* @category ssh, state
*/
final class SSHStateEstabilished extends AbstractSSHState {
/**
* Efetua a autenticação do usuário
* @param ISSHAuthentication $auth
* @param ISSHConnection $context
* @return boolean
* @throws RuntimeException se não for possível autenticar o usuário
* @uses SSHStateAuthenticated
*/
public function authenticate( ISSHAuthentication $auth , ISSHConnection $context ){
if ( !$auth->authenticate( $this->resource ) ){
throw new RuntimeException( sprintf( 'Não foi possível autenticar o usuário %s.' , $auth->getUser() ) );$authenticated = new SSHStateListen();
$authenticated->setResource( $this->resource );
$context->changeState( $authenticated );
}
return true;
}
/**
* Recupera o hash da chave do servidor da conexão ativa
* @return string
* @throws LogicException se o estado não implementar o método execute
*/
public function getFingerprint( ISSHConnection $context ){
return ssh2_fingerprint( $this->resource , SSH2_FINGERPRINT_MD5 | SSH2_FINGERPRINT_HEX );
}
}
com/ssh/state/SSHStateListen.php
<?php
/**
* @author João Batista Neto
* @package ssh
* @category ssh, state
*/
namespace comsshstate;
/**
* @see AbstractSSHState
*/
use comsshinterfacesAbstractSSHState;
/**
* @see ISSHConnection
*/
use comsshinterfacesISSHConnection;
/**
* Implementa o estado para uma conexão autenticada
* @author João Batista Neto
* @final
* @package ssh
* @category ssh, state
*/
final class SSHStateListen extends AbstractSSHState {
/**
* @var resource
*/
private $shell;
/**
* Executa um comando no servidor remoto
* @param string $command
* @param ISSHConnection $context
* @return string A saída do servidor remoto
* @throws RuntimeException se não for possível executar o comando
*/
public function execute( $command , ISSHConnection $context ){
$ret = null;
$stream = ssh2_exec( $this->resource , $command );
if ( is_resource( $stream ) ){
stream_set_blocking( $stream , true );
while ( ( $line = fgets( $stream , 4096 ) ) !== false ){
$ret .= $line;
}throw new RuntimeException( 'Não foi possível executar o comando.' );
}
return $ret;
}
}
com/ssh/SSHConnection.php
<?php
/**
* @author João Batista Neto
* @package ssh
* @category ssh, state
*/
namespace comssh;
/**
* @see ISSHConnection
*/
use comsshinterfacesISSHConnection;
/**
* @see ISSHAuthentication
*/
use comsshinterfacesISSHAuthentication;
/**
* @see ISSHState
*/
use comsshinterfacesISSHState;
/**
* @see SSHStateClosed
*/
use comsshstateSSHStateClosed;
/**
* Implementa uma conexão com um servidor remoto via SSH
* @author João Batista Neto
* @final
* @package ssh
* @category ssh, state
*/
class SSHConnection implements ISSHConnection {
/**
* @var ISSHState
*/
private $state;
/**
* Cria o objeto de conexão
*/
public function __construct(){
$this->state = new SSHStateClosed();
}
/**
* Faz a autenticação no servidor
* @param ISSHAuthentication $auth
* @return boolean
*/
public function authenticate( ISSHAuthentication $auth ){
return $this->state->authenticate( $auth , $this );
}
/**
* Executa um comando no servidor
* @param string $command
* @return boolean
*/
public function execute( $command ){
return $this->state->execute( $command , $this );
}
/**
* Recupera a fingerprint do servidor
* @return string
*/
public function getFingerprint(){
return $this->state->getFingerprint( $this );
}
/**
* Abre uma conexão com um servidor remoto
* @param string $host
* @param integer $port
* @return boolean
*/
public function open( $host , $port = 22 ){
return $this->state->open( $host , $port , $this );
}
/**
* Modifica o estado da conexão
* @param ISSHState $state
*/
public function changeState( ISSHState $state ){
$this->state =& $state;
}
}
Agora, para conectar em um servidor remoto via PHP é simples:
<?php
use comsshSSHConnection;
use comsshauthSSHAuthenticatePassword;
$teste = new SSHConnection();
$teste->open( '127.0.0.1' );
$teste->authenticate( new SSHAuthenticatePassword( 'usuario' , 'senha' ) );
echo $teste->execute( 'ls -l /var/www/html/xxx/com/ssh' );
No meu caso, a saída foi:
total 16drwxr-xr-x. 3 neto apache 4096 Mar 11 18:18 authdrwxr-xr-x. 3 neto apache 4096 Mar 11 18:18 interfaces-rw-r--r--. 1 neto apache 1681 Mar 11 18:17 SSHConnection.phpdrwxr-xr-x. 3 neto apache 4096 Mar 12 06:35 state
/applications/core/interface/imageproxy/imageproxy.php?img=http://forum.imasters.com.br/public/style_emoticons/default/wink.gif&key=0566fd943552bcff9cb1b879403ca34b5ff8f67befaac7fe4648006e9f764689" alt="Imagem Postada" class="bbc_emoticon">
Muito bom. O mestre dos padrões de projeto. http://forum.imasters.com.br/public/style_emoticons/default/joia.gif
Carlos Eduardo
Parabéns. O mestre dos padrões de projeto.² :)
Parabéns. O mestre dos padrões de projeto.[3]
/applications/core/interface/imageproxy/imageproxy.php?img=http://rafaelnanet.files.wordpress.com/2009/04/051101_dvd_yoda_ex.jpg&key=3b679417580b601d5cb14db6aabcd75e0ea86a739c0fc1436e50ec9821f8e338" alt="Imagem Postada" />
*Imagem: João pensando no proximo artigo
to com um problema, copiei todos arquivos mas to tendo um erro!
o arquivo que roda o comando ssh é o test.php
todos arquivos e pasta estao com chmod 777 e o php é 5.3.2
Fatal error: Class 'com\ssh\SSHConnection' not found in /var/www/lighttpd/ssh/test.php on line 5
4 ./php.php
4 ./com/ssh/auth/SSHAuthenticatePassword.php
8 ./com/ssh/auth
4 ./com/ssh/interfaces/ISSHAuthentication.php
4 ./com/ssh/interfaces/AbstractSSHState.php
4 ./com/ssh/interfaces/ISSHState.php
16 ./com/ssh/interfaces
4 ./com/ssh/SSHConnection.php
4 ./com/ssh/state/SSHStateClosed.php
4 ./com/ssh/state/SSHStateListen.php
4 ./com/ssh/state/SSHStateEstabilished.php
16 ./com/ssh/state
48 ./com/ssh
52 ./com
4 ./test.php
64 .
>
todos arquivos e pasta estao com chmod 777 e o php é 5.3.2
Jamais de 777 em produção, é um erro grave de segurança.
>
Fatal error: Class 'com\ssh\SSHConnection' not found in /var/www/lighttpd/ssh/test.php on line 5
Veja esse link http://forum.imasters.com.br/public/style_emoticons/default/seta.gif http://br2.php.net/manual/pt_BR/function.spl-autoload-register.php
Se estiver em ambiente Windows, bastará o uso da função sem argumentos, desde que você tenha as pastas no seu include_path
No Linux, você deverá converter os separadores do namespace para separadores de diretório.
Eu costumo colocar esses tipos de diretórios dentro de um outro chamado application pois, dessa forma, fica mais fácil normalizar:
application/config.php
<?php
/**
* Configurações do ambiente
* @package config
* @category configurations
*/
namespace config;
/**
* Caminho do diretório application
* @var string
*/
$applicationPath = realpath( 'application' );
/**
* Configurações das mensagens de erro em desenvolvimento e produção
*/
if ( defined( 'production' ) ){
/**
* Configurações de exibição de erro para produção
*/
error_reporting( E_ALL & ~E_DEPRECATED );
ini_set( 'display_errors' , 'Off' );error_reporting( E_ALL | E_STRICT );
ini_set( 'display_errors' , 'On' );
}
/**
* Definição do include_path, diretório application assume prioridade em relação
* aos originais.
*/
set_include_path( sprintf( '%s%s%s' , $applicationPath , PATH_SEPARATOR , get_include_path() ) );
/**
* Registrando a função __autoload para carregar automaticamente nossas classes.
* Para normalizar, substituimos a \ usada na hierarquia dos NAMESPACES pela constante DIRECTORY_SEPARATOR,
* isso funcionará tanto em servidores Windows quanto Linux, já que a constante DIRECTORY_SEPARATOR conterá
* o valor adequado para o ambiente.
*/
spl_autoload_register( function( $class ){
require sprintf( '%s.php' , str_replace( '\\' , DIRECTORY_SEPARATOR , $class ) );
} );tem como zipar isso ai ? http://forum.imasters.com.br/public/style_emoticons/default/joia.gif
ja tentei aqui so da erro ^^
consegui, vlw, to enferrujado, parei 1 ano e pouco atras^^
nem existia namespace ainda
Pessoal, infelizmente não consegui rodar a solução =(
Algum de vocês conhece esse erro? Estou tentando rodar em um servidor Linux
[root@dyn529872 teste_ssh]# php index.php
PHP Parse error: syntax error, unexpected T_STRING, expecting T_CONSTANT_ENCAPSED_STRING or '(' in /var/www/html/teste_ssh/index.php on line 3
You have new mail in /var/spool/mail/root
[root@dyn529872 teste_ssh]#
Poderiam me dar uma ajuda?
Abraço
Srs,
Estou tentando instalar essa biblioteca já faz algum tempo. Já tentei no Cent OS, no REDHAT e no Debian porem não obtive sucesso em nenhum dos casos, alguem teria um tutorial de como instalar?
Obrigado
Senhores,
Finalmente consegui instalar a biblioteca sem que ela apresente erro. Estou utilizando RH 5.5 só que estou recebendo uma msg de erro quando abro a Pagina pelo apache:
[Thu Nov 04 14:46:59 2010] [error] [client 9.18.218.31] PHP Warning: ssh2_connect() [<a href='function.ssh2-connect'>function.ssh2-connect</a>]: Unable to connect to 9.18.218.20 on port 22 in /var/www/html/teste_ssh01.php on line 11
[Thu Nov 04 14:46:59 2010] [error] [client 9.18.218.31] PHP Warning: ssh2_connect() [<a href='function.ssh2-connect'>function.ssh2-connect</a>]: Unable to connect to 9.18.218.20 in /var/www/html/teste_ssh01.php on line 11
Se rodo ele na linha de comando ele roda de boa:
[root@xxxx html]# php teste_ssh01.php
okay: logged in...
Sist. Arq. Tam Usad Disp Uso% Montado em
/dev/hda1 1,9G 293M 1,6G 16% /
/dev/hda9 1,9G 35M 1,8G 2% /tmp
/dev/hda7 4,8G 599M 3,9G 14% /opt
/dev/hda6 4,8G 1,8G 2,8G 40% /home
/dev/hda5 9,5G 8,1G 909M 91% /var
/dev/hda3 9,5G 1,3G 7,8G 14% /usr
/dev/hda2 19G 19G 0 100% /img
tmpfs 993M 0 993M 0% /dev/shm
/dev/hda10 74G 7,6G 63G 11% /backup
<br>
[root@xxxx html]#
Se puderem me ajudar eu agradeço.
Abraço
Excelente trabalho João, meus parabens! :)