Saltar al contenido principal

Introducción

El facade Process de Laravel es un envoltorio ligero sobre el componente Process de Symfony. Ofrece una API concisa para ejecutar comandos de shell desde tu aplicación Laravel y tratar el resultado.

Arrancar un proceso

Con Process::run() ejecutas un comando de forma síncrona y obtienes el resultado.
use Illuminate\Support\Facades\Process;

$result = Process::run('ls -la');

return $result->output();
La instancia ProcessResult expone métodos para inspeccionar el resultado.
$result = Process::run('ls -la');

$result->command();       // Comando ejecutado
$result->successful();    // ¿Éxito? (código 0)
$result->failed();        // ¿Fallo? (código distinto de 0)
$result->output();        // Salida estándar (stdout)
$result->errorOutput();   // Salida de error (stderr)
$result->exitCode();      // Código de salida

Lanzar una excepción si falla

Para lanzar Illuminate\Process\Exceptions\ProcessFailedException cuando el código sea superior a 0, utiliza throw() o throwIf().
$result = Process::run('ls -la')->throw();

$result = Process::run('ls -la')->throwIf($condition);

Opciones del proceso

Directorio de trabajo

Indica el directorio con path(). Si lo omites, se utiliza el directorio actual del script PHP.
$result = Process::path(__DIR__)->run('ls -la');

Entrada estándar

Con input() pasas datos por la entrada estándar del proceso.
$result = Process::input('Hello World')->run('cat');

Timeout

Por defecto son 60 segundos. Cámbialo con timeout(). Si expira, el proceso se aborta y se lanza ProcessTimedOutException.
$result = Process::timeout(120)->run('bash import.sh');
También puedes usar helpers CarbonInterval.
use function Illuminate\Support\minutes;

$result = Process::timeout(minutes(2))->run('bash import.sh');
Para desactivar el timeout utiliza forever().
$result = Process::forever()->run('bash import.sh');
También hay un idle timeout (segundos consecutivos sin salida).
$result = Process::timeout(60)->idleTimeout(30)->run('bash import.sh');

Variables de entorno

Con env() añades o sobrescribes variables de entorno. Las del sistema se heredan automáticamente.
$result = Process::forever()
    ->env(['IMPORT_PATH' => __DIR__])
    ->run('bash import.sh');
Para excluir una variable heredada, asígnale false.
$result = Process::forever()
    ->env(['LOAD_PATH' => false])
    ->run('bash import.sh');

Desactivar la salida

Si no vas a usar salidas voluminosas, quietly() reduce el consumo de memoria.
$result = Process::quietly()->run('bash import.sh');

Salida en tiempo real

Pasando una closure como segundo argumento de run(), recibes la salida en streaming.
$result = Process::run('ls -la', function (string $type, string $output) {
    echo $output;
});

Pipelines

Con Process::pipe() la salida de un comando alimenta la entrada del siguiente.
use Illuminate\Process\Pipe;
use Illuminate\Support\Facades\Process;

$result = Process::pipe(function (Pipe $pipe) {
    $pipe->command('cat example.txt');
    $pipe->command('grep -i "laravel"');
});

if ($result->successful()) {
    // ...
}
También puedes pasar un array de comandos.
$result = Process::pipe([
    'cat example.txt',
    'grep -i "laravel"',
]);
Si asignas una clave con as() a cada proceso, la closure de salida puede identificar de cuál proviene la salida.
$result = Process::pipe(function (Pipe $pipe) {
    $pipe->as('first')->command('cat example.txt');
    $pipe->as('second')->command('grep -i "laravel"');
}, function (string $type, string $output, string $key) {
    // $key vale 'first' o 'second'
});

Procesos asíncronos

Con Process::start() arrancas un proceso en segundo plano. Tu aplicación puede seguir con otras tareas mientras se ejecuta.
$process = Process::timeout(120)->start('bash import.sh');

while ($process->running()) {
    // Otras tareas
}

$result = $process->wait();

PID y señales

Con id() obtienes el PID del proceso.
$process = Process::start('bash import.sh');

