Skip to content

7 de Janeiro de 2009

SSH2 & PHP Howto Guide: SSH Connections Made Easy in PHP

PHP doesn’t come with native sup­port for mak­ing SSH con­nec­tions via the libssh2 libraries. You must use the PECL SSH2 exten­sions. Installing them can be tricky, but Kevin van Zon­n­eveld does a great job explain­ing how to install them over here. So I won’t go there. The new ver­sion, 0.11.0, also seems to be com­pil­ing more reli­ably for everyone.

Unfor­tu­nately, the library is sparsely doc­u­mented, and still buggy in some places. And most of the com­ments posted on http://www.php.net/ssh2 are just plain wrong! Kudos to Mike Sul­li­van for fix­ing some of the issues with non-blocking I/O (And let’s not for­get to thank Sara Gole­mon for writ­ing it to begin with!). I list the most con­spic­u­ous prob­lems at the bot­tom of this blog entry for inter­ested par­ties. Every­one else can use our wrap­pers to smooth over some of the kinks and make most com­mon tasks triv­ial to perform.

Our wrap­per is released under GNU license and can be used, for exam­ple, as follows:

$php_ssh2 = new SSH2('YOURHOST.COM');
$php_ssh2->loginWithPassword('YOUR_LOGIN', 'YOUR_PASSWORD');
echo $php_ssh2->execCommandBlock('find /cat/food');

All Per­ti­nent Features:

$php_ssh2->execCommandBlockNoOutput()

allows exe­cu­tion of a script ignor­ing out­put. Note that with­out block­ing exe­cu­tion man­u­ally, 2 ssh2_execs will exe­cute asy­chro­nously. So it should also be used for shell scripts that have no out­put. Why? If you never check for data, it will never block — yes, even in block­ing mode! This is sub­tle … until it clicks.

$php_ssh2->setLogReads($setting = true)

enables or dis­ables read log­ging on the cur­rent SSH2 stream.

$php_ssh2->setLogWrites($setting = true)

enables or dis­ables write log­ging on the cur­rent SSH2 stream.

$php_ssh2->getShell($set_blocking = false, $term_type = 'vt102' ... )

opens a shell for the user — gen­er­ally not needed and much harder to work with.

$php_ssh2->waitPrompt($prompt_regex = '> $', &$buf = '', $timeout_secs = 0)

waits for a spec­i­fied prompt $prompt_regex (expressed as a reg­u­lar expres­sion) for $timeout_secs (or 0 to block for­ever). Returns true or false, leaves response (whether match­ing or not) buffer in &$buf parameter.

$php_ssh2->writePrompt($command, $add_newline = true)

writes the spec­i­fied out­put to stream. Returns what it was able to write.

The rest of the func­tions are fairly self-explanatory. Check out the library here —
http://www.seoegghead.com/software/ssh2-php-wrappers.seo

Problems/Gotchas I’ve Observed in PECL SSH2

1. Non-blocking mode buggy and/or core­dumps in ver­sions < 0.11.0. So make sure you upgrade.
2. FreeBSD Ports cur­rently reports a patched “usr/ports/security/pecl-ssh2? ver­sion 0.10.0 as 0.11.0 (Not strictly a PECL SSH2 prob­lem, but worth not­ing as it caused me grief).
3. stream_set_timeout() does not work at all with SSH2 streams — silently always returns false.
4. stream_select() does not work with SSH2 streams — but prints a warn­ing.
5. One must pass NULL to $pty — not false (like some com­ments on php.net claim), not “” — oth­er­wise LFs (“\n”) will get changed to CRLFs (“\r\n”). Text files will mostly sur­vive this, but binary data will be cor­rupted! This took us a solid hour to debug and involved a hex-editor.

As a con­se­quence of some of the above, there is no good way to do non-blocking I/O in ver­sions < 0.11.0. Period. No time­outs, no polling, no select­ing. If you need non-blocking I/O to work reli­ably, you must upgrade to 0.11.0.

seoeg­gheadv

Read more from PHP

Share your thoughts, post a comment.

(required)
(required)

Note: HTML is allowed. Your email address will never be published.

Subscribe to comments

Spam protection by WP Captcha-Free

Bad Behavior has blocked 38 access attempts in the last 7 days.