Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit2a0c81a

Browse files
committed
Add support for include_dir in config file.
This allows easily splitting configuration into many files, deployed in adirectory.Magnus Hagander, Greg Smith, Selena Deckelmann, reviewed by Noah Misch.
1 parentce9eee3 commit2a0c81a

File tree

4 files changed

+290
-62
lines changed

4 files changed

+290
-62
lines changed

‎doc/src/sgml/config.sgml

Lines changed: 117 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -79,38 +79,6 @@ shared_buffers = 128MB
7979
value, write either two quotes (preferred) or backslash-quote.
8080
</para>
8181

82-
<para>
83-
<indexterm>
84-
<primary><literal>include</></primary>
85-
<secondary>in configuration file</secondary>
86-
</indexterm>
87-
In addition to parameter settings, the <filename>postgresql.conf</>
88-
file can contain <firstterm>include directives</>, which specify
89-
another file to read and process as if it were inserted into the
90-
configuration file at this point. This feature allows a configuration
91-
file to be divided into physically separate parts.
92-
Include directives simply look like:
93-
<programlisting>
94-
include 'filename'
95-
</programlisting>
96-
If the file name is not an absolute path, it is taken as relative to
97-
the directory containing the referencing configuration file.
98-
Inclusions can be nested.
99-
</para>
100-
101-
<para>
102-
<indexterm>
103-
<primary><literal>include_if_exists</></primary>
104-
<secondary>in configuration file</secondary>
105-
</indexterm>
106-
There is also an <literal>include_if_exists</> directive, which acts
107-
the same as the <literal>include</> directive, except for the behavior
108-
when the referenced file does not exist or cannot be read. A regular
109-
<literal>include</> will consider this an error condition, but
110-
<literal>include_if_exists</> merely logs a message and continues
111-
processing the referencing configuration file.
112-
</para>
113-
11482
<para>
11583
<indexterm>
11684
<primary>SIGHUP</primary>
@@ -213,7 +181,123 @@ SET ENABLE_SEQSCAN TO OFF;
213181
</para>
214182

215183
</sect2>
216-
</sect1>
184+
185+
<sect2 id="config-includes">
186+
<title>Configuration File Includes</title>
187+
188+
<para>
189+
<indexterm>
190+
<primary><literal>include</></primary>
191+
<secondary>in configuration file</secondary>
192+
</indexterm>
193+
In addition to parameter settings, the <filename>postgresql.conf</>
194+
file can contain <firstterm>include directives</>, which specify
195+
another file to read and process as if it were inserted into the
196+
configuration file at this point. This feature allows a configuration
197+
file to be divided into physically separate parts.
198+
Include directives simply look like:
199+
<programlisting>
200+
include 'filename'
201+
</programlisting>
202+
If the file name is not an absolute path, it is taken as relative to
203+
the directory containing the referencing configuration file.
204+
Inclusions can be nested.
205+
</para>
206+
207+
<para>
208+
<indexterm>
209+
<primary><literal>include_if_exists</></primary>
210+
<secondary>in configuration file</secondary>
211+
</indexterm>
212+
There is also an <literal>include_if_exists</> directive, which acts
213+
the same as the <literal>include</> directive, except for the behavior
214+
when the referenced file does not exist or cannot be read. A regular
215+
<literal>include</> will consider this an error condition, but
216+
<literal>include_if_exists</> merely logs a message and continues
217+
processing the referencing configuration file.
218+
</para>
219+
220+
<para>
221+
<indexterm>
222+
<primary><literal>include_dir</></primary>
223+
<secondary>in configuration file</secondary>
224+
</indexterm>
225+
The <filename>postgresql.conf</> file can also contain
226+
<firstterm>include_dir directives</>, which specify an entire directory
227+
of configuration files to include. It is used similarly:
228+
<programlisting>
229+
include_dir 'directory'
230+
</programlisting>
231+
Non-absolute directory names follow the same rules as single file include
232+
directives: they are relative to the directory containing the referencing
233+
configuration file. Within that directory, only non-directory files whose
234+
names end with the suffix <literal>.conf</literal> will be included. File
235+
names that start with the <literal>.</literal> character are also excluded,
236+
to prevent mistakes as they are hidden on some platforms. Multiple files
237+
within an include directory are processed in filename order. The filenames
238+
are ordered by C locale rules, ie. numbers before letters, and uppercase
239+
letters before lowercase ones.
240+
</para>
241+
242+
<para>
243+
Include files or directories can be used to logically separate portions
244+
of the database configuration, rather than having a single large
245+
<filename>postgresql.conf</> file. Consider a company that has two
246+
database servers, each with a different amount of memory. There are likely
247+
elements of the configuration both will share, for things such as logging.
248+
But memory-related parameters on the server will vary between the two. And
249+
there might be server specific customizations, too. One way to manage this
250+
situation is to break the custom configuration changes for your site into
251+
three files. You could add this to the end of your
252+
<filename>postgresql.conf</> file to include them:
253+
<programlisting>
254+
include 'shared.conf'
255+
include 'memory.conf'
256+
include 'server.conf'
257+
</programlisting>
258+
All systems would have the same <filename>shared.conf</>. Each server
259+
with a particular amount of memory could share the same
260+
<filename>memory.conf</>; you might have one for all servers with 8GB of RAM,
261+
another for those having 16GB. And finally <filename>server.conf</> could
262+
have truly server-specific configuration information in it.
263+
</para>
264+
265+
<para>
266+
Another possibility is to create a configuration file directory and
267+
put this information into files there. For example, a <filename>conf.d</>
268+
directory could be referenced at the end of<filename>postgresql.conf</>:
269+
<screen>
270+
include_dir 'conf.d'
271+
</screen>
272+
Then you could name the files in the <filename>conf.d</> directory like this:
273+
<screen>
274+
00shared.conf
275+
01memory.conf
276+
02server.conf
277+
</screen>
278+
This shows a clear order in which these files will be loaded. This is
279+
important because only the last setting encountered when the server is
280+
reading its configuration will be used. Something set in
281+
<filename>conf.d/02server.conf</> in this example would override a value
282+
set in <filename>conf.d/01memory.conf</>.
283+
</para>
284+
285+
<para>
286+
You might instead use this configuration directory approach while naming
287+
these files more descriptively:
288+
<screen>
289+
00shared.conf
290+
01memory-8GB.conf
291+
02server-foo.conf
292+
</screen>
293+
This sort of arrangement gives a unique name for each configuration file
294+
variation. This can help eliminate ambiguity when several servers have
295+
their configurations all stored in one place, such as in a version
296+
control repository. (Storing database configuration files under version
297+
control is another good practice to consider).
298+
</para>
299+
</sect2>
300+
</sect1>
217301