return $process->id();
Con signal() envías una señal al proceso.
$process->signal(SIGUSR2);

Salida de un proceso asíncrono

Durante la ejecución, latestOutput() y latestErrorOutput() devuelven la salida generada desde la última llamada.
$process = Process::timeout(120)->start('bash import.sh');

while ($process->running()) {
    echo $process->latestOutput();
    echo $process->latestErrorOutput();

    sleep(1);
}
Para esperar hasta que aparezca una determinada salida utiliza waitUntil().
$process = Process::start('bash import.sh');

$process->waitUntil(function (string $type, string $output) {
    return $output === 'Ready...';
});

Comprobar timeouts en asíncrono

Llamar a ensureNotTimedOut() dentro del bucle lanza una excepción si el proceso ha excedido el timeout.
$process = Process::timeout(120)->start('bash import.sh');

while ($process->running()) {
    $process->ensureNotTimedOut();

    sleep(1);
}

Procesos concurrentes

Con Process::pool() ejecutas varios procesos en paralelo.
use Illuminate\Process\Pool;
use Illuminate\Support\Facades\Process;

$pool = Process::pool(function (Pool $pool) {
    $pool->path(__DIR__)->command('bash import-1.sh');
    $pool->path(__DIR__)->command('bash import-2.sh');
    $pool->path(__DIR__)->command('bash import-3.sh');
})->start(function (string $type, string $output, int $key) {
    // ...
});

while ($pool->running()->isNotEmpty()) {
    // ...
}

$results = $pool->wait();
Con concurrently() arrancas el pool y esperas los resultados en una sola línea.
[$first, $second, $third] = Process::concurrently(function (Pool $pool) {
    $pool->path(__DIR__)->command('ls -la');
    $pool->path(app_path())->command('ls -la');
    $pool->path(storage_path())->command('ls -la');
});

echo $first->output();

Asignar nombres a los procesos

Con as() asignas una clave a cada proceso para acceder cómodamente al resultado.
$pool = Process::pool(function (Pool $pool) {
    $pool->as('first')->command('bash import-1.sh');
    $pool->as('second')->command('bash import-2.sh');
    $pool->as('third')->command('bash import-3.sh');
})->start(function (string $type, string $output, string $key) {
    // ...
});

$results = $pool->wait();

return $results['first']->output();
También puedes enviar una señal a todo el pool.
$pool->signal(SIGUSR2);

Pruebas

Fake de procesos

Con Process::fake() puedes escribir tests sin ejecutar comandos reales.
use Illuminate\Support\Facades\Process;

Process::fake();

$response = $this->get('/import');

Process::assertRan('bash import.sh');
Puedes especificar la salida y el código de salida.
Process::fake([
    '*' => Process::result(
        output: 'Test output',
        errorOutput: 'Test error output',
        exitCode: 1,
    ),
]);

Fake de comandos concretos

Con comodines o cadenas exactas como clave, puedes definir fakes distintos.
Process::fake([
    'cat *'    => Process::result(output: 'file contents'),
    'ls -la'   => Process::result(output: 'file listing'),
]);

Fakes en secuencia

Cuando se invoca varias veces el mismo comando, puedes definir el orden de las respuestas.
Process::fake([
    'ls *' => [
        Process::result('first time'),
        Process::result('second time'),
    ],
]);

Aserciones

MétodoDescripción
Process::assertRan('command')Verifica que se ejecutó el comando
Process::assertNotRan('command')Verifica que no se ejecutó
Process::assertRan(fn)Validación detallada con closure
Process::assertRanTimes('command', 3)Se ejecutó el número indicado de veces

Prevenir procesos no simulados

Al llamar a Process::preventStrayProcesses(), si se ejecuta un comando sin fake definido se lanza una excepción.
Process::preventStrayProcesses();

Process::fake([
    'ls *' => Process::result('file listing'),
]);

// Excepción: 'bash import.sh' no tiene fake
Process::run('bash import.sh');

Páginas relacionadas

Consola Artisan

Crea comandos personalizados que invoquen procesos.

Colas

Compáralo con el procesamiento asíncrono.
Última modificación el 13 de julio de 2026