├── .gitignore ├── LICENSE ├── README.md ├── composer.json └── src └── Controller.php /.gitignore: -------------------------------------------------------------------------------- 1 | composer.lock 2 | .DS_Store 3 | *.sublime-* 4 | 5 | vendor/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Tim Helfensdörfer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Yii2 SSH Console 2 | 3 | Controller with ssh commands for the yii2 console. 4 | 5 | ## Example 6 | 7 | ```php 8 | connect('example.com', [ 19 | 'username' => 'myusername', 20 | 'password' => 'mypassword', // optional 21 | ]); 22 | 23 | // Or via private key 24 | /* 25 | $this->connect('example.com', [ 26 | 'username' => 'myusername', 27 | 'key' => '/path/to/private.key', 28 | 'password' => 'mykeypassword', // optional 29 | ]); 30 | */ 31 | 32 | $output = $this->run('echo "test"'); 33 | echo 'Output: ' . $output; // Output: test 34 | 35 | $output = $this->run([ 36 | 'cd /path/to/install', 37 | './put_offline.sh', 38 | 'git pull -f', 39 | 'composer install', 40 | './yii migrate --interactive=0', 41 | './build.sh', 42 | './yii cache/flush', 43 | './put_online.sh', 44 | ]); 45 | 46 | // Or via callback 47 | $this->run([ 48 | 'cd /path/to/install', 49 | './put_offline.sh', 50 | 'git pull -f', 51 | 'composer install', 52 | './yii migrate --interactive=0', 53 | './build.sh', 54 | './yii cache/flush', 55 | './put_online.sh', 56 | ], function($line) { 57 | echo $line; 58 | }); 59 | } 60 | } 61 | ``` 62 | 63 | And then in the local console: 64 | 65 | ```bash 66 | ./yii deploy 67 | ``` 68 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "thelfensdrfer/yii2-ssh-console", 3 | "description": "SSH library for yii2 console commands", 4 | "license": "MIT", 5 | "authors": [ 6 | { 7 | "name": "Tim Helfensdoerfer", 8 | "email": "tim@visualappeal.de" 9 | } 10 | ], 11 | "minimum-stability": "dev", 12 | "require": { 13 | "php": ">=5.4.0", 14 | "yiisoft/yii2": "*", 15 | "phpseclib/phpseclib": "2.0.*" 16 | }, 17 | "autoload": { 18 | "psr-4": { 19 | "yii2sshconsole\\": "src/" 20 | }, 21 | "files": [ 22 | "../../phpseclib/phpseclib/phpseclib/Net/SSH2.php" 23 | ] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Controller.php: -------------------------------------------------------------------------------- 1 | 'myname', 28 | * 'password' => 'mypassword', // can be empty 29 | * ] 30 | * or via private key 31 | * [ 32 | * 'key' => '/path/to/private.key', 33 | * 'password' => 'mykeypassword', // can be empty 34 | * ] 35 | * @param integer $port Default 22 36 | * @param integer $timeout Default 10 seconds 37 | * 38 | * @throws \yii2sshconsole\LoginFailedException If the login failes 39 | * @throws \yii2sshconsole\LoginUnknownException If no username is set 40 | * 41 | * @return bool 42 | */ 43 | public function connect($host, $auth, $port = 22, $timeout = 10) 44 | { 45 | $this->ssh = new SSH2($host, $port, $timeout); 46 | 47 | if (!isset($auth['key']) && isset($auth['username'])) { 48 | // Login via username/password 49 | 50 | $username = $auth['username']; 51 | $password = isset($auth['password']) ? $auth['password'] : ''; 52 | 53 | if (!$this->ssh->login($username, $password)) 54 | throw new LoginFailedException(Yii::t( 55 | 'Yii2SshConsole', 56 | 'Login failed for user {username} using password {answer}!', 57 | [ 58 | 'username' => $username, 59 | 'answer' => !empty($password) ? 1 : 0 60 | ] 61 | )); 62 | else 63 | return true; 64 | } elseif (isset($auth['key']) and isset($auth['username'])) { 65 | // Login via private key 66 | 67 | $username = $auth['username']; 68 | $password = isset($auth['key_password']) ? $auth['key_password'] : ''; 69 | 70 | $key = new RSA; 71 | if (!empty($password)) { 72 | $key->setPassword($password); 73 | } 74 | $key->loadKey(file_get_contents($auth['key'])); 75 | 76 | if (!$this->ssh->login($username, $key)) 77 | throw new LoginFailedException(Yii::t( 78 | 'Yii2SshConsole', 79 | 'Login failed for user {username} using key with password {answer}!', 80 | [ 81 | 'username' => $username, 82 | 'answer' => !empty($password) ? 1 : 0 83 | ] 84 | )); 85 | else 86 | return true; 87 | } else { 88 | // No username given 89 | 90 | throw new LoginUnknownException(Yii::t( 91 | 'Yii2SshConsole', 92 | 'No username given!' 93 | )); 94 | } 95 | 96 | return false; 97 | } 98 | 99 | /** 100 | * Read the next line from the SSH session. 101 | * 102 | * @return string|null 103 | */ 104 | public function readLine() 105 | { 106 | $output = $this->ssh->_get_channel_packet(SSH2::CHANNEL_EXEC); 107 | 108 | return $output === true ? null : $output; 109 | } 110 | 111 | /** 112 | * Run a ssh command for the current connection. 113 | * 114 | * @param string|array $commands 115 | * @param callable $callback 116 | * 117 | * @throws NotConnectedException If the client is not connected to the server 118 | * 119 | * @return string|null 120 | */ 121 | public function run($commands, $callback = null) 122 | { 123 | if (!$this->ssh->isConnected()) 124 | throw new NotConnectedException(); 125 | 126 | if (is_array($commands)) 127 | $commands = implode(' && ', $commands); 128 | 129 | if ($callback === null) 130 | $output = ''; 131 | 132 | $this->ssh->exec($commands, false); 133 | 134 | while (true) { 135 | if (is_null($line = $this->readLine())) break; 136 | 137 | if ($callback === null) 138 | $output .= $line; 139 | else 140 | call_user_func($callback, $line, $this); 141 | } 142 | 143 | if ($callback === null) 144 | return $output; 145 | else 146 | return null; 147 | } 148 | 149 | /** 150 | * Returns the log messages of the connection. 151 | * 152 | * @return array 153 | */ 154 | public function getLog() 155 | { 156 | return $this->ssh->getLog(); 157 | } 158 | } 159 | --------------------------------------------------------------------------------