218302
<sect1 id="runtime-config-file-locations">
219303
<title>File Locations</title>

‎src/backend/utils/misc/guc-file.l

Lines changed: 157 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,39 @@ ProcessConfigFile(GucContext context)
362362
}
363363
}
364364

365+
/*
366+
* Given a configuration file or directory location that may be a relative
367+
* path, return an absolute one. We consider the location to be relative to
368+
* the directory holding the calling file.
369+
*/
370+
staticchar *
371+
AbsoluteConfigLocation(constchar *location,constchar *calling_file)
372+
{
373+
charabs_path[MAXPGPATH];
374+
375+
if (is_absolute_path(location))
376+
returnpstrdup(location);
377+
else
378+
{
379+
if (calling_file !=NULL)
380+
{
381+
strlcpy(abs_path, calling_file,sizeof(abs_path));
382+
get_parent_directory(abs_path);
383+
join_path_components(abs_path, abs_path, location);
384+
canonicalize_path(abs_path);
385+
}
386+
else
387+
{
388+
/*
389+
* calling_file is NULL, we make an absolute path from $PGDATA
390+
*/
391+
join_path_components(abs_path, data_directory, location);
392+
canonicalize_path(abs_path);
393+
}
394+
returnpstrdup(abs_path);
395+
}
396+
}
397+
365398
/*
366399
* Read and parse a single configuration file. This function recurses
367400
* to handle "include" directives.
@@ -378,7 +411,6 @@ ParseConfigFile(const char *config_file, const char *calling_file, bool strict,
378411
{
379412
boolOK =true;
380413
FILE *fp;
381-
charabs_path[MAXPGPATH];
382414

383415
/*
384416
* Reject too-deep include nesting depth. This is just a safety check
@@ -394,31 +426,7 @@ ParseConfigFile(const char *config_file, const char *calling_file, bool strict,
394426
returnfalse;
395427
}
396428

397-
/*
398-
* If config_file is a relative path, convert to absolute. We consider
399-
* it to be relative to the directory holding the calling file.
400-
*/
401-
if (!is_absolute_path(config_file))
402-
{
403-
if (calling_file !=NULL)
404-
{
405-
strlcpy(abs_path, calling_file,sizeof(abs_path));
406-
get_parent_directory(abs_path);
407-
join_path_components(abs_path, abs_path, config_file);
408-
canonicalize_path(abs_path);
409-
config_file = abs_path;
410-
}
411-
else
412-
{
413-
/*
414-
* calling_file is NULL, we make an absolute path from $PGDATA
415-
*/
416-
join_path_components(abs_path, data_directory, config_file);
417-
canonicalize_path(abs_path);
418-
config_file = abs_path;
419-
}
420-
}
421-
429+
config_file =AbsoluteConfigLocation(config_file,calling_file);
422430
fp =AllocateFile(config_file,"r");
423431
if (!fp)
424432
{
@@ -563,20 +571,35 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,
563571
}
564572

