1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
|
#!/usr/bin/php
<?php
$options = getopt('du:');
if ($options === FALSE) {
die("Failed to parse command line options\n");
}
$debug = isset($options['d']);
$user = isset($options['u']) ? $options['u'] : "veryimportantdaemon";
$pidfile = "/var/run/veryimportant.pid";
if (getmyuid() != 0) {
die("This script must be started as root (it will revoke its privileges)\n");
}
if (!($passwd = posix_getpwnam($user))) {
die("Failed to get passwd entry for user \"$user\"\n");
}
# Set the default timezone to the system's timezone.
if (function_exists("date_default_timezone_set") and
function_exists("date_default_timezone_get"))
@date_default_timezone_set(@date_default_timezone_get());
if (file_exists($pidfile)) {
$pid = rtrim(file_get_contents($pidfile));
if (posix_kill($pid, 0)) {
die("Failed to create pidfile $pidfile (PID $pid is still running)\n");
}
trigger_error("Removing stale pidfile $pidfile", E_USER_NOTICE);
unlink($pidfile);
}
# if debug ist not set open a child process
if (!$debug) {
$pid = pcntl_fork();
if ($pid == -1) {
die("Could not fork");
} else if ($pid) {
// We are the parent, we may exit now.
exit(0);
}
}
$pid = pcntl_fork();
if ($pid == -1) {
die("Could not fork again");
} else if ($pid) {
pcntl_signal(SIGINT, SIG_IGN);
pcntl_signal(SIGTERM, SIG_IGN);
// We are the parent. Write pidfile and wait until the child exists.
if (!file_put_contents($pidfile, "$pid\n")) {
posix_kill($pid, 15);
die("Failed to create pidfile $pidfile");
}
$child = pcntl_waitpid($pid, $status);
unlink($pidfile);
exit;
}
$uid = $passwd['uid'];
$gid = $passwd['gid'];
if (!posix_setgid($gid) or !posix_setuid($uid)) {
die("Failed revoke privileges to run as user \"$user\"\n");
}
function sig_handler($signo)
{
switch ($signo) {
case SIGINT:
case SIGTERM:
// handle shutdown tasks
Logger::info("Got signal $signo, exiting");
exit(128 + $signo);
}
}
function err_handler($errno, $errstr, $errfile, $errline, $errcontext)
{
switch ($errno) {
case E_USER_ERROR:
// print and exit
Logger::error("Fatal error: $errstr in $errfile on line $errline (exiting)");
case E_USER_WARNING:
Logger::warn("Warning: $errstr in $errfile on line $errline");
break;
case E_USER_NOTICE:
Logger::info("Notice: $errstr in $errfile on line $errline");
break;
default:
Logger::warn("Unknown error type $errno: $errstr in $errfile on line $errline");
break;
}
return TRUE;
}
/**
* basic logger
*
* Example usage:
* @code
* Logger::init(fopen("/var/log/veryimportant.log", "a"));
*
* Logger::info("Small info line");
* Logger::warn("A little warning");
* Logger::debug("Some sweet debug information");
* Logger::error("Houston, we've got a (serious) problem");
* @endcode
*/
class Logger {
private static $instance = NULL;
private $handle = null;
protected function __construct($handle) {
$this->handle = $handle;
register_shutdown_function(array(&$this, "__destruct"));
}
public function __destruct() {
if($this->handle) {
fclose($this->handle);
}
return true;
}
public function writeLog($level, $message) {
if($this->handle) {
fwrite($this->handle, sprintf("%s - %s - %s\n", date('r'), $level, $message));
}
}
private final function __clone() {}
private static function getInstance() {
if (self::$instance === NULL) {
throw new Exception('call init before');
}
return self::$instance;
}
public static function init($output) {
self::$instance = new self($output);
}
public static function info($message) {
self::getInstance()->writeLog('INFO', $message);
}
public static function warn($message) {
self::getInstance()->writeLog('WARN', $message);
}
public static function debug($message) {
self::getInstance()->writeLog('DEBUG', $message);
}
public static function error($message) {
self::getInstance()->writeLog('ERROR', $message);
exit;
}
}
set_error_handler("err_handler");
pcntl_signal(SIGINT, "sig_handler");
pcntl_signal(SIGTERM, "sig_handler");
# Enable the signal handle callback mechanism.
declare(ticks = 1);
# Open the output stream which should receive all log messages.
# if debug is set just print the messages - if not, then log to file
Logger::init($debug ? STDOUT : fopen("/var/log/veryimportant.log", "a"));
# program code
# run controller from here
# e.g. Controller::dispatch()
while(true) {
Logger::info("i am running");
sleep(1);
}
?>
|