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

2.0.0 2025-12-11 06:29 UTC

This package is not auto-updated.

Last update: 2025-12-11 05:31:07 UTC


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): string
  • executeWithExitCode(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 + stderr
  • int $exitCode - Process exit code

Methods

  • isSuccessful(): bool - Returns true when exitCode === 0

CommandExecutorException

Exception thrown when command execution fails.

Methods

  • getCommandOutput(): ?string - Returns the command output
  • getExitCode(): ?int - Returns the exit code
  • fromCommandFailure() - 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

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Run quality checks (composer quality)
  4. Commit your changes (git commit -m 'Add amazing feature')
  5. Push to the branch (git push origin feature/amazing-feature)
  6. 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.