phpseclib\Net\SSH2::exec PHP Method

exec() public method

If $callback is set to false then \phpseclib\Net\SSH2::_get_channel_packet(self::CHANNEL_EXEC) will need to be called manually. In all likelihood, this is not a feature you want to be taking advantage of.
public exec ( string $command, Callback $callback = null ) : string
$command string
$callback Callback
return string
    function exec($command, $callback = null)
    {
        $this->curTimeout = $this->timeout;
        $this->is_timeout = false;
        $this->stdErrorLog = '';
        if (!($this->bitmap & self::MASK_LOGIN)) {
            return false;
        }
        // RFC4254 defines the (client) window size as "bytes the other party can send before it must wait for the window to
        // be adjusted".  0x7FFFFFFF is, at 2GB, the max size.  technically, it should probably be decremented, but,
        // honestly, if you're transferring more than 2GB, you probably shouldn't be using phpseclib, anyway.
        // see http://tools.ietf.org/html/rfc4254#section-5.2 for more info
        $this->window_size_server_to_client[self::CHANNEL_EXEC] = $this->window_size;
        // 0x8000 is the maximum max packet size, per http://tools.ietf.org/html/rfc4253#section-6.1, although since PuTTy
        // uses 0x4000, that's what will be used here, as well.
        $packet_size = 0x4000;
        $packet = pack('CNa*N3', NET_SSH2_MSG_CHANNEL_OPEN, strlen('session'), 'session', self::CHANNEL_EXEC, $this->window_size_server_to_client[self::CHANNEL_EXEC], $packet_size);
        if (!$this->_send_binary_packet($packet)) {
            return false;
        }
        $this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_OPEN;
        $response = $this->_get_channel_packet(self::CHANNEL_EXEC);
        if ($response === false) {
            return false;
        }
        if ($this->request_pty === true) {
            $terminal_modes = pack('C', NET_SSH2_TTY_OP_END);
            $packet = pack('CNNa*CNa*N5a*', NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[self::CHANNEL_EXEC], strlen('pty-req'), 'pty-req', 1, strlen('vt100'), 'vt100', $this->windowColumns, $this->windowRows, 0, 0, strlen($terminal_modes), $terminal_modes);
            if (!$this->_send_binary_packet($packet)) {
                return false;
            }
            $response = $this->_get_binary_packet();
            if ($response === false) {
                throw new \RuntimeException('Connection closed by server');
            }
            if (!strlen($response)) {
                return false;
            }
            list(, $type) = unpack('C', Strings::shift($response, 1));
            switch ($type) {
                case NET_SSH2_MSG_CHANNEL_SUCCESS:
                    break;
                case NET_SSH2_MSG_CHANNEL_FAILURE:
                default:
                    $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
                    throw new \RuntimeException('Unable to request pseudo-terminal');
            }
            $this->in_request_pty_exec = true;
        }
        // sending a pty-req SSH_MSG_CHANNEL_REQUEST message is unnecessary and, in fact, in most cases, slows things
        // down.  the one place where it might be desirable is if you're doing something like \phpseclib\Net\SSH2::exec('ping localhost &').
        // with a pty-req SSH_MSG_CHANNEL_REQUEST, exec() will return immediately and the ping process will then
        // then immediately terminate.  without such a request exec() will loop indefinitely.  the ping process won't end but
        // neither will your script.
        // although, in theory, the size of SSH_MSG_CHANNEL_REQUEST could exceed the maximum packet size established by
        // SSH_MSG_CHANNEL_OPEN_CONFIRMATION, RFC4254#section-5.1 states that the "maximum packet size" refers to the
        // "maximum size of an individual data packet". ie. SSH_MSG_CHANNEL_DATA.  RFC4254#section-5.2 corroborates.
        $packet = pack('CNNa*CNa*', NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[self::CHANNEL_EXEC], strlen('exec'), 'exec', 1, strlen($command), $command);
        if (!$this->_send_binary_packet($packet)) {
            return false;
        }
        $this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_REQUEST;
        $response = $this->_get_channel_packet(self::CHANNEL_EXEC);
        if ($response === false) {
            return false;
        }
        $this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_DATA;
        if ($callback === false || $this->in_request_pty_exec) {
            return true;
        }
        $output = '';
        while (true) {
            $temp = $this->_get_channel_packet(self::CHANNEL_EXEC);
            switch (true) {
                case $temp === true:
                    return is_callable($callback) ? true : $output;
                case $temp === false:
                    return false;
                default:
                    if (is_callable($callback)) {
                        if (call_user_func($callback, $temp) === true) {
                            $this->_close_channel(self::CHANNEL_EXEC);
                            return true;
                        }
                    } else {
                        $output .= $temp;
                    }
            }
        }
    }

Usage Example

Example #1
1
 /**
  * @param string $commandName
  * @param string $target
  * @param array  $targetConfig
  * @param array  $inputCommand
  * @param array  $userHomeDir
  * @return string
  */
 public function executeCommand($commandName, $target, $targetConfig, $inputCommand, $userHomeDir)
 {
     $remoteCommand = str_replace([sprintf('\'%s\'', $commandName), sprintf('target=\'%s\'', $target)], [$commandName, sprintf('root=%s', $targetConfig['root'])], $inputCommand);
     $remoteCommand = sprintf('%s %s', $targetConfig['console'], $remoteCommand);
     $key = null;
     if (array_key_exists('password', $targetConfig)) {
         $key = $targetConfig['password'];
     }
     if (!$key) {
         $key = new RSA();
         if (array_key_exists('passphrase', $targetConfig['keys'])) {
             $passphrase = $targetConfig['keys']['passphrase'];
             $passphrase = realpath(preg_replace('/~/', $userHomeDir, $passphrase, 1));
             $key->setPassword(trim(file_get_contents($passphrase)));
         }
         $private = $targetConfig['keys']['private'];
         $private = realpath(preg_replace('/~/', $userHomeDir, $private, 1));
         if (!$key->loadKey(trim(file_get_contents($private)))) {
             return $this->getTranslator()->trans('commands.site.debug.messages.private-key');
         }
     }
     $ssh = new SSH2($targetConfig['host'], $targetConfig['port']);
     if (!$ssh->login($targetConfig['user'], $key)) {
         return sprintf('%s - %s', $ssh->getExitStatus(), $ssh->getErrors());
     } else {
         return $ssh->exec($remoteCommand);
     }
 }
All Usage Examples Of phpseclib\Net\SSH2::exec