565573
/* OK, process the option name and value */
566-
if (guc_name_compare(opt_name,"include_if_exists") ==0)
574+
if (guc_name_compare(opt_name,"include_dir") ==0)
567575
{
568576
/*
569-
* Aninclude_if_exists directive isn't a variable and should be
577+
* Aninclude_dir directive isn't a variable and should be
570578
* processed immediately.
571579
*/
572-
if (!ParseConfigFile(opt_value, config_file,false,
580+
if (!ParseConfigDirectory(opt_value, config_file,
573581
depth +1, elevel,
574582
head_p, tail_p))
575583
OK =false;
576584
yy_switch_to_buffer(lex_buffer);
585+
ConfigFileLineno = save_ConfigFileLineno;
577586
pfree(opt_name);
578587
pfree(opt_value);
579588
}
589+
elseif (guc_name_compare(opt_name,"include_if_exists") ==0)
590+
{
591+
/*
592+
* An include_if_exists directive isn't a variable and should be
593+
* processed immediately.
594+
*/
595+
if (!ParseConfigFile(opt_value, config_file,false,
596+
depth +1, elevel,
597+
head_p, tail_p))
598+
OK =false;
599+
yy_switch_to_buffer(lex_buffer);
600+
pfree(opt_name);
601+
pfree(opt_value);
602+
}
580603
elseif (guc_name_compare(opt_name,"include") ==0)
581604
{
582605
/*
@@ -665,6 +688,111 @@ cleanup:
665688
return OK;
666689
}
667690

691+
/*
692+
* Read and parse all config files in a subdirectory in alphabetical order
693+
*/
694+
bool
695+
ParseConfigDirectory(constchar *includedir,
696+
constchar *calling_file,
697+
int depth,int elevel,
698+
ConfigVariable **head_p,
699+
ConfigVariable **tail_p)
700+
{
701+
char *directory;
702+
DIR *d;
703+
structdirent *de;
704+
char **filenames =NULL;
705+
intnum_filenames =0;
706+
intsize_filenames =0;
707+
boolstatus;
708+
709+
directory =AbsoluteConfigLocation(includedir, calling_file);
710+
d =AllocateDir(directory);
711+
if (d ==NULL)
712+
{
713+
ereport(elevel,
714+
(errcode_for_file_access(),
715+
errmsg("could not open configuration directory\"%s\": %m",
716+
directory)));
717+
returnfalse;
718+
}
719+
720+
/*
721+
* Read the directory and put the filenames in an array, so we can sort
722+
* them prior to processing the contents.
723+
*/
724+
while ((de =ReadDir(d, directory)) !=NULL)
725+
{
726+
structstat st;
727+
charfilename[MAXPGPATH];
728+
729+
/*
730+
* Only parse files with names ending in ".conf". Explicitly reject
731+
* files starting with ".". This excludes things like "." and "..",
732+
* as well as typical hidden files, backup files, and editor debris.
733+
*/
734+
if (strlen(de->d_name) <6)
735+
continue;
736+
if (de->d_name[0] =='.')
737+
continue;
738+
if (strcmp(de->d_name +strlen(de->d_name) -5,".conf") !=0)
739+
continue;
740+
741+
join_path_components(filename, directory, de->d_name);
742+
canonicalize_path(filename);
743+
if (stat(filename, &st) ==0)
744+
{
745+
if (!S_ISDIR(st.st_mode))
746+
{
747+
/* Add file to list, increasing its size in blocks of 32 */
748+
if (num_filenames == size_filenames)
749+
{
750+
size_filenames +=32;
751+
if (num_filenames ==0)
752+
/* Must initialize, repalloc won't take NULL input */
753+
filenames =palloc(size_filenames *sizeof(char *));
754+
else
755+
filenames =repalloc(filenames, size_filenames *sizeof(char *));
756+
}
757+
filenames[num_filenames] =pstrdup(filename);
758+
num_filenames++;
759+
}
760+
}
761+
else
762+
{
763+
/*
764+
* stat does not care about permissions, so the most likely reason
765+
* a file can't be accessed now is if it was removed between the
766+
* directory listing and now.
767+
*/
768+
ereport(elevel,
769+
(errcode_for_file_access(),
770+
errmsg("could not stat file\"%s\": %m",
771+
filename)));
772+
returnfalse;
773+
}
774+
}
775+
776+
if (num_filenames >0)
777+
{
778+
inti;
779+
qsort(filenames, num_filenames,sizeof(char *), pg_qsort_strcmp);
780+
for (i =0; i < num_filenames; i++)
781+
{
782+
if (!ParseConfigFile(filenames[i],NULL,true,
783+
depth, elevel, head_p, tail_p))
784+
{
785+
status =false;
786+
goto cleanup;
787+
}
788+
}
789+
}
790+
status =true;
791+
792+
cleanup:
793+
FreeDir(d);
794+
return status;
795+
}
668796

669797
/*
670798
* Free a list of ConfigVariables, including the names and the values

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp