FileSystemWatcher: 파일 시스템 모니터링
FileSystemWatcher란
Async\FileSystemWatcher는 파일 및 디렉토리 변경 사항에 대한 영구적인 관찰자입니다.
일회성 접근 방식과 달리, FileSystemWatcher는 지속적으로 실행되며 표준 foreach 반복을 통해 이벤트를 전달합니다:
<?php
use Async\FileSystemWatcher;
$watcher = new FileSystemWatcher('/path/to/dir');
foreach ($watcher as $event) {
echo "{$event->filename}: renamed={$event->renamed}, changed={$event->changed}\n";
}
?>
반복은 버퍼가 비어 있을 때 자동으로 코루틴을 일시 중단하고 새 이벤트가 도착하면 재개합니다.
FileSystemEvent
각 이벤트는 네 개의 readonly 속성을 가진 Async\FileSystemEvent 객체입니다:
| 속성 | 타입 | 설명 |
|---|---|---|
path |
string |
FileSystemWatcher 생성자에 전달된 경로 |
filename |
?string |
이벤트를 발생시킨 파일 이름 (null일 수 있음) |
renamed |
bool |
true – 파일이 생성, 삭제 또는 이름 변경됨 |
changed |
bool |
true – 파일 내용이 수정됨 |
두 가지 버퍼링 모드
Coalesce (기본값)
coalesce 모드에서는 path/filename 키로 이벤트가 그룹화됩니다. 반복자가 처리하기 전에 파일이 여러 번 변경된 경우, 버퍼에는 병합된 플래그를 가진 하나의 이벤트만 남습니다:
<?php
use Async\FileSystemWatcher;
// coalesce: true -- 기본값
$watcher = new FileSystemWatcher('/tmp/dir');
?>
이는 일반적인 시나리오에 최적입니다: 핫 리로드, 설정 변경 재빌드, 동기화.
Raw
raw 모드에서는 OS의 각 이벤트가 순환 버퍼에 별도의 요소로 저장됩니다:
<?php
use Async\FileSystemWatcher;
$watcher = new FileSystemWatcher('/tmp/dir', coalesce: false);
?>
정확한 순서와 이벤트 수가 중요한 경우에 적합합니다 – 감사, 로깅, 복제.
생성자
new FileSystemWatcher(
string $path,
bool $recursive = false,
bool $coalesce = true
)
path – 파일 또는 디렉토리 경로. 경로가 존재하지 않으면 Error가 발생합니다.
recursive – true이면 중첩 디렉토리도 모니터링됩니다.
coalesce – 버퍼링 모드: true – 이벤트 병합 (HashTable), false – 모든 이벤트 (순환 버퍼).
모니터링은 객체 생성 즉시 시작됩니다. 이벤트는 반복이 시작되기 전에도 버퍼링됩니다.
수명 주기
close()
모니터링을 중지합니다. 현재 반복은 버퍼에 남아 있는 이벤트를 처리한 후 종료됩니다. 멱등성 – 반복 호출이 안전합니다.
<?php
$watcher->close();
?>
isClosed()
<?php
$watcher->isClosed(); // bool
?>
자동 닫기
FileSystemWatcher 객체가 파괴되면(스코프를 벗어남) 모니터링이 자동으로 중지됩니다.
예제
핫 리로드 설정
<?php
use Async\FileSystemWatcher;
use function Async\spawn;
spawn(function() {
$watcher = new FileSystemWatcher('/etc/myapp', recursive: true);
foreach ($watcher as $event) {
if (str_ends_with($event->filename ?? '', '.yml')) {
echo "Config changed: {$event->filename}\n";
reloadConfig();
}
}
});
?>
시간 제한 모니터링
<?php
use Async\FileSystemWatcher;
use function Async\spawn;
use function Async\delay;
$watcher = new FileSystemWatcher('/tmp/uploads');
spawn(function() use ($watcher) {
delay(30_000);
$watcher->close();
});
foreach ($watcher as $event) {
processUpload($event->filename);
}
echo "Monitoring finished\n";
?>
여러 디렉토리 모니터링
<?php
use Async\FileSystemWatcher;
use function Async\spawn;
$dirs = ['/var/log/app', '/var/log/nginx', '/var/log/postgres'];
foreach ($dirs as $dir) {
spawn(function() use ($dir) {
$watcher = new FileSystemWatcher($dir);
foreach ($watcher as $event) {
echo "[{$dir}] {$event->filename}\n";
}
});
}
?>
감사를 위한 Raw 모드
<?php
use Async\FileSystemWatcher;
use function Async\spawn;
spawn(function() {
$watcher = new FileSystemWatcher('/secure/data', coalesce: false);
foreach ($watcher as $event) {
$type = $event->renamed ? 'RENAME' : 'CHANGE';
auditLog("[{$type}] {$event->path}/{$event->filename}");
}
});
?>
Scope를 통한 취소
FileSystemWatcher는 스코프가 취소되면 올바르게 종료됩니다:
<?php
use Async\FileSystemWatcher;
use function Async\spawn;
use function Async\delay;
spawn(function() {
$watcher = new FileSystemWatcher('/tmp/test');
spawn(function() use ($watcher) {
foreach ($watcher as $event) {
echo "{$event->filename}\n";
}
echo "Iteration finished\n";
});
delay(5000);
$watcher->close();
});
?>