logging: try to reopen message log on cyclelogs command

When the cyclelogs command is issued, check if the file specified by the
-l option is still in its place and if not try opening it again. If that
fails (e.g. due to chrony no longer having root privileges), keep the
old file handle to avoid losing log messages.
This commit is contained in:
Miroslav Lichvar
2025-03-20 12:57:37 +01:00
parent 75bbccf518
commit dd8738119b
2 changed files with 47 additions and 6 deletions

View File

@@ -1467,6 +1467,13 @@ purged. An example of how to do this is shown below.
# chronyc cyclelogs
# rm /var/log/chrony/measurements1.log
----
+
Note that log files enabled by the *log* directive are opened when the first
entry is made. The message log file specified by the *chronyd*'s *-l* option is
opened early on start and closed on the *cyclelogs* command only if opening of
the new file succeeds to avoid losing messages. If *chronyd* is configured to
drop root privileges and the directory containg the log file is not writable
for the specified user, *chronyd* will not be able to open the file again.
[[dump]]*dump*::
The *dump* command causes *chronyd* to write its current history of

View File

@@ -46,6 +46,7 @@ static LOG_Context log_contexts;
/* Flag indicating we have initialised */
static int initialised = 0;
static char *file_log_path = NULL;
static FILE *file_log = NULL;
static int system_log = 0;
@@ -92,6 +93,9 @@ LOG_Finalise(void)
if (file_log)
fclose(file_log);
file_log = NULL;
Free(file_log_path);
file_log_path = NULL;
LOG_CycleLogFiles();
@@ -200,27 +204,42 @@ void LOG_Message(LOG_Severity severity,
/* ================================================== */
void
LOG_OpenFileLog(const char *log_file)
static FILE *
open_file_log(const char *log_file, char mode)
{
FILE *f;
if (log_file) {
f = UTI_OpenFile(NULL, log_file, NULL, 'A', 0640);
f = UTI_OpenFile(NULL, log_file, NULL, mode, 0640);
} else {
f = stderr;
}
/* Enable line buffering */
setvbuf(f, NULL, _IOLBF, BUFSIZ);
if (f)
setvbuf(f, NULL, _IOLBF, BUFSIZ);
return f;
}
/* ================================================== */
void
LOG_OpenFileLog(const char *log_file)
{
if (file_log_path)
Free(file_log_path);
if (log_file)
file_log_path = Strdup(log_file);
else
file_log_path = NULL;
if (file_log && file_log != stderr)
fclose(file_log);
file_log = f;
file_log = open_file_log(file_log_path, 'A');
}
/* ================================================== */
void
@@ -385,14 +404,29 @@ LOG_FileWrite(LOG_FileID id, const char *format, ...)
void
LOG_CycleLogFiles(void)
{
struct stat st;
LOG_FileID i;
FILE *f;
/* The log will be opened later when an entry is logged */
for (i = 0; i < n_filelogs; i++) {
if (logfiles[i].file)
fclose(logfiles[i].file);
logfiles[i].file = NULL;
logfiles[i].writes = 0;
}
/* Try to open the log specified by the -l option, but only if nothing is
present at its path to avoid unnecessary error messages. Keep the
original file if that fails (the process might no longer have the
necessary privileges to write in the directory). */
if (file_log && file_log != stderr && stat(file_log_path, &st) < 0 && errno == ENOENT) {
f = open_file_log(file_log_path, 'a');
if (f) {
fclose(file_log);
file_log = f;
}
}
}
/* ================================================== */