adachsoft / command-executor-lib
A robust PHP library for executing system commands with timeout support, output handling, and process management
Installs: 15
Dependents: 4
Suggesters: 0
Security: 0
Stars: 0
Forks: 0
pkg:composer/adachsoft/command-executor-lib
Requires
- php: ^8.3
Requires (Dev)
- adachsoft/php-code-style: ^0.2.1
- friendsofphp/php-cs-fixer: ^3.0
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^11.0
README
A robust PHP library for executing system commands with timeout support, output handling, and process management.
Features
- Simple API - Easy to use interface for command execution
- Error Handling - Comprehensive exception handling with detailed error information
- Process Management - Robust process handling with non-blocking I/O and timeouts
- Output Capture - Captures both stdout and stderr streams and exposes them separately and combined
- Environment Variables - Support for custom environment variables
- Working Directory - Ability to set custom working directory
- PHP 8.3+ - Modern PHP with strict types and full type safety
Installation
Install via Composer:
composer require adachsoft/command-executor-lib
Requirements
- PHP 8.3 or higher
- No external system dependencies
Quick Start
Basic Usage
<?php
use AdachSoft\CommandExecutorLib\CommandExecutorException;
use AdachSoft\CommandExecutorLib\SimpleCommandExecutor;
$executor = new SimpleCommandExecutor();
// Execute a simple command
try {
$output = $executor->execute('ls -la');
echo $output;
} catch (CommandExecutorException $e) {
echo 'Error: ' . $e->getMessage();
}
Advanced Usage
Execute with Environment Variables
<?php
use AdachSoft\CommandExecutorLib\SimpleCommandExecutor;
$executor = new SimpleCommandExecutor();
// Set custom environment variables
$env = [
'PATH' => '/usr/local/bin:/usr/bin:/bin',
'DEBUG' => 'true',
];
$output = $executor->execute('echo $DEBUG', $env);
// Output: true
Execute in Specific Directory
<?php
use AdachSoft\CommandExecutorLib\SimpleCommandExecutor;
$executor = new SimpleCommandExecutor();
// Execute command in specific directory
$output = $executor->execute('ls -la', [], '/var/www');
Handle Command Failures
<?php
use AdachSoft\CommandExecutorLib\CommandExecutorException;
use AdachSoft\CommandExecutorLib\SimpleCommandExecutor;
$executor = new SimpleCommandExecutor();
try {
$output = $executor->execute('nonexistent-command');
} catch (CommandExecutorException $e) {
echo 'Command failed: ' . $e->getMessage() . "\n";
echo 'Exit code: ' . $e->getExitCode() . "\n";
echo 'Output: ' . $e->getCommandOutput() . "\n";
}
Get Exit Code Without Exception (array result)
<?php
use AdachSoft\CommandExecutorLib\SimpleCommandExecutor;
$executor = new SimpleCommandExecutor();
// Execute command and get stdout, stderr, combined output and exit code
$result = $executor->executeWithExitCode('ls /nonexistent');
if ($result['exitCode'] === 0) {
echo 'Success (stdout): ' . $result['stdout'] . "\n";
} else {
echo 'Failed with code ' . $result['exitCode'] . ': ' . $result['output'] . "\n";
}
Get Detailed Result as DTO
<?php
use AdachSoft\CommandExecutorLib\CommandExecutionResult;
use AdachSoft\CommandExecutorLib\SimpleCommandExecutor;
$executor = new SimpleCommandExecutor();
/** @var CommandExecutionResult $result */
$result = $executor->executeWithResult('ls /nonexistent');
if ($result->isSuccessful()) {
echo 'Success (stdout): ' . $result->stdout . "\n";
} else {
echo 'Failed with code ' . $result->exitCode . ': ' . $result->output . "\n";
}
Using Timeouts
<?php
use AdachSoft\CommandExecutorLib\CommandExecutorException;
use AdachSoft\CommandExecutorLib\SimpleCommandExecutor;
$executor = new SimpleCommandExecutor();
try {
// This command will be terminated after 1 second
$output = $executor->execute('sleep 5', [], null, 1.0);
} catch (CommandExecutorException $e) {
echo 'Command timed out: ' . $e->getMessage();
}
Real-World Examples
Git Operations
<?php
use AdachSoft\CommandExecutorLib\SimpleCommandExecutor;
$executor = new SimpleCommandExecutor();
// Get current git branch
$branch = trim($executor->execute('git rev-parse --abbrev-ref HEAD'));
echo "Current branch: $branch";
// Check git status
$status = $executor->execute('git status --porcelain', [], '/path/to/project');
if (empty($status)) {
echo 'Working directory is clean';
} else {
echo 'Uncommitted changes detected';
}
File Operations
<?php
use AdachSoft\CommandExecutorLib\SimpleCommandExecutor;
$executor = new SimpleCommandExecutor();
// Create backup
$backupDir = '/backups/' . date('Y-m-d');
$executor->execute("mkdir -p $backupDir");
$executor->execute("cp -r /var/www $backupDir/");
// Check disk usage
$usage = $executor->execute('df -h / | tail -1');
echo "Disk usage: $usage";
Docker Operations
<?php
use AdachSoft\CommandExecutorLib\SimpleCommandExecutor;
$executor = new SimpleCommandExecutor();
// Build Docker image
$executor->execute('docker build -t myapp:latest .', [], '/path/to/dockerfile');
// Run container
$result = $executor->executeWithExitCode('docker run --rm myapp:latest');
if ($result['exitCode'] === 0) {
echo 'Container executed successfully';
}
API Reference
CommandExecutorInterface
The main interface that all command executors must implement.
Methods
execute(string $command, array $env = [], ?string $cwd = null, ?float $timeout = null): stringexecuteWithExitCode(string $command, array $env = [], ?string $cwd = null, ?float $timeout = null): array{stdout: string, stderr: string, output: string, exitCode: int}executeWithResult(string $command, array $env = [], ?string $cwd = null, ?float $timeout = null): CommandExecutionResult
SimpleCommandExecutor
Default implementation using PHP's proc_open().
Constructor
$executor = new SimpleCommandExecutor();
CommandExecutionResult
Immutable data transfer object representing command execution result.
Properties
string $stdout- Standard output (STDOUT)string $stderr- Standard error output (STDERR)string $output- Combined stdout + stderrint $exitCode- Process exit code
Methods
isSuccessful(): bool- ReturnstruewhenexitCode === 0
CommandExecutorException
Exception thrown when command execution fails.
Methods
getCommandOutput(): ?string- Returns the command outputgetExitCode(): ?int- Returns the exit codefromCommandFailure()- Static factory method for creating exceptions
Error Handling
The library provides comprehensive error handling through CommandExecutorException:
<?php
use AdachSoft\CommandExecutorLib\CommandExecutorException;
use AdachSoft\CommandExecutorLib\SimpleCommandExecutor;
$executor = new SimpleCommandExecutor();
try {
$output = $executor->execute('invalid-command');
} catch (CommandExecutorException $e) {
// Handle specific error cases
switch ($e->getExitCode()) {
case 127:
echo 'Command not found';
break;
case 126:
echo 'Permission denied';
break;
default:
echo 'Command failed: ' . $e->getMessage();
}
}
Testing
Run the test suite:
composer test
Run with coverage:
composer test-coverage
Run code quality checks:
composer quality
Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Run quality checks (
composer quality) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Merge Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Changelog
See CHANGELOG.md for a detailed list of changes.