日志服务在启动时必定会开启,无论你怎么配置。如果不能开启,则整个进程也不能开启。而且日志服务是比其他服务早启动的服务。原因在于他要给其他服务提供服务。
1. 日志服务使用标准输出
默认情况下(即不配置一个C或者LUA服务文件给logservice
),使用的是自带的C实现的服务logger.so
, 此时如果没有配置logger
字段指定日志文件路径,则是输出到标准输出。
config.logger = optstring("logger", NULL);
config.logservice = optstring("logservice", "logger");
...
struct skynet_context *ctx = skynet_context_new(config->logservice, config->logger);
if (ctx == NULL) {
fprintf(stderr, "Can't launch %s service\n", config->logservice);
exit(1);
}
注意:在配置了daemon=/path/to/pid.file
时,进入了Daemon模式下,代码通过redirect_fds
函数把标准输入输出和错误输出都定位到/dev/null
。所以在这个模式下,不能使用标准输入和输出。
2. 日志服务使用单一文件
不配置logservice
字段,只配置logger
字段指定文件全路径即可。
弊端是在长时间服务时,无法自动切日志。比如日志太大时。
3. 日志使用自带Lua服务
如下配置, 其中logger
不再是上面使用的文件,而是Lua服务的启动脚本。
logger = "log-service"
logservice = "snlua"
4. 日志服务的信号处理
当进程收到挂起信号时,只会通知日志服务。所以需要监听这个信号时,做好协议处理即可。
static int SIG = 0;
static void
handle_hup(int signal) {
if (signal == SIGHUP) {
SIG = 1;
}
}
void
skynet_start(struct skynet_config * config) {
// register SIGHUP for log file reopen struct sigaction sa;
sa.sa_handler = &handle_hup;
sa.sa_flags = SA_RESTART;
sigfillset(&sa.sa_mask);
sigaction(SIGHUP, &sa, NULL);
//...
}
static void
signal_hup() {
// make log file reopen
struct skynet_message smsg;
smsg.source = 0;
smsg.session = 0;
smsg.data = NULL;
smsg.sz = (size_t)PTYPE_SYSTEM << MESSAGE_TYPE_SHIFT;
uint32_t logger = skynet_handle_findname("logger");
if (logger) {
skynet_context_push(logger, &smsg);
}
}
static void *
thread_timer(void *p) {
struct monitor * m = p;
skynet_initthread(THREAD_TIMER);
for (;;) {
skynet_updatetime();
skynet_socket_updatetime();
CHECK_ABORT
wakeup(m,m->count-1);
usleep(2500);
if (SIG) {
signal_hup();
SIG = 0;
}
}
//...
//...
}
5. 日志服务处理自带日志
日志服务也要处理这类日志。此外说的自带日志是指通过C接口skynet_error
发送到日志服务的日志,在Lua层即skynet.error(...)
产生的日志。
评论 (0)