I'm trying to establish an interactive SSH connection to a remote server using PHP via the command line on Mac OS X 10.6. I'm currently using PHP's proc_open function to execute the following command:
ssh -t -t -p 22 [email protected]
This almost works. The -t -t
options are supposed to force a pseudo terminal which they almost do. I am able to enter the SSH password and press enter. However, after pressing enter the terminal appears to simply hang. No output, no nothing - it's as if the SSH session has failed. I can't run commands or anything and have to kill the whole thing using Ctrl+C. I know the login is successful because I can execute a command like ssh -t -t -p 22 [email protected] "ls -la"
and get the correct output.
I thought the problem must be related to the fact that I was using standard pipes in my proc_open call, so I replaced them with pty. I get the following error: "pty pseudo terminal not supported on this system..."
Does Mac OS X simply not support pty or pseudo terminals? (I'm pretty new at using all this shell terminology).
Here's the PHP code:
$descriptorspec = array(0 => array("pty"), 1 => array("pty"), 2 => array("pty"));
$cwd = getcwd();
$process = proc_open('ssh -t -t -p 22 [email protected]', $descriptorspec, $pipes, $cwd);
if (is_resource($process))
{
while (true)
{
echo(stream_get_contents($pipes[1]));
$status = proc_get_status($process);
if (! $status["running"])
break;
}
}
(Sorry - cannot for the life of me figure out SO's formatting instructions...)
What am I doing wrong? Why can't I use pty? Is this just impossible on Mac OS X? Thanks for your help!
You should use public key authentication rather than trying to programmatically bypass interactive password authentication.
The password prompt is supposed to be used from a tty and I believe it was made intentionally difficult to use otherwise. Also the -t -t
argument only takes effect once you are connected to the remote host. And I don't believe the PHP function proc_open()
can run a command inside a virtual terminal.
To setup public key authentication:
# Generate keypair
ssh-keygen -t rsa
# Copy public key to server
scp ~/.ssh/id_rsa.pub example.com:.ssh/authorized_keys
# Now you shouldn't be prompted for a password when connecting to example.com
# from this host and user account.
ssh example.com
# Since the web server (and thus PHP) probably has its own user account...
# Copy the ~/.ssh/id_rsa file somewhere else
cp ~/.ssh/id_rsa /some_path/id_rsa
# Change ownership of the file to the web server account
chown www-data:www-data /some_path/id_rsa
# Fix the file permissions (ssh ignore the keyfile if it is world readable)
chown 600 /some_path/id_rsa
# Try connecting to the server through the web server account
su -c "ssh -i /some_path/id_rsa -o UserKnownHostsFile=/some_path/known_hosts example.com" www-data
# Add the host to the known hosts file when prompted
Alternately, you could use plink
(part of PuTTY for Linux) instead of OpenSSH as it can take the password on the command line plink -pw password example.com
. But doing so presents a security risk as anyone who runs ps aux
on the server can see the password in the process list.
There is also a program called sshpass
that takes the password from an environment variable or command argument and passes it to ssh
.