From 45f308bd664526988f97e0a09280d5d74f5e24bb Mon Sep 17 00:00:00 2001 From: Daniel Bachhuber Date: Mon, 16 May 2016 11:19:32 -0700 Subject: [PATCH 1/2] Use `--ssh=[:]` to run commands on remote servers --- php/WP_CLI/Runner.php | 43 +++++++++++++++++++++++++++++++++++++++++++ php/config-spec.php | 6 ++++++ 2 files changed, 49 insertions(+) diff --git a/php/WP_CLI/Runner.php b/php/WP_CLI/Runner.php index 8d13f2690c..0b19a3fc81 100644 --- a/php/WP_CLI/Runner.php +++ b/php/WP_CLI/Runner.php @@ -333,6 +333,44 @@ private function _run_command() { $this->run_command( $this->arguments, $this->assoc_args ); } + /** + * Perform a command against a remote server over SSH + */ + private function run_ssh_command( $ssh ) { + + $host = $ssh; + $path = ''; + if ( false !== ( $key = stripos( $host, ':' ) ) ) { + $path = substr( $host, $key + 1 ); + $host = substr( $host, 0, $key ); + } + + WP_CLI::debug( 'SSH host: ' . $host, 'bootstrap' ); + WP_CLI::debug( 'SSH path: ' . $path, 'bootstrap' ); + + $is_tty = function_exists( 'posix_isatty' ) && posix_isatty( STDOUT ); + + $wp_binary = 'wp'; + $wp_args = array_slice( $GLOBALS['argv'], 1 ); + $wp_path = $path ? sprintf( '--path=%s', $path ) : ''; + foreach( $wp_args as $k => $v ) { + if ( preg_match( '#--ssh=#', $v ) ) { + unset( $wp_args[ $k ] ); + } + } + $command = sprintf( + 'ssh -q %s %s %s', + escapeshellarg( $host ), + $is_tty ? '-t' : '-T', + escapeshellarg( $wp_binary . ' ' . $wp_path . ' ' . implode( ' ', $wp_args ) ) + ); + + passthru( $command, $exit_code ); + if ( 0 !== $exit_code ) { + exit( $exit_code ); + } + } + /** * Check whether a given command is disabled by the config * @@ -668,6 +706,11 @@ public function start() { } } + if ( $this->config['ssh'] ) { + $this->run_ssh_command( $this->config['ssh'] ); + return; + } + // Show synopsis if it's a composite command. $r = $this->find_command_to_run( $this->arguments ); if ( is_array( $r ) ) { diff --git a/php/config-spec.php b/php/config-spec.php index 84221c0f04..b38f595849 100644 --- a/php/config-spec.php +++ b/php/config-spec.php @@ -7,6 +7,12 @@ 'desc' => 'Path to the WordPress files.', ), + 'ssh' => array( + 'runtime' => '=', + 'file' => '', + 'desc' => 'Perform operation against a remote server over SSH.', + ), + 'url' => array( 'runtime' => '=', 'file' => '', From b580bbaa7610038a47cc7b2110611b76ab737f31 Mon Sep 17 00:00:00 2001 From: Daniel Bachhuber Date: Wed, 18 May 2016 05:31:18 -0700 Subject: [PATCH 2/2] Introduce `WP_CLI_SSH_PRE_CMD` for users to set up env as needed ``` WP_CLI::add_hook( 'before_ssh', function() { if ( $ssh = WP_CLI::get_runner()->config['ssh'] ) { list( $host, $path ) = explode( ':', $ssh ); switch( $host ) { case 'hb': putenv( 'WP_CLI_SSH_PRE_CMD=export PATH=$HOME/bin:$PATH' ); break; } } }); ``` --- php/WP_CLI/Runner.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/php/WP_CLI/Runner.php b/php/WP_CLI/Runner.php index 0b19a3fc81..be27d56614 100644 --- a/php/WP_CLI/Runner.php +++ b/php/WP_CLI/Runner.php @@ -345,14 +345,20 @@ private function run_ssh_command( $ssh ) { $host = substr( $host, 0, $key ); } + WP_CLI::do_hook( 'before_ssh' ); + WP_CLI::debug( 'SSH host: ' . $host, 'bootstrap' ); WP_CLI::debug( 'SSH path: ' . $path, 'bootstrap' ); $is_tty = function_exists( 'posix_isatty' ) && posix_isatty( STDOUT ); + $pre_cmd = getenv( 'WP_CLI_SSH_PRE_CMD' ); + if ( $pre_cmd ) { + $pre_cmd = rtrim( $pre_cmd, ';' ) . '; '; + } $wp_binary = 'wp'; $wp_args = array_slice( $GLOBALS['argv'], 1 ); - $wp_path = $path ? sprintf( '--path=%s', $path ) : ''; + $wp_path = $path ? sprintf( '--path=%s', str_replace( '~', '$HOME', $path ) ) : ''; foreach( $wp_args as $k => $v ) { if ( preg_match( '#--ssh=#', $v ) ) { unset( $wp_args[ $k ] ); @@ -362,9 +368,11 @@ private function run_ssh_command( $ssh ) { 'ssh -q %s %s %s', escapeshellarg( $host ), $is_tty ? '-t' : '-T', - escapeshellarg( $wp_binary . ' ' . $wp_path . ' ' . implode( ' ', $wp_args ) ) + escapeshellarg( $pre_cmd . $wp_binary . ' ' . $wp_path . ' ' . implode( ' ', $wp_args ) ) ); + WP_CLI::debug( 'Running SSH command: ' . $command, 'bootstrap' ); + passthru( $command, $exit_code ); if ( 0 !== $exit_code ) { exit( $exit_code );