Support for command line configuration options for redis-server.

This commit is contained in:
antirez 2011-12-01 13:44:53 +01:00
parent 4c8bd905a0
commit 67c6f0f630
3 changed files with 81 additions and 37 deletions

View File

@ -23,39 +23,25 @@ void resetServerSaveParams() {
server.saveparamslen = 0; server.saveparamslen = 0;
} }
/* I agree, this is a very rudimental way to load a configuration... void loadServerConfigFromString(char *config) {
will improve later if the config gets more complex */ char *err = NULL;
void loadServerConfig(char *filename) { int linenum = 0, totlines, i;
FILE *fp; sds *lines;
char buf[REDIS_CONFIGLINE_MAX+1], *err = NULL;
int linenum = 0;
sds line = NULL;
if (filename[0] == '-' && filename[1] == '\0') lines = sdssplitlen(config,strlen(config),"\n",1,&totlines);
fp = stdin;
else {
if ((fp = fopen(filename,"r")) == NULL) {
redisLog(REDIS_WARNING, "Fatal error, can't open config file '%s'", filename);
exit(1);
}
}
while(fgets(buf,REDIS_CONFIGLINE_MAX+1,fp) != NULL) { for (i = 0; i < totlines; i++) {
sds *argv; sds *argv;
int argc, j; int argc;
linenum++; linenum = i+1;
line = sdsnew(buf); lines[i] = sdstrim(lines[i]," \t\r\n");
line = sdstrim(line," \t\r\n");
/* Skip comments and blank lines*/ /* Skip comments and blank lines*/
if (line[0] == '#' || line[0] == '\0') { if (lines[i][0] == '#' || lines[i][0] == '\0') continue;
sdsfree(line);
continue;
}
/* Split into arguments */ /* Split into arguments */
argv = sdssplitargs(line,&argc); argv = sdssplitargs(lines[i],&argc);
sdstolower(argv[0]); sdstolower(argv[0]);
/* Execute config directives */ /* Execute config directives */
@ -162,7 +148,7 @@ void loadServerConfig(char *filename) {
err = "Invalid number of databases"; goto loaderr; err = "Invalid number of databases"; goto loaderr;
} }
} else if (!strcasecmp(argv[0],"include") && argc == 2) { } else if (!strcasecmp(argv[0],"include") && argc == 2) {
loadServerConfig(argv[1]); loadServerConfig(argv[1],NULL);
} else if (!strcasecmp(argv[0],"maxclients") && argc == 2) { } else if (!strcasecmp(argv[0],"maxclients") && argc == 2) {
server.maxclients = atoi(argv[1]); server.maxclients = atoi(argv[1]);
} else if (!strcasecmp(argv[0],"maxmemory") && argc == 2) { } else if (!strcasecmp(argv[0],"maxmemory") && argc == 2) {
@ -325,22 +311,56 @@ void loadServerConfig(char *filename) {
} else { } else {
err = "Bad directive or wrong number of arguments"; goto loaderr; err = "Bad directive or wrong number of arguments"; goto loaderr;
} }
for (j = 0; j < argc; j++) sdsfreesplitres(argv,argc);
sdsfree(argv[j]);
zfree(argv);
sdsfree(line);
} }
if (fp != stdin) fclose(fp); sdsfreesplitres(lines,totlines);
return; return;
loaderr: loaderr:
fprintf(stderr, "\n*** FATAL CONFIG FILE ERROR ***\n"); fprintf(stderr, "\n*** FATAL CONFIG FILE ERROR ***\n");
fprintf(stderr, "Reading the configuration file, at line %d\n", linenum); fprintf(stderr, "Reading the configuration file, at line %d\n", linenum);
fprintf(stderr, ">>> '%s'\n", line); fprintf(stderr, ">>> '%s'\n", lines[i]);
fprintf(stderr, "%s\n", err); fprintf(stderr, "%s\n", err);
exit(1); exit(1);
} }
/* Load the server configuration from the specified filename.
* The function appends the additional configuration directives stored
* in the 'options' string to the config file before loading.
*
* Both filename and options can be NULL, in such a case are considered
* emtpy. This way loadServerConfig can be used to just load a file or
* just load a string. */
void loadServerConfig(char *filename, char *options) {
sds config = sdsempty();
char buf[REDIS_CONFIGLINE_MAX+1];
/* Load the file content */
if (filename) {
FILE *fp;
if (filename[0] == '-' && filename[1] == '\0') {
fp = stdin;
} else {
if ((fp = fopen(filename,"r")) == NULL) {
redisLog(REDIS_WARNING,
"Fatal error, can't open config file '%s'", filename);
exit(1);
}
}
while(fgets(buf,REDIS_CONFIGLINE_MAX+1,fp) != NULL)
config = sdscat(config,buf);
if (fp != stdin) fclose(fp);
}
/* Append the additional options */
if (options) {
config = sdscat(config,"\n");
config = sdscat(config,options);
}
loadServerConfigFromString(config);
sdsfree(config);
}
/*----------------------------------------------------------------------------- /*-----------------------------------------------------------------------------
* CONFIG command for remote configuration * CONFIG command for remote configuration
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/

View File

@ -2008,15 +2008,39 @@ int main(int argc, char **argv) {
zmalloc_enable_thread_safeness(); zmalloc_enable_thread_safeness();
initServerConfig(); initServerConfig();
if (argc == 2) { if (argc >= 2) {
int j = 1; /* First option to parse in argv[] */
sds options = sdsempty();
char *configfile = NULL;
/* Handle special options --help and --version */
if (strcmp(argv[1], "-v") == 0 || if (strcmp(argv[1], "-v") == 0 ||
strcmp(argv[1], "--version") == 0) version(); strcmp(argv[1], "--version") == 0) version();
if (strcmp(argv[1], "--help") == 0 || if (strcmp(argv[1], "--help") == 0 ||
strcmp(argv[1], "-h") == 0) usage(); strcmp(argv[1], "-h") == 0) usage();
/* First argument is the config file name? */
if (argv[j][0] != '-' || argv[j][1] != '-')
configfile = argv[j++];
/* All the other options are parsed and conceptually appended to the
* configuration file. For instance --port 6380 will generate the
* string "port 6380\n" to be parsed after the actual file name
* is parsed, if any. */
while(j != argc) {
if (argv[j][0] == '-' && argv[j][1] == '-') {
/* Option name */
if (sdslen(options)) options = sdscat(options,"\n");
options = sdscat(options,argv[j]+2);
options = sdscat(options," ");
} else {
/* Option argument */
options = sdscatrepr(options,argv[j],strlen(argv[j]));
options = sdscat(options," ");
}
j++;
}
resetServerSaveParams(); resetServerSaveParams();
loadServerConfig(argv[1]); loadServerConfig(configfile,options);
} else if ((argc > 2)) { sdsfree(options);
usage();
} else { } else {
redisLog(REDIS_WARNING,"Warning: no config file specified, using the default config. In order to specify a config file use 'redis-server /path/to/redis.conf'"); redisLog(REDIS_WARNING,"Warning: no config file specified, using the default config. In order to specify a config file use 'redis-server /path/to/redis.conf'");
} }

View File

@ -954,7 +954,7 @@ int listMatchPubsubPattern(void *a, void *b);
int pubsubPublishMessage(robj *channel, robj *message); int pubsubPublishMessage(robj *channel, robj *message);
/* Configuration */ /* Configuration */
void loadServerConfig(char *filename); void loadServerConfig(char *filename, char *options);
void appendServerSaveParams(time_t seconds, int changes); void appendServerSaveParams(time_t seconds, int changes);
void resetServerSaveParams(); void resetServerSaveParams();