提交 ac3100bc 编写于 作者: A antirez

Set process name in ps output to make operations safer.

This commit allows Redis to set a process name that includes the binding
address and the port number in order to make operations simpler.

Redis children processes doing AOF rewrites or RDB saving change the
name into redis-aof-rewrite and redis-rdb-bgsave respectively.

This in general makes harder to kill the wrong process because of an
error and makes simpler to identify saving children.

This feature was suggested by Arnaud GRANAL in the Redis Google Group,
Arnaud also pointed me to the setproctitle.c implementation includeed in
this commit.

This feature should work on all the Linux, OSX, and all the three major
BSD systems.
上级 fedcd511
......@@ -99,7 +99,7 @@ endif
REDIS_SERVER_NAME= redis-server
REDIS_SENTINEL_NAME= redis-sentinel
REDIS_SERVER_OBJ= adlist.o ae.o anet.o dict.o redis.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o migrate.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o
REDIS_SERVER_OBJ= adlist.o ae.o anet.o dict.o redis.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o migrate.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o
REDIS_CLI_NAME= redis-cli
REDIS_CLI_OBJ= anet.o sds.o adlist.o redis-cli.o zmalloc.o release.o anet.o ae.o crc64.o
REDIS_BENCHMARK_NAME= redis-benchmark
......
......@@ -82,6 +82,7 @@ sentinel.o: sentinel.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \
ziplist.h intset.h version.h util.h rdb.h rio.h \
../deps/hiredis/hiredis.h ../deps/hiredis/async.h \
../deps/hiredis/hiredis.h
setproctitle.o: setproctitle.c
sha1.o: sha1.c sha1.h config.h
slowlog.o: slowlog.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \
../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \
......
......@@ -961,6 +961,7 @@ int rewriteAppendOnlyFileBackground(void) {
/* Child */
if (server.ipfd > 0) close(server.ipfd);
if (server.sofd > 0) close(server.sofd);
redisSetProcTitle("redis-aof-rewrite");
snprintf(tmpfile,256,"temp-rewriteaof-bg-%d.aof", (int) getpid());
if (rewriteAppendOnlyFile(tmpfile) == REDIS_OK) {
size_t private_dirty = zmalloc_get_private_dirty();
......
......@@ -105,6 +105,18 @@
#define rdb_fsync_range(fd,off,size) fsync(fd)
#endif
/* Check if we can use setproctitle().
* BSD systems have support for it, we provide an implementation for
* Linux and osx. */
#if (defined __NetBSD__ || defined __FreeBSD__ || defined __OpenBSD__)
#define USE_SETPROCTITLE
#endif
#if (defined __linux || defined __APPLE__)
#define USE_SETPROCTITLE
void setproctitle(const char *fmt, ...);
#endif
/* Byte ordering detection */
#include <sys/types.h> /* This will likely define BYTE_ORDER */
......
......@@ -730,6 +730,7 @@ int rdbSaveBackground(char *filename) {
/* Child */
if (server.ipfd > 0) close(server.ipfd);
if (server.sofd > 0) close(server.sofd);
redisSetProcTitle("redis-rdb-bgsave");
retval = rdbSave(filename);
if (retval == REDIS_OK) {
size_t private_dirty = zmalloc_get_private_dirty();
......
......@@ -2585,6 +2585,13 @@ void redisOutOfMemoryHandler(size_t allocation_size) {
redisPanic("OOM");
}
void redisSetProcTitle(char *title) {
setproctitle("%s %s:%d",
title,
server.bindaddr ? server.bindaddr : "*",
server.port);
}
int main(int argc, char **argv) {
struct timeval tv;
......@@ -2655,6 +2662,7 @@ int main(int argc, char **argv) {
if (server.daemonize) daemonize();
initServer();
if (server.daemonize) createPidFile();
redisSetProcTitle(argv[0]);
redisAsciiArt();
if (!server.sentinel_mode) {
......
......@@ -815,6 +815,7 @@ long long mstime(void);
void getRandomHexChars(char *p, unsigned int len);
uint64_t crc64(uint64_t crc, const unsigned char *s, uint64_t l);
void exitFromChild(int retcode);
void redisSetProcTitle(char *title);
/* networking.c -- Networking and Client related operations */
redisClient *createClient(int fd);
......
/* ==========================================================================
* setproctitle.c - Linux/Darwin setproctitle.
* --------------------------------------------------------------------------
* Copyright (C) 2010 William Ahern
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
* ==========================================================================
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stddef.h> /* NULL size_t */
#include <stdarg.h> /* va_list va_start va_end */
#include <stdlib.h> /* malloc(3) setenv(3) clearenv(3) setproctitle(3) getprogname(3) */
#include <stdio.h> /* vsnprintf(3) snprintf(3) */
#include <string.h> /* strlen(3) strchr(3) strdup(3) memset(3) memcpy(3) */
#include <errno.h> /* errno program_invocation_name program_invocation_short_name */
#if !defined(HAVE_SETPROCTITLE)
#define HAVE_SETPROCTITLE (defined __NetBSD__ || defined __FreeBSD__ || defined __OpenBSD__)
#endif
#if !HAVE_SETPROCTITLE
#if (defined __linux || defined __APPLE__) && defined __GNUC__
static struct {
/* original value */
const char *arg0;
/* title space available */
char *base, *end;
/* pointer to original nul character within base */
char *nul;
_Bool reset;
int error;
} SPT;
#ifndef SPT_MIN
#define SPT_MIN(a, b) (((a) < (b))? (a) : (b))
#endif
static inline size_t spt_min(size_t a, size_t b) {
return SPT_MIN(a, b);
} /* spt_min() */
/*
* For discussion on the portability of the various methods, see
* http://lists.freebsd.org/pipermail/freebsd-stable/2008-June/043136.html
*/
static int spt_clearenv(void) {
#if __GLIBC__
clearenv();
return 0;
#else
extern char **environ;
char **tmp;
if (!(tmp = malloc(sizeof *tmp)))
return errno;
tmp[0] = NULL;
environ = tmp;
return 0;
#endif
} /* spt_clearenv() */
static int spt_copyenv(char *oldenv[]) {
extern char **environ;
char *eq;
int i, error;
if (environ != oldenv)
return 0;
if ((error = spt_clearenv()))
goto error;
for (i = 0; oldenv[i]; i++) {
if (!(eq = strchr(oldenv[i], '=')))
continue;
*eq = '\0';
error = (0 != setenv(oldenv[i], eq + 1, 1))? errno : 0;
*eq = '=';
if (error)
goto error;
}
return 0;
error:
environ = oldenv;
return error;
} /* spt_copyenv() */
static int spt_copyargs(int argc, char *argv[]) {
char *tmp;
int i;
for (i = 1; i < argc || (i >= argc && argv[i]); i++) {
if (!argv[i])
continue;
if (!(tmp = strdup(argv[i])))
return errno;
argv[i] = tmp;
}
return 0;
} /* spt_copyargs() */
void spt_init(int argc, char *argv[], char *envp[]) __attribute__((constructor));
void spt_init(int argc, char *argv[], char *envp[]) {
char *base, *end, *nul, *tmp;
int i, error;
if (!(base = argv[0]))
return;
nul = &base[strlen(base)];
end = nul + 1;
for (i = 0; i < argc || (i >= argc && argv[i]); i++) {
if (!argv[i] || argv[i] < end)
continue;
end = argv[i] + strlen(argv[i]) + 1;
}
for (i = 0; envp[i]; i++) {
if (envp[i] < end)
continue;
end = envp[i] + strlen(envp[i]) + 1;
}
if (!(SPT.arg0 = strdup(argv[0])))
goto syerr;
#if __GLIBC__
if (!(tmp = strdup(program_invocation_name)))
goto syerr;
program_invocation_name = tmp;
if (!(tmp = strdup(program_invocation_short_name)))
goto syerr;
program_invocation_short_name = tmp;
#elif __APPLE__
if (!(tmp = strdup(getprogname())))
goto syerr;
setprogname(tmp);
#endif
if ((error = spt_copyenv(envp)))
goto error;
if ((error = spt_copyargs(argc, argv)))
goto error;
SPT.nul = nul;
SPT.base = base;
SPT.end = end;
return;
syerr:
error = errno;
error:
SPT.error = error;
} /* spt_init() */
#ifndef SPT_MAXTITLE
#define SPT_MAXTITLE 255
#endif
void setproctitle(const char *fmt, ...) {
char buf[SPT_MAXTITLE + 1]; /* use buffer in case argv[0] is passed */
va_list ap;
char *nul;
int len, error;
if (!SPT.base)
return;
if (fmt) {
va_start(ap, fmt);
len = vsnprintf(buf, sizeof buf, fmt, ap);
va_end(ap);
} else {
len = snprintf(buf, sizeof buf, "%s", SPT.arg0);
}
if (len <= 0)
{ error = errno; goto error; }
if (!SPT.reset) {
memset(SPT.base, 0, SPT.end - SPT.base);
SPT.reset = 1;
} else {
memset(SPT.base, 0, spt_min(sizeof buf, SPT.end - SPT.base));
}
len = spt_min(len, spt_min(sizeof buf, SPT.end - SPT.base) - 1);
memcpy(SPT.base, buf, len);
nul = &SPT.base[len];
if (nul < SPT.nul) {
*SPT.nul = '.';
} else if (nul == SPT.nul && &nul[1] < SPT.end) {
*SPT.nul = ' ';
*++nul = '\0';
}
return;
error:
SPT.error = error;
} /* setproctitle() */
#endif /* __linux || __APPLE__ */
#endif /* !HAVE_SETPROCTITLE */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册