mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-02-03 03:52:38 +00:00
MEDIUM: init: allow directory as argument of -f
If -f argument is a directory add all the files (and only files) it containes to the config files list. These files are added in lexical order (respecting LC_COLLATE). Only files with ".cfg" extension are added. Only non hidden files (not prefixed with ".") are added. Symlink are followed. The -f order is still respected: $ tree -a rootdir rootdir |-- dir1 ||-- .6.cfg ||-- 1.cfg ||-- 2 ||-- 3.cfg ||-- 4.cfg -> 1.cfg ||-- 5 -> 1.cfg ||-- 7.cfg -> . |`-- dir4 |`-- 8.cfg |-- dir2 ||-- 10.cfg |`-- 9.cfg |-- dir3 |`-- 11.cfg |-- link -> dir3/ |-- root1 |-- root2 `-- root3 $ ./haproxy -C rootdir -f root2 -f dir2 -f root3 -f dir1 \ -f link -f root1 root2 dir2/10.cfg dir2/9.cfg root3 dir1/1.cfg dir1/3.cfg dir1/4.cfg link/11.cfg root1 This can be useful on systemd where you can't change the haproxy commande line options on service reload.
This commit is contained in:
parent
0f503925f0
commit
379d9c7c14
@ -6,7 +6,7 @@ HAProxy \- fast and reliable http reverse proxy and load balancer
|
|||||||
|
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
|
||||||
haproxy \-f <configuration\ file> [\-L\ <name>] [\-n\ maxconn] [\-N\ maxconn] [\-C\ <dir>] [\-v|\-vv] [\-d] [\-D] [\-q] [\-V] [\-c] [\-p\ <pidfile>] [\-dk] [\-ds] [\-de] [\-dp] [\-db] [\-dM[<byte>]] [\-m\ <megs>] [{\-sf|\-st}\ pidlist...]
|
haproxy \-f <configuration\ file|dir> [\-L\ <name>] [\-n\ maxconn] [\-N\ maxconn] [\-C\ <dir>] [\-v|\-vv] [\-d] [\-D] [\-q] [\-V] [\-c] [\-p\ <pidfile>] [\-dk] [\-ds] [\-de] [\-dp] [\-db] [\-dM[<byte>]] [\-m\ <megs>] [{\-sf|\-st}\ pidlist...]
|
||||||
|
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
|
|
||||||
@ -33,8 +33,10 @@ instances without risking the system's stability.
|
|||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB\-f <configuration file>\fP
|
\fB\-f <configuration file|dir>\fP
|
||||||
Specify configuration file path.
|
Specify configuration file or directory path. If the argument is a directory
|
||||||
|
the files (and only files) it containes are added in lexical order (respecting
|
||||||
|
LC_COLLATE) ; only non hidden files with ".cfg" extension are added.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB\-L <name>\fP
|
\fB\-L <name>\fP
|
||||||
|
@ -124,26 +124,30 @@ enforce some settings without touching the configuration files. The current
|
|||||||
list of options is :
|
list of options is :
|
||||||
|
|
||||||
-- <cfgfile>* : all the arguments following "--" are paths to configuration
|
-- <cfgfile>* : all the arguments following "--" are paths to configuration
|
||||||
file to be loaded and processed in the declaration order. It is mostly
|
file/directory to be loaded and processed in the declaration order. It is
|
||||||
useful when relying on the shell to load many files that are numerically
|
mostly useful when relying on the shell to load many files that are
|
||||||
ordered. See also "-f". The difference between "--" and "-f" is that one
|
numerically ordered. See also "-f". The difference between "--" and "-f" is
|
||||||
"-f" must be placed before each file name, while a single "--" is needed
|
that one "-f" must be placed before each file name, while a single "--" is
|
||||||
before all file names. Both options can be used together, the command line
|
needed before all file names. Both options can be used together, the
|
||||||
ordering still applies. When more than one file is specified, each file
|
command line ordering still applies. When more than one file is specified,
|
||||||
must start on a section boundary, so the first keyword of each file must be
|
each file must start on a section boundary, so the first keyword of each
|
||||||
one of "global", "defaults", "peers", "listen", "frontend", "backend", and
|
file must be one of "global", "defaults", "peers", "listen", "frontend",
|
||||||
so on. A file cannot contain just a server list for example.
|
"backend", and so on. A file cannot contain just a server list for example.
|
||||||
|
|
||||||
-f <cfgfile> : adds <cfgfile> to the list of configuration files to be
|
-f <cfgfile|cfgdir> : adds <cfgfile> to the list of configuration files to be
|
||||||
loaded. Configuration files are loaded and processed in their declaration
|
loaded. If <cfgdir> is a directory, all the files (and only files) it
|
||||||
order. This option may be specified multiple times to load multiple files.
|
containes are added in lexical order (respecting LC_COLLATE) to the list of
|
||||||
See also "--". The difference between "--" and "-f" is that one "-f" must
|
configuration files to be loaded ; only files with ".cfg" extension are
|
||||||
be placed before each file name, while a single "--" is needed before all
|
added, only non hidden files (not prefixed with ".") are added.
|
||||||
file names. Both options can be used together, the command line ordering
|
Configuration files are loaded and processed in their declaration order.
|
||||||
still applies. When more than one file is specified, each file must start
|
This option may be specified multiple times to load multiple files. See
|
||||||
on a section boundary, so the first keyword of each file must be one of
|
also "--". The difference between "--" and "-f" is that one "-f" must be
|
||||||
"global", "defaults", "peers", "listen", "frontend", "backend", and so
|
placed before each file name, while a single "--" is needed before all file
|
||||||
on. A file cannot contain just a server list for example.
|
names. Both options can be used together, the command line ordering still
|
||||||
|
applies. When more than one file is specified, each file must start on a
|
||||||
|
section boundary, so the first keyword of each file must be one of
|
||||||
|
"global", "defaults", "peers", "listen", "frontend", "backend", and so on.
|
||||||
|
A file cannot contain just a server list for example.
|
||||||
|
|
||||||
-C <dir> : changes to directory <dir> before loading configuration
|
-C <dir> : changes to directory <dir> before loading configuration
|
||||||
files. This is useful when using relative paths. Warning when using
|
files. This is useful when using relative paths. Warning when using
|
||||||
|
110
src/haproxy.c
110
src/haproxy.c
@ -31,6 +31,9 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <locale.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
@ -423,7 +426,7 @@ void usage(char *name)
|
|||||||
{
|
{
|
||||||
display_version();
|
display_version();
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Usage : %s [-f <cfgfile>]* [ -vdV"
|
"Usage : %s [-f <cfgfile|cfgdir>]* [ -vdV"
|
||||||
"D ] [ -n <maxconn> ] [ -N <maxpconn> ]\n"
|
"D ] [ -n <maxconn> ] [ -N <maxpconn> ]\n"
|
||||||
" [ -p <pidfile> ] [ -m <max megs> ] [ -C <dir> ] [-- <cfgfile>*]\n"
|
" [ -p <pidfile> ] [ -m <max megs> ] [ -C <dir> ] [-- <cfgfile>*]\n"
|
||||||
" -v displays version ; -vv shows known build options.\n"
|
" -v displays version ; -vv shows known build options.\n"
|
||||||
@ -551,6 +554,99 @@ void dump(struct sig_handler *sh)
|
|||||||
pool_gc2();
|
pool_gc2();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This function check if cfg_cfgfiles containes directories.
|
||||||
|
* If it find one, it add all the files (and only files) it containes
|
||||||
|
* in cfg_cfgfiles in place of the directory (and remove the directory).
|
||||||
|
* It add the files in lexical order.
|
||||||
|
* It add only files with .cfg extension.
|
||||||
|
* It doesn't add files with name starting with '.'
|
||||||
|
*/
|
||||||
|
void cfgfiles_expand_directories(void)
|
||||||
|
{
|
||||||
|
struct wordlist *wl, *wlb;
|
||||||
|
char *err = NULL;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
|
||||||
|
struct stat file_stat;
|
||||||
|
struct dirent **dir_entries = NULL;
|
||||||
|
int dir_entries_nb;
|
||||||
|
int dir_entries_it;
|
||||||
|
|
||||||
|
if (stat(wl->s, &file_stat)) {
|
||||||
|
Alert("Cannot open configuration file/directory %s : %s\n",
|
||||||
|
wl->s,
|
||||||
|
strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!S_ISDIR(file_stat.st_mode))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* from this point wl->s is a directory */
|
||||||
|
|
||||||
|
dir_entries_nb = scandir(wl->s, &dir_entries, NULL, alphasort);
|
||||||
|
if (dir_entries_nb < 0) {
|
||||||
|
Alert("Cannot open configuration directory %s : %s\n",
|
||||||
|
wl->s,
|
||||||
|
strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* for each element in the directory wl->s */
|
||||||
|
for (dir_entries_it = 0; dir_entries_it < dir_entries_nb; dir_entries_it++) {
|
||||||
|
struct dirent *dir_entry = dir_entries[dir_entries_it];
|
||||||
|
char *filename = NULL;
|
||||||
|
char *d_name_cfgext = strstr(dir_entry->d_name, ".cfg");
|
||||||
|
|
||||||
|
/* don't add filename that begin with .
|
||||||
|
* only add filename with .cfg extention
|
||||||
|
*/
|
||||||
|
if (dir_entry->d_name[0] == '.' ||
|
||||||
|
!(d_name_cfgext && d_name_cfgext[4] == '\0'))
|
||||||
|
goto next_dir_entry;
|
||||||
|
|
||||||
|
if (!memprintf(&filename, "%s/%s", wl->s, dir_entry->d_name)) {
|
||||||
|
Alert("Cannot load configuration files %s : out of memory.\n",
|
||||||
|
filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stat(filename, &file_stat)) {
|
||||||
|
Alert("Cannot open configuration file %s : %s\n",
|
||||||
|
wl->s,
|
||||||
|
strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* don't add anything else than regular file in cfg_cfgfiles
|
||||||
|
* this way we avoid loops
|
||||||
|
*/
|
||||||
|
if (!S_ISREG(file_stat.st_mode))
|
||||||
|
goto next_dir_entry;
|
||||||
|
|
||||||
|
if (!list_append_word(&wl->list, filename, &err)) {
|
||||||
|
Alert("Cannot load configuration files %s : %s\n",
|
||||||
|
filename,
|
||||||
|
err);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
next_dir_entry:
|
||||||
|
free(filename);
|
||||||
|
free(dir_entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(dir_entries);
|
||||||
|
|
||||||
|
/* remove the current directory (wl) from cfg_cfgfiles */
|
||||||
|
free(wl->s);
|
||||||
|
LIST_DEL(&wl->list);
|
||||||
|
free(wl);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(err);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function initializes all the necessary variables. It only returns
|
* This function initializes all the necessary variables. It only returns
|
||||||
* if everything is OK. If something fails, it exits.
|
* if everything is OK. If something fails, it exits.
|
||||||
@ -757,14 +853,17 @@ void init(int argc, char **argv)
|
|||||||
(arg_mode & (MODE_DAEMON | MODE_SYSTEMD | MODE_FOREGROUND | MODE_VERBOSE
|
(arg_mode & (MODE_DAEMON | MODE_SYSTEMD | MODE_FOREGROUND | MODE_VERBOSE
|
||||||
| MODE_QUIET | MODE_CHECK | MODE_DEBUG));
|
| MODE_QUIET | MODE_CHECK | MODE_DEBUG));
|
||||||
|
|
||||||
if (LIST_ISEMPTY(&cfg_cfgfiles))
|
|
||||||
usage(progname);
|
|
||||||
|
|
||||||
if (change_dir && chdir(change_dir) < 0) {
|
if (change_dir && chdir(change_dir) < 0) {
|
||||||
Alert("Could not change to directory %s : %s\n", change_dir, strerror(errno));
|
Alert("Could not change to directory %s : %s\n", change_dir, strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* handle cfgfiles that are actualy directories */
|
||||||
|
cfgfiles_expand_directories();
|
||||||
|
|
||||||
|
if (LIST_ISEMPTY(&cfg_cfgfiles))
|
||||||
|
usage(progname);
|
||||||
|
|
||||||
global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
|
global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
|
||||||
|
|
||||||
init_default_instance();
|
init_default_instance();
|
||||||
@ -1653,6 +1752,9 @@ int main(int argc, char **argv)
|
|||||||
char errmsg[100];
|
char errmsg[100];
|
||||||
int pidfd = -1;
|
int pidfd = -1;
|
||||||
|
|
||||||
|
/* get the locale from the environment variables */
|
||||||
|
setlocale(LC_ALL, "");
|
||||||
|
|
||||||
init(argc, argv);
|
init(argc, argv);
|
||||||
signal_register_fct(SIGQUIT, dump, SIGQUIT);
|
signal_register_fct(SIGQUIT, dump, SIGQUIT);
|
||||||
signal_register_fct(SIGUSR1, sig_soft_stop, SIGUSR1);
|
signal_register_fct(SIGUSR1, sig_soft_stop, SIGUSR1);
|
||||||
|
Loading…
Reference in New Issue
Block a user