A PHP package to execute commands via SSH
Our team released a new package called spatie/ssh. This package allows you to execute commands via an SSH connection.
With the package installed, you can execute an SSH command like this:
$process = Ssh::create('user', 'example.com')->execute('your favorite command');
It will return an instance of Symfony's Process
.
Here's how to check if your command ran ok:
$process->isSuccessful();
And this is how you can get the output:
$process->getOutput();
To run multiple commands, pass an array to the execute method.
$process = Ssh::create('user', 'example.com')->execute([
'first command',
'second command',
]);
The package has a few extra options, head over to the readme on GitHub, to learn more.
Why we built this
I'm currently building a package called spatie/laravel-backup-server
. It will be the spiritual successor of spatie/laravel-backup. Laravel Backup is usually installed into the Laravel app, and it will copy that app to some other storage. Laravel Backup Server will take a different approach: it will SSH into each server that needs to be backed up and will copy all the files on to itself.
The package will also be able to, before and after the actual copying of files starts, execute some commands.
Let's take a look at how that is implemented. In laravel-backup-server
a Source
is a model that represents something that needs to be backed up.
On that model we have an executeSshCommands
methods that looks like this:
/** @test */
public function executeSshCommands(array $commands): Process
{
$ssh = new Ssh($this->ssh_user, $this->host);
if ($this->ssh_port) {
$ssh->usePort($this->ssh_port);
}
if ($this->ssh_private_key_file) {
$ssh->usePrivateKey($this->ssh_private_key_file);
}
return $ssh->execute($commands);
}
In that method, we get some of the attributes of the model and use them to connect to a host. Inside the backup procure that
executeSshCommands
is getting called.
Here's how we test that commands in the pre_backup_commands
do actually succeed (there's a separate test for post_backup_comands
. In the test, we create a new file using the touch
command, which will be performed via SSH. Later in the test, we assert that the created file is part of the backup.
/** @test */
public function it_can_perform_a_pre_backup_command()
{
$this->container->addFiles(__DIR__ . '/stubs/serverContent/testServer', '/src');
$this->source->update(['pre_backup_commands' => ['cd /src', 'touch newfile.txt']]);
$this->artisan('backup-server:backup')->assertExitCode(0);
$this->assertTrue($this->source->backups()->first()->has('src/newfile.txt'));
$this->assertEquals(Backup::STATUS_COMPLETED, $this->source->backups()->first()->status);
}
$container
in the test above is a local docker container, which we've set up to have a target to ssh into, you can read more on that in this blog post.
Here's another test that proves the backup fails should any of the commands in the pre_backup_commands
fails.
In closing
spatie/ssh is probably the easiest way to perform a quick SSH command. It doesn't have a lot of features, but that's ok. It's intended as something very lightweight. This isn't the first package our team has built. Here's a list with all the stuff we released previously.
What are your thoughts on "A PHP package to execute commands via SSH"?