phpseclib: Unable to open channel - Consecutive Execs

I am writing a provisioning script to setup my server for me. Now everything seems to be working except it seems that the connection is being shut down early?

ErrorException (E_USER_NOTICE)
Unable to open channel

I am first connecting via SSH , then running lots of commands (50 or more) by running

run('do some linux stuff here');

Below is more code

    public function ssh($ip)
    {
        $key = new RSA();
        $key->setPassword(env('SSH_KEY_PASSWORD'));
        $key->loadKey(file_get_contents('/home/vagrant/.ssh/id_rsa'));

        $ssh = new SSH2($ip);

        $ssh->enableQuietMode();

        if (!$ssh->login('root', $key)) {
            exit('Login Failed');
        }

        $this->session = $ssh;
    }
}

 public function run($command, $read = false)
    {
        $results = $this->session->exec($command.";");

        if(!empty($error = $this->session->getStdError())) {
            \Log::error($error);
        }

        if(!empty($results)) {
            \Log::info($results);
        }

        if($read) {
            return $this->session->read();
        }
    }


Is there a problem with how im doing it , is there a better way ?

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 21 (11 by maintainers)

Commits related to this issue

Most upvoted comments

A new release has been made.

Thanks!

I’ll try to do a release this weekend.

Thanks!

The problem is that you’ve enabled a PTY. Once you’ve done that exec() works like an interactive shell in that you have to do read() to get output and can send data in the middle of receiving the output via write().

A normal exec() command dies after the output has ended. But with a PTY that’s not the case because the command doesn’t necessarily have to die. ie. if you did $ssh->exec('bash') with a PTY… that command wouldn’t really die unless you did $ssh->exec("exit\n") whist not being in vim or some such.

Your code has you parsing the output of $ssh->exec() even tho you have a PTY. That doesn’t work. Example:

$ssh->enablePTY();

echo $ssh->exec('ls -latr');

That returns 1 because $ssh->exec() returned true.

A few more code snippets:

$ssh->enablePTY();
echo $ssh->exec('ls -latr');
echo $ssh->exec('pwd');

That gives me an error similar to the one you’re getting. Since phpseclib 1.0 / 2.0 have a fixed channel for exec’s you can’t do two exec’s with a PTY concurrently so the above will never really work but maybe I can make it so that instead of outputting an error the second $ssh->exec() returns false. (fwiw, I do plan on supporting dynamic channels in the master / 3.0 version at some point).

Also…

$ssh->enablePTY();
echo $ssh->exec('ls -latr');
$ssh->disablePTY();
echo $ssh->exec('pwd');

Without a PTY exec() would close the channel after it got the output. But with a PTY it doesn’t do that and $ssh->disablePTY() doesn’t close the channel either. It’d probably be good if it did but it doesn’t. I’ll look into changing that behavior.