3 namespace Robo\Task\Remote;
5 use Robo\Contract\CommandInterface;
6 use Robo\Exception\TaskException;
7 use Robo\Task\BaseTask;
8 use Robo\Contract\SimulatedInterface;
11 * Runs multiple commands on a remote server.
12 * Per default, commands are combined with &&, unless stopOnFail is false.
17 * $this->taskSshExec('remote.example.com', 'user')
18 * ->remoteDir('/var/www/html')
20 * ->exec('chmod g+x logs')
25 * You can even exec other tasks (which implement CommandInterface):
28 * $gitTask = $this->taskGitStack()
29 * ->checkout('master')
32 * $this->taskSshExec('remote.example.com')
33 * ->remoteDir('/var/www/html/site')
38 * You can configure the remote directory for all future calls:
41 * \Robo\Task\Remote\Ssh::configure('remoteDir', '/some-dir');
44 class Ssh extends BaseTask implements CommandInterface, SimulatedInterface
46 use \Robo\Common\CommandReceiver;
47 use \Robo\Common\ExecOneCommand;
62 protected $stopOnFail = true;
70 * Changes to the given directory before running commands.
77 * @param null|string $hostname
78 * @param null|string $user
80 public function __construct($hostname = null, $user = null)
82 $this->hostname = $hostname;
87 * @param string $hostname
91 public function hostname($hostname)
93 $this->hostname = $hostname;
102 public function user($user)
109 * Whether or not to chain commands together with && and stop the chain if one command fails.
111 * @param bool $stopOnFail
115 public function stopOnFail($stopOnFail = true)
117 $this->stopOnFail = $stopOnFail;
122 * Changes to the given directory before running commands.
124 * @param string $remoteDir
128 public function remoteDir($remoteDir)
130 $this->remoteDir = $remoteDir;
135 * @param string $filename
139 public function identityFile($filename)
141 $this->option('-i', $filename);
151 public function port($port)
153 $this->option('-p', $port);
161 public function forcePseudoTty()
171 public function quiet()
181 public function verbose()
189 * @param string|string[]|CommandInterface $command
193 public function exec($command)
195 if (is_array($command)) {
196 $command = implode(' ', array_filter($command));
199 $this->exec[] = $command;
205 * Returns command that can be executed.
206 * This method is used to pass generated command from one task to another.
210 public function getCommand()
213 foreach ($this->exec as $command) {
214 $commands[] = $this->receiveCommand($command);
217 $remoteDir = $this->remoteDir ? $this->remoteDir : $this->getConfigValue('remoteDir');
218 if (!empty($remoteDir)) {
219 array_unshift($commands, sprintf('cd "%s"', $remoteDir));
221 $command = implode($this->stopOnFail ? ' && ' : ' ; ', $commands);
223 return $this->sshCommand($command);
229 public function run()
231 $this->validateParameters();
232 $command = $this->getCommand();
233 return $this->executeCommand($command);
239 public function simulate($context)
241 $command = $this->getCommand();
242 $this->printTaskInfo("Running {command}", ['command' => $command] + $context);
245 protected function validateParameters()
247 if (empty($this->hostname)) {
248 throw new TaskException($this, 'Please set a hostname');
250 if (empty($this->exec)) {
251 throw new TaskException($this, 'Please add at least one command');
256 * Returns an ssh command string running $command on the remote.
258 * @param string|CommandInterface $command
262 protected function sshCommand($command)
264 $command = $this->receiveCommand($command);
265 $sshOptions = $this->arguments;
266 $hostSpec = $this->hostname;
268 $hostSpec = $this->user . '@' . $hostSpec;
271 return "ssh{$sshOptions} {$hostSpec} '{$command}'";