【问题标题】:Running Redis in daemonized form and using Upstart to manage it doesn't work以守护程序形式运行 Redis 并使用 Upstart 管理它不起作用
【发布时间】:2011-12-29 23:43:05
【问题描述】:

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

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 以守护进程的形式分叉了两次,并且“期望守护进程”应该可以工作,但是 Upstart 脚本始终保留前父级的 PID (PID - 1)。有人搞定了吗?

【问题讨论】:

  • 我知道这是一些淫秽的问题死灵术,但是...为什么不使用daemonize no 并将expect 子句完全排除在您的新贵配置之外? (我问是因为我在 ubuntu 14 机器上设置 redis)

标签: redis daemon upstart


【解决方案1】:

以下 upstart 配置似乎对我有用,ubuntu 12.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

【讨论】:

    【解决方案2】:

    其他人也有同样的问题。见this gist

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

    有关守护进程的更多信息,请参阅this faq

    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 端停用守护进程,要么尝试在 upstart 配置中使用 expect fork 而不是 expect 守护进程。

    【讨论】:

    • 感谢您的回复。我的 strace 研究以及正常观察表明 Redis 分叉了两次。阅读代码,我不明白这是怎么可能的,但似乎是这样。另外,我确实尝试了“期望分叉”,但这并没有导致找到正确的 PID。我看过那个要点,但永远不能相信其他人已经做了深入的功课来解决根本问题。我认为 Upstart 的问题是守护进程。
    • 我刚刚在一个守护实例上尝试了一个简单的 strace -f src/redis-server redis.conf 2>strace.log ,它只分叉一次。请注意,在 Linux 上,clone 系统调用用于创建进程和线程(Redis 现在使用几个后台线程)。参数应该明确是线程还是进程。太糟糕了,“期待叉子”不能像我们预期的那样工作......
    • 好的,感谢您确认这是一个单叉。我肯定尝试过“期望分叉”但没有成功,但我可能会再试一次以确保。我会回来报告的。
    • 不走运,但我可能做错了什么。希望有人能代表我们解决这个问题。感谢迪迪埃的帮助。
    猜你喜欢
    • 2014-08-23
    • 2017-04-21
    • 2014-08-30
    • 1970-01-01
    • 1970-01-01
    • 2012-09-26
    • 2012-02-18
    • 1970-01-01
    • 2012-05-19
    相关资源
    最近更新 更多