Improve and clean up supervised process support. (#8036)
* Configuration file default should now be "auto". * Expose "process_supervised" as an info field. * Log messages improvements (clarify required systemd config, report auto-detected supervision mode, etc.) * Set server.supervised properly, so it can take precedence of "daemonize" configuration. * Produce clear warning if systemd is detected/requested but executable is compiled without support for it, instead of silently ignoring. * Handle systemd notification error on startup, and turn off supervised mode if it failed.
This commit is contained in:
parent
ea7cf737a1
commit
d638b05834
@ -228,6 +228,7 @@ tcp-keepalive 300
|
|||||||
|
|
||||||
# By default Redis does not run as a daemon. Use 'yes' if you need it.
|
# By default Redis does not run as a daemon. Use 'yes' if you need it.
|
||||||
# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
|
# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
|
||||||
|
# When Redis is supervised by upstart or systemd, this parameter has no impact.
|
||||||
daemonize no
|
daemonize no
|
||||||
|
|
||||||
# If you run Redis from upstart or systemd, Redis can interact with your
|
# If you run Redis from upstart or systemd, Redis can interact with your
|
||||||
@ -236,11 +237,17 @@ daemonize no
|
|||||||
# supervised upstart - signal upstart by putting Redis into SIGSTOP mode
|
# supervised upstart - signal upstart by putting Redis into SIGSTOP mode
|
||||||
# requires "expect stop" in your upstart job config
|
# requires "expect stop" in your upstart job config
|
||||||
# supervised systemd - signal systemd by writing READY=1 to $NOTIFY_SOCKET
|
# supervised systemd - signal systemd by writing READY=1 to $NOTIFY_SOCKET
|
||||||
|
# on startup, and updating Redis status on a regular
|
||||||
|
# basis.
|
||||||
# supervised auto - detect upstart or systemd method based on
|
# supervised auto - detect upstart or systemd method based on
|
||||||
# UPSTART_JOB or NOTIFY_SOCKET environment variables
|
# UPSTART_JOB or NOTIFY_SOCKET environment variables
|
||||||
# Note: these supervision methods only signal "process is ready."
|
# Note: these supervision methods only signal "process is ready."
|
||||||
# They do not enable continuous pings back to your supervisor.
|
# They do not enable continuous pings back to your supervisor.
|
||||||
supervised no
|
#
|
||||||
|
# The default is "no". To run under upstart/systemd, you can simply uncomment
|
||||||
|
# the line below:
|
||||||
|
#
|
||||||
|
# supervised auto
|
||||||
|
|
||||||
# If a pid file is specified, Redis writes it where specified at startup
|
# If a pid file is specified, Redis writes it where specified at startup
|
||||||
# and removes it at exit.
|
# and removes it at exit.
|
||||||
|
101
src/server.c
101
src/server.c
@ -4247,11 +4247,20 @@ sds genRedisInfoString(const char *section) {
|
|||||||
static int call_uname = 1;
|
static int call_uname = 1;
|
||||||
static struct utsname name;
|
static struct utsname name;
|
||||||
char *mode;
|
char *mode;
|
||||||
|
char *supervised;
|
||||||
|
|
||||||
if (server.cluster_enabled) mode = "cluster";
|
if (server.cluster_enabled) mode = "cluster";
|
||||||
else if (server.sentinel_mode) mode = "sentinel";
|
else if (server.sentinel_mode) mode = "sentinel";
|
||||||
else mode = "standalone";
|
else mode = "standalone";
|
||||||
|
|
||||||
|
if (server.supervised) {
|
||||||
|
if (server.supervised_mode == SUPERVISED_UPSTART) supervised = "upstart";
|
||||||
|
else if (server.supervised_mode == SUPERVISED_SYSTEMD) supervised = "systemd";
|
||||||
|
else supervised = "unknown";
|
||||||
|
} else {
|
||||||
|
supervised = "no";
|
||||||
|
}
|
||||||
|
|
||||||
if (sections++) info = sdscat(info,"\r\n");
|
if (sections++) info = sdscat(info,"\r\n");
|
||||||
|
|
||||||
if (call_uname) {
|
if (call_uname) {
|
||||||
@ -4275,6 +4284,7 @@ sds genRedisInfoString(const char *section) {
|
|||||||
"atomicvar_api:%s\r\n"
|
"atomicvar_api:%s\r\n"
|
||||||
"gcc_version:%i.%i.%i\r\n"
|
"gcc_version:%i.%i.%i\r\n"
|
||||||
"process_id:%I\r\n"
|
"process_id:%I\r\n"
|
||||||
|
"process_supervised:%s\r\n"
|
||||||
"run_id:%s\r\n"
|
"run_id:%s\r\n"
|
||||||
"tcp_port:%i\r\n"
|
"tcp_port:%i\r\n"
|
||||||
"uptime_in_seconds:%I\r\n"
|
"uptime_in_seconds:%I\r\n"
|
||||||
@ -4300,6 +4310,7 @@ sds genRedisInfoString(const char *section) {
|
|||||||
0,0,0,
|
0,0,0,
|
||||||
#endif
|
#endif
|
||||||
(int64_t) getpid(),
|
(int64_t) getpid(),
|
||||||
|
supervised,
|
||||||
server.runid,
|
server.runid,
|
||||||
server.port ? server.port : server.tls_port,
|
server.port ? server.port : server.tls_port,
|
||||||
(int64_t)uptime,
|
(int64_t)uptime,
|
||||||
@ -5224,62 +5235,82 @@ void redisSetCpuAffinity(const char *cpulist) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Send a notify message to systemd. Returns sd_notify return code which is
|
||||||
* Check whether systemd or upstart have been used to start redis.
|
* a positive number on success. */
|
||||||
*/
|
int redisCommunicateSystemd(const char *sd_notify_msg) {
|
||||||
|
#ifdef HAVE_LIBSYSTEMD
|
||||||
|
int ret = sd_notify(0, sd_notify_msg);
|
||||||
|
|
||||||
int redisSupervisedUpstart(void) {
|
if (ret == 0)
|
||||||
|
serverLog(LL_WARNING, "systemd supervision error: NOTIFY_SOCKET not found!");
|
||||||
|
else if (ret < 0)
|
||||||
|
serverLog(LL_WARNING, "systemd supervision error: sd_notify: %d", ret);
|
||||||
|
return ret;
|
||||||
|
#else
|
||||||
|
UNUSED(sd_notify_msg);
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attempt to set up upstart supervision. Returns 1 if successful. */
|
||||||
|
static int redisSupervisedUpstart(void) {
|
||||||
const char *upstart_job = getenv("UPSTART_JOB");
|
const char *upstart_job = getenv("UPSTART_JOB");
|
||||||
|
|
||||||
if (!upstart_job) {
|
if (!upstart_job) {
|
||||||
serverLog(LL_WARNING,
|
serverLog(LL_WARNING,
|
||||||
"upstart supervision requested, but UPSTART_JOB not found");
|
"upstart supervision requested, but UPSTART_JOB not found!");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
serverLog(LL_NOTICE, "supervised by upstart, will stop to signal readiness");
|
serverLog(LL_NOTICE, "supervised by upstart, will stop to signal readiness.");
|
||||||
raise(SIGSTOP);
|
raise(SIGSTOP);
|
||||||
unsetenv("UPSTART_JOB");
|
unsetenv("UPSTART_JOB");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int redisCommunicateSystemd(const char *sd_notify_msg) {
|
/* Attempt to set up systemd supervision. Returns 1 if successful. */
|
||||||
const char *notify_socket = getenv("NOTIFY_SOCKET");
|
static int redisSupervisedSystemd(void) {
|
||||||
if (!notify_socket) {
|
#ifndef HAVE_LIBSYSTEMD
|
||||||
serverLog(LL_WARNING,
|
serverLog(LL_WARNING,
|
||||||
"systemd supervision requested, but NOTIFY_SOCKET not found");
|
"systemd supervision requested or auto-detected, but Redis is compiled without libsystemd support!");
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_LIBSYSTEMD
|
|
||||||
(void) sd_notify(0, sd_notify_msg);
|
|
||||||
#else
|
|
||||||
UNUSED(sd_notify_msg);
|
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
|
#else
|
||||||
|
if (redisCommunicateSystemd("STATUS=Redis is loading...\n") <= 0)
|
||||||
|
return 0;
|
||||||
|
serverLog(LL_NOTICE,
|
||||||
|
"Supervised by systemd. Please make sure you set appropriate values for TimeoutStartSec and TimeoutStopSec in your service unit.");
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int redisIsSupervised(int mode) {
|
int redisIsSupervised(int mode) {
|
||||||
if (mode == SUPERVISED_AUTODETECT) {
|
int ret = 0;
|
||||||
const char *upstart_job = getenv("UPSTART_JOB");
|
|
||||||
const char *notify_socket = getenv("NOTIFY_SOCKET");
|
|
||||||
|
|
||||||
if (upstart_job) {
|
if (mode == SUPERVISED_AUTODETECT) {
|
||||||
redisSupervisedUpstart();
|
if (getenv("UPSTART_JOB")) {
|
||||||
} else if (notify_socket) {
|
serverLog(LL_VERBOSE, "Upstart supervision detected.");
|
||||||
server.supervised_mode = SUPERVISED_SYSTEMD;
|
mode = SUPERVISED_UPSTART;
|
||||||
serverLog(LL_WARNING,
|
} else if (getenv("NOTIFY_SOCKET")) {
|
||||||
"WARNING auto-supervised by systemd - you MUST set appropriate values for TimeoutStartSec and TimeoutStopSec in your service unit.");
|
serverLog(LL_VERBOSE, "Systemd supervision detected.");
|
||||||
return redisCommunicateSystemd("STATUS=Redis is loading...\n");
|
mode = SUPERVISED_SYSTEMD;
|
||||||
}
|
}
|
||||||
} else if (mode == SUPERVISED_UPSTART) {
|
|
||||||
return redisSupervisedUpstart();
|
|
||||||
} else if (mode == SUPERVISED_SYSTEMD) {
|
|
||||||
serverLog(LL_WARNING,
|
|
||||||
"WARNING supervised by systemd - you MUST set appropriate values for TimeoutStartSec and TimeoutStopSec in your service unit.");
|
|
||||||
return redisCommunicateSystemd("STATUS=Redis is loading...\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
switch (mode) {
|
||||||
|
case SUPERVISED_UPSTART:
|
||||||
|
ret = redisSupervisedUpstart();
|
||||||
|
break;
|
||||||
|
case SUPERVISED_SYSTEMD:
|
||||||
|
ret = redisSupervisedSystemd();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
server.supervised_mode = mode;
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int iAmMaster(void) {
|
int iAmMaster(void) {
|
||||||
|
Loading…
Reference in New Issue
Block a user