PHP는 웹에 특화된 언어다. 그렇게 때문에 애플리케이션이나 시스템 프로그래밍을 할 때 필요한 기능이 부족하다. 하지만 서비스를 만들다 보면 서버(데몬)처럼 웹을 벗어난 것이 필요 할 때가 생긴다. 이럴 때는 아파치(Apache)나 crond를 이용해 문제를 해결 할 수 있다. 그러나 아파치나 crond를 이용한 방법은 어느 정도 한계가 있기 때문에 경우에 따라 해결책이 되지는 못 한다. 이런 경우 백그라운드로 동작하는 데몬을 만드는 것이 깔끔하다. 데몬을 만드는 방법은 널리 알려져있기 때문에 거기에 맞춰 코드를 작성해도 되지만, 굳이 바퀴를 다시 발명 할 필요는 없을테니 System_Daemon PEAR 모듈을 이용하면 된다. System_Daemon 모듈을 사용한 간단한 예제를 우선 살펴보자.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/local/php/bin/php -q
<?php
ini_set('include_path', ini_get('include_path').':..');

error_reporting(E_ALL);
require_once "System/Daemon.php";

$appname = "example";

System_Daemon::setOption("appName", $appname);
System_Daemon::setOption("appRunAsUID", getmyuid());
System_Daemon::setOption("appRunAsGID", getmygid());
System_Daemon::setOption("logLocation", getcwd()."/log/$appname.log");
System_Daemon::setOption("appPidLocation", getcwd()."/log/$appname/$appname.pid");

System_Daemon::start();
while ( true ) {
    System_Daemon::log(System_Daemon::LOG_INFO, "HELLO - ".time());
    sleep(1);
}
System_Daemon::stop();
?>

참고로 System_Daemon 모듈을 사용하기 위해서는 --enable-pcntl 옵션으로 컴파일 되어 있어야 한다. 1번째 줄의 php 경로는 각자 php 설정에 맞춰 수정하면 된다. System_Daemon 사용법은 간단하나 몇가지 조심해야 할 부분이 있다. appRunAsUIDappRunAsGID를 통해 특정 사용자나 그룹으로 실행하고 싶은 경우 root 권한이 필요하다.

또한 pid 파일은 다른 파일과 섞이지 않는 독립적인 디렉토리로 설정해야 하며, 자동으로 디렉토리를 생성해주지 않는다. 보통 로그 디렉토리 안에 log/foobar/foobar.pid 형식으로 구성한다고 보면 된다. 만약 root로 실행을 하거나 디렉토리 퍼미션을 잘 조정 해 줄 생각이라면 /var/run 안으로 구성하는 것이 더 좋겠다.

그리고 logLocation이나 appPidLocation 설정은 절대 경로로 해야 한다. 보통 프로세스가 데몬으로 바뀌면 워킹 디렉토리를 루트(/)로 설정을 하게 되는데, 이것에 영향을 받기 때문으로 보인다.

PEAR 사이트의 문서에는 옵션이 없으므로 어떤 옵션이 있는지 직접 소스 코드를 열어 읽어 봐두어야 한다. lib/php/System/Daemon.php 파일이다. php를 패키지로 설치한 경우 깊숙히 들어있으므로 locate 명령으로 찾는 것이 더 편하다. 전체 코드를 다 볼 필요는 없고 $_optionDefinitions 변수만 읽어 보면 된다.