메인 콘텐츠로 건너뛰기

시작하기

Laravel의 Process 파사드는 Symfony Process 컴포넌트의 얇은 래퍼입니다. 셸 명령을 Laravel 애플리케이션에서 호출하고, 그 결과를 다루기 위한 간결한 API를 제공합니다.

프로세스 실행

Process::run()을 사용하면 명령을 동기적으로 실행하고 결과를 가져올 수 있습니다.
use Illuminate\Support\Facades\Process;

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

return $result->output();
ProcessResult 인스턴스에는 결과를 확인하기 위한 다양한 메서드가 마련되어 있습니다.
$result = Process::run('ls -la');

$result->command();       // 실행한 명령
$result->successful();    // 성공했는지 (종료 코드 0)
$result->failed();        // 실패했는지 (종료 코드 0 이외)
$result->output();        // 표준 출력 (stdout)
$result->errorOutput();   // 표준 에러 출력 (stderr)
$result->exitCode();      // 종료 코드

실패 시 예외 던지기

종료 코드가 0보다 큰 경우 Illuminate\Process\Exceptions\ProcessFailedException을 던지게 하려면 throw() 또는 throwIf()를 사용합니다.
$result = Process::run('ls -la')->throw();

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

프로세스 옵션

작업 디렉터리

path()로 작업 디렉터리를 지정할 수 있습니다. 생략하면 현재 PHP 스크립트의 작업 디렉터리가 사용됩니다.
$result = Process::path(__DIR__)->run('ls -la');

표준 입력

input()으로 프로세스의 표준 입력에 데이터를 전달할 수 있습니다.
$result = Process::input('Hello World')->run('cat');

타임아웃

기본값은 60초입니다. timeout()으로 변경할 수 있습니다. 타임아웃이 발생하면 프로세스가 중단되고 ProcessTimedOutException이 던져집니다.
$result = Process::timeout(120)->run('bash import.sh');
CarbonInterval 헬퍼 함수도 사용할 수 있습니다.
use function Illuminate\Support\minutes;

$result = Process::timeout(minutes(2))->run('bash import.sh');
타임아웃을 무효화하려면 forever()를 사용합니다.
$result = Process::forever()->run('bash import.sh');
아이들 타임아웃(출력이 없는 상태가 지속되는 초 수)을 설정할 수도 있습니다.
$result = Process::timeout(60)->idleTimeout(30)->run('bash import.sh');

환경 변수

env()로 환경 변수를 추가하거나 덮어쓸 수 있습니다. 시스템의 환경 변수는 자동으로 상속됩니다.
$result = Process::forever()
    ->env(['IMPORT_PATH' => __DIR__])
    ->run('bash import.sh');
상속된 변수를 제외하려면 false를 지정합니다.
$result = Process::forever()
    ->env(['LOAD_PATH' => false])
    ->run('bash import.sh');

출력 비활성화

대량의 출력이 필요 없는 경우 quietly()로 메모리 소비를 억제할 수 있습니다.
$result = Process::quietly()->run('bash import.sh');

실시간 출력

run()의 두 번째 인수에 클로저를 전달하면 출력을 실시간으로 받을 수 있습니다.
$result = Process::run('ls -la', function (string $type, string $output) {
    echo $output;
});

파이프라인

Process::pipe()를 사용하면 어떤 명령의 출력을 다음 명령의 입력으로 전달할 수 있습니다.
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()) {
    // ...
}
명령 문자열의 배열을 전달할 수도 있습니다.
$result = Process::pipe([
    'cat example.txt',
    'grep -i "laravel"',
]);
각 프로세스에 as()로 키를 붙이면, 출력 클로저에서 어느 프로세스의 출력인지 구분할 수 있습니다.
$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' 또는 'second'
});

비동기 프로세스

Process::start()를 사용하면 프로세스를 비동기로 실행할 수 있습니다. 프로세스가 실행 중인 동안 애플리케이션은 다른 처리를 계속할 수 있습니다.
$process = Process::timeout(120)->start('bash import.sh');

while ($process->running()) {
    // 다른 처리
}

$result = $process->wait();

프로세스 ID와 시그널

id()로 실행 중인 프로세스의 OS 프로세스 ID를 가져올 수 있습니다.
$process = Process::start('bash import.sh');

return $process->id();
signal()로 프로세스에 시그널을 보낼 수 있습니다.
$process->signal(SIGUSR2);

비동기 프로세스의 출력

실행 중에 latestOutput()latestErrorOutput()을 사용하면, 이전 취득 이후의 차분 출력을 가져올 수 있습니다.
$process = Process::timeout(120)->start('bash import.sh');

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

    sleep(1);
}
특정 출력이 나타날 때까지 대기하려면 waitUntil()을 사용합니다.
$process = Process::start('bash import.sh');

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

비동기 프로세스의 타임아웃 확인

루프 안에서 ensureNotTimedOut()을 호출하면, 타임아웃한 경우 예외가 던져집니다.
$process = Process::timeout(120)->start('bash import.sh');

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

    sleep(1);
}

병렬 프로세스

Process::pool()을 사용하면 여러 프로세스를 병렬로 실행할 수 있습니다.
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()를 사용하면 풀을 즉시 시작하고 결과를 기다리는 처리를 한 줄로 작성할 수 있습니다.
[$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();

프로세스에 이름 붙이기

as()로 각 프로세스에 문자열 키를 붙이면 결과의 취득이 명확해집니다.
$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();
풀 전체에 시그널을 보낼 수도 있습니다.
$pool->signal(SIGUSR2);

테스트

프로세스 페이크

Process::fake()를 사용하면 실제 셸 명령을 실행하지 않고 테스트할 수 있습니다.
use Illuminate\Support\Facades\Process;

Process::fake();

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

Process::assertRan('bash import.sh');
출력이나 종료 코드를 지정할 수도 있습니다.
Process::fake([
    '*' => Process::result(
        output: 'Test output',
        errorOutput: 'Test error output',
        exitCode: 1,
    ),
]);

특정 명령을 페이크하기

와일드카드나 명령 문자열을 키로 사용해 개별적으로 페이크를 설정할 수 있습니다.
Process::fake([
    'cat *'    => Process::result(output: 'file contents'),
    'ls -la'   => Process::result(output: 'file listing'),
]);

시퀀스 페이크

같은 명령을 여러 번 호출하는 경우, 반환되는 결과의 순서를 지정할 수 있습니다.
Process::fake([
    'ls *' => [
        Process::result('first time'),
        Process::result('second time'),
    ],
]);

어서션

메서드설명
Process::assertRan('command')명령이 실행되었음을 검증
Process::assertNotRan('command')명령이 실행되지 않았음을 검증
Process::assertRan(fn)클로저로 실행 내용을 상세히 검증
Process::assertRanTimes('command', 3)명령이 지정 횟수 실행되었음을 검증

예기치 않은 프로세스 방지

Process::preventStrayProcesses()를 호출하면 페이크가 설정되지 않은 명령이 실행된 경우 예외가 던져집니다.
Process::preventStrayProcesses();

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

// 예외: 'bash import.sh'에는 페이크가 설정되지 않음
Process::run('bash import.sh');

관련 페이지

Artisan 콘솔

커스텀 명령을 작성해 프로세스를 호출

비동기 처리와의 비교
마지막 수정일 2026년 7월 13일