以daemonized形式运行Redis并使用Upstart来管理它不会';行不通

以daemonized形式运行Redis并使用Upstart来管理它不会';行不通,redis,daemon,upstart,Redis,Daemon,Upstart,我为Redis编写了一个新贵脚本,如下所示: description "Redis Server" start on runlevel [2345] stop on shutdown expect daemon exec sudo -u redis /usr/local/bin/redis-server /etc/redis/redis.conf respawn respawn limit 10 5 然后,我通过redis.conf将redis配置为: daemonize yes 所有

我为Redis编写了一个新贵脚本,如下所示:

description "Redis Server"

start on runlevel [2345]
stop on shutdown
expect daemon

exec sudo -u redis /usr/local/bin/redis-server /etc/redis/redis.conf

respawn
respawn limit 10 5
然后,我通过redis.conf将redis配置为:

daemonize yes

所有的文档和我自己的实验都表明,Redis以daemonized的形式分叉两次,并且“expect daemon”应该可以工作,但是Upstart脚本始终保持前父脚本(PID-1)的PID。有人用过吗?

其他人也有同样的问题。看

当激活daemonize选项时,Redis不会检查进程是否已经是守护进程(没有对getppid的调用)。它系统地分叉,但只有一次。这有点不寻常,其他守护机制可能需要对getppid进行初始检查,并调用fork两次(在setsid调用之前和之后),但在Linux上这并不是严格要求的

有关守护进程的详细信息,请参阅

Redis daemonize功能非常简单:

void daemonize(void) {
    int fd;

    if (fork() != 0) exit(0); /* parent exits */
    setsid(); /* create a new session */

    /* Every output goes to /dev/null. If Redis is daemonized but
     * the 'logfile' is set to 'stdout' in the configuration file
     * it will not log at all. */
    if ((fd = open("/dev/null", O_RDWR, 0)) != -1) {
        dup2(fd, STDIN_FILENO);
        dup2(fd, STDOUT_FILENO);
        dup2(fd, STDERR_FILENO);
        if (fd > STDERR_FILENO) close(fd);
    }
}
Upstart文档说明:

expect daemon
Specifies that the job's main process is a daemon, and will fork twice after being run.
init(8) will follow this daemonisation, and will wait for this to occur before running
the job's post-start script or considering the job to be running.
Without this stanza init(8) is unable to supervise daemon processes and will
believe them to have stopped as soon as they daemonise on startup.

expect fork
Specifies that the job's main process will fork once after being run. init(8) will
follow this fork, and will wait for this to occur before running the job's post-start
script or considering the job to be running.
Without this stanza init(8) is unable to supervise forking processes and will believe
them to have stopped as soon as they fork on startup.

因此,我要么在Redis端停用daemonization,要么在upstart配置中尝试使用expect fork而不是expect daemon。

以下upstart配置似乎适合我,Ubuntu12.04上的upstart 1.5,Redis.conf daemonize设置为yes:

description "redis server"

start on (local-filesystems and net-device-up IFACE=eth0)
stop on shutdown

setuid redis
setgid redis
expect fork

exec /opt/redis/redis-server /opt/redis/redis.conf

respawn

谢谢你的回复。我的strace研究和正常观察表明,Redis分叉两次。阅读代码时,我不知道这是怎么可能的,但不知怎么的,它似乎是。此外,我尝试了“expect fork”,但没有找到正确的PID。我已经看到了这一要点,但人们永远不能相信其他人已经做了深入的功课来解决根本问题。我假设Upstart不存在daemonization的问题,我刚刚在一个daemonized实例上尝试了一个简单的strace-f src/redis server redis.conf 2>strace.log,它只运行了一次。请注意,在Linux上,克隆系统调用用于创建进程和线程(Redis现在使用两个后台线程)。参数应该明确它是线程还是进程。太糟糕了,“expect fork”没有像我们预期的那样工作……好的,谢谢你确认它是一个单独的fork。我确实尝试过“expect fork”,但没有成功,但我可能会再尝试一次,以确保成功。我会回去报告的。运气不好,但我可能做错了什么。希望有人能代表我们解决这个问题。谢谢你的帮助,迪迪埃。我知道这是一个关于巫术的淫秽问题,但是。。。为什么不使用
daemonize no
并将
expect
子句完全保留在upstart配置之外?(我这样问是因为我正在ubuntu 14上安装redis)