vcn / exeg
Library providing a shell command abstraction
Installs: 9 947
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 3
Forks: 0
Open Issues: 0
Requires
- php: >=7.1.0
Requires (Dev)
- symfony/process: ^4.2
Suggests
- symfony/process: symfony/process is required to use the classes in the Vcn\Exeg\Symfony\-namespace
This package is auto-updated.
Last update: 2024-10-26 00:51:54 UTC
README
Exeg is a PHP-library that provides an abstraction for commands. Exeg makes it possible to execute the same command in different environments, for example local (using symfony/process), or over SSH.
Quickstart
<?php use Vcn\Exeg\Command; use Vcn\Exeg\Shell; // Create a command $command = new Command('cat', ['/etc/hosts']); // We now have a platform-agnostic representation of the command: var_dump($command); echo PHP_EOL; // Command-instances are immutable. Instead of setters the class has with-methods which create copies of the current // instance with the specified property changed. Let's demonstrate it by complete rebuilding the command: $command = $command ->withCmd('env') ->withArgs([]) ->withWorkDir('/') ->withEnv(['FOO' => 'BAR']); // withArgs() and withEnv() have an optional second boolean parameter which you can use to append them instead of replacing them $command = $command->withEnv(['BAR' => 'BAZ'], true); // Exeg also provides a few utilities to use the commands. For example, let's render the command to a string which has // been properly escaped, ready for usage in a shell $shellString = Shell::render($command) . PHP_EOL; passthru($shellString);
Symfony
Exeg provides an adapter to symfony/process:
<?php use Vcn\Exeg\Command; use Vcn\Exeg\Symfony\ExegSymfony; use Vcn\Exeg\Symfony\ProcessBuffer; // ExegSymfony is the adapter from Exeg to symfony/process $exegSymfony = new ExegSymfony(); // This is the command we want to execute. $command = new Command('cat', ['/etc/hosts']); // The ExegSymfony-instance can build a Symfony-process for us $process = $exegSymfony->build($command); // Symfony uses callbacks to handle process output. Exeg provides utilities to handle them in a few different ways. In // this case, we want a callback that passes through all data to our own stdout/stderr. $passthroughCallback = ProcessBuffer::passthrough(); // Run process and display exit code $exitCode = $process->run($passthroughCallback); echo "Command exited with code {$exitCode}" . PHP_EOL;
Working directories
When working with paths relative to a directory, Vcn\Exeg\WorkDir
makes life a little easier.
<?php use Vcn\Exeg\WorkDir; $workDir = new WorkDir('/etc'); // Displays /etc/hosts $displayHostsCommand = $workDir->command('cat', ['hosts']); // Displays /etc/hostname $displayHostnameCommand = $workDir->command('cat', ['hostname']);
Combining commands
Sometimes commands take commands as argument. You can use Shell::render()
to generate the command argument.
<?php use Vcn\Exeg\Command; use Vcn\Exeg\Shell; use Vcn\Exeg\Symfony\ExegSymfony; use Vcn\Exeg\Symfony\ProcessBuffer; $exegSymfony = new ExegSymfony(); $catHostsCommand = new Command('cat', ['/etc/hosts']); $bashCommand = new Command('bash', ['-c', Shell::render($catHostsCommand)]); $exegSymfony->run($bashCommand, ProcessBuffer::passthrough());
Pipelines
You can construct unix pipelines using a utility-class:
<?php use Vcn\Exeg\Command; use Vcn\Exeg\Shell; $findCmd = new Command( 'find', [ // find all files in /home/johndoe ending in *.jpg or *.jpeg '/home/johndoe', '-xdev', '-type', 'f', '(', '-iname', '*.jpg', '-o', '-iname', '*.jpeg', ')', // use magick to output [filename] [width px] [height px] '-exec', 'magick', 'identify', '-format', '%i %w %h\n', '{}', ';', ] ); // Use awk to change output to [w*h] [filename] $awkCmd = new Command('awk', ['-F', ' ', '{ print $2*$3 " " $1; }']); // Use numeric sort to the files by number of pixels $sortCmd = new Command('sort', ['-n']); $cmd = Shell\Pipeline ::first($findCmd) ->then($awkCmd) ->last($sortCmd); echo "{$cmd->render()}\n";
SSH
The class Vcn\Exeg\Command\Ssh\Server
implements an abstraction of an SSH server.
<?php use Vcn\Exeg\Command; use Vcn\Exeg\Command\Ssh; use Vcn\Exeg\Symfony\ExegSymfony; use Vcn\Exeg\Symfony\ProcessBuffer; $exegSymfony = new ExegSymfony(); $sshServer = new Ssh\Server('example.test'); $catHostsCommand = new Command('cat', ['/etc/hosts']); $sshCommand = $sshServer->adopt($catHostsCommand); $exegSymfony->run($sshCommand, ProcessBuffer::passthrough());
rsync
The class Vcn\Exeg\Command\Rsync\Factory
creates rsync commands.
<?php use Vcn\Exeg\Command\Rsync; use Vcn\Exeg\Symfony\ExegSymfony; use Vcn\Exeg\Symfony\ProcessBuffer; $exegSymfony = new ExegSymfony(); $srcDir = '/home/user/src/'; $destDir = '/home/user/dest/'; $rsyncParams = Rsync\Params::create()->withArchive(); $rsyncCommand = Rsync\Factory::local($srcDir, $destDir, $rsyncParams); $exegSymfony->run($rsyncCommand, ProcessBuffer::passthrough());
Rsync + SSH
The factory also contains methods to rsync from/to SSH servers.
<?php use Vcn\Exeg\Command\Rsync; use Vcn\Exeg\Command\Ssh; use Vcn\Exeg\Symfony\ExegSymfony; use Vcn\Exeg\Symfony\ProcessBuffer; $exegSymfony = new ExegSymfony(); $srcDir = '/home/user/src/'; $destServer = new Ssh\Server('example.test'); $destDir = '/home/user/dest/'; $rsyncParams = Rsync\Params::create()->withArchive(); $rsyncCommand = Rsync\Factory::localToSsh($srcDir, $destServer, $destDir, $rsyncParams); $exegSymfony->run($rsyncCommand, ProcessBuffer::passthrough());