> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Processi

> Esecuzione di comandi shell da Laravel con la facade Process: sincroni, asincroni e concorrenti.

## Introduzione

La facade `Process` di Laravel è un wrapper sottile del [componente Process di Symfony](https://symfony.com/doc/current/components/process.html).
Offre un'API concisa per invocare comandi shell dall'applicazione Laravel e gestirne il risultato.

```mermaid theme={null}
flowchart LR
    A["App Laravel"] --> B["Facade Process"]
    B --> C["Comando shell"]
    C --> D["ProcessResult<br>(output / exitCode)"]
    D --> A
```

## Avvio di un processo

`Process::run()` esegue in modo sincrono.

```php theme={null}
use Illuminate\Support\Facades\Process;

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

return $result->output();
```

L'istanza `ProcessResult` ha metodi per esaminare l'esito.

```php theme={null}
$result = Process::run('ls -la');

$result->command();
$result->successful();
$result->failed();
$result->output();       // stdout
$result->errorOutput();  // stderr
$result->exitCode();
```

### Lanciare un'eccezione al fallimento

Con `throw()` o `throwIf()` viene lanciata `ProcessFailedException` per exit code > 0.

```php theme={null}
$result = Process::run('ls -la')->throw();

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

## Opzioni

### Working directory

```php theme={null}
$result = Process::path(__DIR__)->run('ls -la');
```

### Standard input

```php theme={null}
$result = Process::input('Hello World')->run('cat');
```

### Timeout

Default 60s. Cambia con `timeout()`. Se scade, viene lanciata `ProcessTimedOutException`.

```php theme={null}
$result = Process::timeout(120)->run('bash import.sh');
```

Anche con `CarbonInterval`.

```php theme={null}
use function Illuminate\Support\minutes;

$result = Process::timeout(minutes(2))->run('bash import.sh');
```

Disabilitalo con `forever()`.

```php theme={null}
$result = Process::forever()->run('bash import.sh');
```

Idle timeout (nessuna uscita per N s):

```php theme={null}
$result = Process::timeout(60)->idleTimeout(30)->run('bash import.sh');
```

### Variabili d'ambiente

Con `env()`; le variabili di sistema vengono ereditate.

```php theme={null}
$result = Process::forever()
    ->env(['IMPORT_PATH' => __DIR__])
    ->run('bash import.sh');
```

Per rimuovere una variabile ereditata usa `false`.

```php theme={null}
$result = Process::forever()
    ->env(['LOAD_PATH' => false])
    ->run('bash import.sh');
```

### Disabilitare l'output

Per grandi output usa `quietly()` per risparmiare memoria.

```php theme={null}
$result = Process::quietly()->run('bash import.sh');
```

### Output in tempo reale

Passa una closure a `run()`.

```php theme={null}
$result = Process::run('ls -la', function (string $type, string $output) {
    echo $output;
});
```

## Pipeline

`Process::pipe()` collega output/input tra comandi.

```php theme={null}
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()) {
    // ...
}
```

Puoi anche passare un array di stringhe.

```php theme={null}
$result = Process::pipe([
    'cat example.txt',
    'grep -i "laravel"',
]);
```

Con `as()` identifichi la sorgente dell'output.

```php theme={null}
$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 = 'first' o 'second'
});
```

## Processi asincroni

Con `Process::start()`.

```php theme={null}
$process = Process::timeout(120)->start('bash import.sh');

while ($process->running()) {
    // Altro lavoro
}

$result = $process->wait();
```

### PID e segnali

```php theme={null}
$process = Process::start('bash import.sh');

return $process->id();

$process->signal(SIGUSR2);
```

### Output incrementale

```php theme={null}
$process = Process::timeout(120)->start('bash import.sh');

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

    sleep(1);
}
```

Aspettare fino a un output specifico:

```php theme={null}
$process = Process::start('bash import.sh');

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

### Verifica del timeout

```php theme={null}
$process = Process::timeout(120)->start('bash import.sh');

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

    sleep(1);
}
```

## Processi concorrenti

Con `Process::pool()`.

```php theme={null}
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();
```

`concurrently()` avvia e attende in una riga.

```php theme={null}
[$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();
```

### Nomi per i processi

```php theme={null}
$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();
```

Segnale all'intero pool:

```php theme={null}
$pool->signal(SIGUSR2);
```

## Test

### Fake dei processi

```php theme={null}
use Illuminate\Support\Facades\Process;

Process::fake();

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

Process::assertRan('bash import.sh');
```

Personalizza output ed exit code:

```php theme={null}
Process::fake([
    '*' => Process::result(
        output: 'Test output',
        errorOutput: 'Test error output',
        exitCode: 1,
    ),
]);
```

### Fake per comandi specifici

```php theme={null}
Process::fake([
    'cat *'    => Process::result(output: 'file contents'),
    'ls -la'   => Process::result(output: 'file listing'),
]);
```

### Sequenze

```php theme={null}
Process::fake([
    'ls *' => [
        Process::result('first time'),
        Process::result('second time'),
    ],
]);
```

### Asserzioni

| Metodo                                  | Descrizione                     |
| --------------------------------------- | ------------------------------- |
| `Process::assertRan('command')`         | Il comando è stato eseguito     |
| `Process::assertNotRan('command')`      | Il comando non è stato eseguito |
| `Process::assertRan(fn)`                | Verifica dettagli con closure   |
| `Process::assertRanTimes('command', 3)` | Numero di esecuzioni            |

### Prevenzione di processi sfuggiti

```php theme={null}
Process::preventStrayProcesses();

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

// Lancia eccezione: 'bash import.sh' non è fake
Process::run('bash import.sh');
```

## Pagine correlate

<Columns cols={2}>
  <Card title="Console Artisan" icon="terminal" href="/it/artisan">
    Crea comandi personalizzati che invocano processi.
  </Card>

  <Card title="Code" icon="list" href="/it/queues">
    Confronto con l'elaborazione asincrona.
  </Card>
</Columns>


## Related topics

- [WebSocket (Jetstream / Firehose)](/it/packages/laravel-bluesky/websocket.md)
- [Laravel Reverb](/it/reverb.md)
- [Concorrenza](/it/concurrency.md)
- [Introduzione al testing](/it/testing.md)
- [Cache](/it/cache.md)
