Oh Dear is the all-in-one monitoring tool for your entire website. We monitor uptime, SSL certificates, broken links, scheduled tasks and more. You'll get a notifications for us when something's wrong. All that paired with a developer friendly API and kick-ass documentation. O, and you'll also be able to create a public status page under a minute. Start monitoring using our free trial now.

A PHP package to execute commands via SSH

Original – by Freek Van der Herten – 3 minute read

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.

Stay up to date with all things Laravel, PHP, and JavaScript.

You can follow me on these platforms:

On all these platforms, regularly share programming tips, and what I myself have learned in ongoing projects.

Every month I send out a newsletter containing lots of interesting stuff for the modern PHP developer.

Expect quick tips & tricks, interesting tutorials, opinions and packages. Because I work with Laravel every day there is an emphasis on that framework.

Rest assured that I will only use your email address to send you the newsletter and will not use it for any other purposes.

Comments

What are your thoughts on "A PHP package to execute commands via SSH"?

Comments powered by Laravel Comments
Want to join the conversation? Log in or create an account to post a comment.