2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 06:25:31 +00:00

new: usr: add support for external log rotation tools

Add two mechanisms to close open log files.  The first is `rndc closelogs`.  The second is `kill -USR1 <pid>`.
They are intended to be used with external log rotation	tools.

Closes #4780

Merge branch '4780-add-support-for-external-log-rotation-tools' into 'main'

Closes #4780

See merge request isc-projects/bind9!9113
This commit is contained in:
Mark Andrews
2024-07-31 08:48:51 +00:00
10 changed files with 120 additions and 37 deletions

View File

@@ -16,6 +16,7 @@
#include <stdbool.h>
#include <isc/lex.h>
#include <isc/log.h>
#include <isc/mem.h>
#include <isc/result.h>
#include <isc/string.h>
@@ -201,6 +202,9 @@ named_control_docommand(isccc_sexpr_t *message, bool readonly,
command_compare(command, NAMED_COMMAND_MODZONE))
{
result = named_server_changezone(named_g_server, cmdline, text);
} else if (command_compare(command, NAMED_COMMAND_CLOSELOGS)) {
isc_log_closefilelogs(named_g_lctx);
result = ISC_R_SUCCESS;
} else if (command_compare(command, NAMED_COMMAND_DELZONE)) {
result = named_server_delzone(named_g_server, lex, text);
} else if (command_compare(command, NAMED_COMMAND_DNSSEC)) {

View File

@@ -28,48 +28,49 @@
#define NAMED_CONTROL_PORT 953
#define NAMED_COMMAND_STOP "stop"
#define NAMED_COMMAND_HALT "halt"
#define NAMED_COMMAND_RELOAD "reload"
#define NAMED_COMMAND_RECONFIG "reconfig"
#define NAMED_COMMAND_REFRESH "refresh"
#define NAMED_COMMAND_RETRANSFER "retransfer"
#define NAMED_COMMAND_DUMPSTATS "stats"
#define NAMED_COMMAND_QUERYLOG "querylog"
#define NAMED_COMMAND_ADDZONE "addzone"
#define NAMED_COMMAND_CLOSELOGS "closelogs"
#define NAMED_COMMAND_DELZONE "delzone"
#define NAMED_COMMAND_DNSSEC "dnssec"
#define NAMED_COMMAND_DNSTAP "dnstap"
#define NAMED_COMMAND_DNSTAPREOPEN "dnstap-reopen"
#define NAMED_COMMAND_DUMPDB "dumpdb"
#define NAMED_COMMAND_SECROOTS "secroots"
#define NAMED_COMMAND_TRACE "trace"
#define NAMED_COMMAND_NOTRACE "notrace"
#define NAMED_COMMAND_DUMPSTATS "stats"
#define NAMED_COMMAND_FETCHLIMIT "fetchlimit"
#define NAMED_COMMAND_FLUSH "flush"
#define NAMED_COMMAND_FLUSHNAME "flushname"
#define NAMED_COMMAND_FLUSHTREE "flushtree"
#define NAMED_COMMAND_STATUS "status"
#define NAMED_COMMAND_FREEZE "freeze"
#define NAMED_COMMAND_UNFREEZE "unfreeze"
#define NAMED_COMMAND_THAW "thaw"
#define NAMED_COMMAND_RECURSING "recursing"
#define NAMED_COMMAND_NULL "null"
#define NAMED_COMMAND_NOTIFY "notify"
#define NAMED_COMMAND_VALIDATION "validation"
#define NAMED_COMMAND_SCAN "scan"
#define NAMED_COMMAND_SIGN "sign"
#define NAMED_COMMAND_HALT "halt"
#define NAMED_COMMAND_LOADKEYS "loadkeys"
#define NAMED_COMMAND_ADDZONE "addzone"
#define NAMED_COMMAND_MODZONE "modzone"
#define NAMED_COMMAND_DELZONE "delzone"
#define NAMED_COMMAND_SHOWZONE "showzone"
#define NAMED_COMMAND_SYNC "sync"
#define NAMED_COMMAND_SIGNING "signing"
#define NAMED_COMMAND_DNSSEC "dnssec"
#define NAMED_COMMAND_ZONESTATUS "zonestatus"
#define NAMED_COMMAND_NTA "nta"
#define NAMED_COMMAND_TESTGEN "testgen"
#define NAMED_COMMAND_MKEYS "managed-keys"
#define NAMED_COMMAND_DNSTAPREOPEN "dnstap-reopen"
#define NAMED_COMMAND_DNSTAP "dnstap"
#define NAMED_COMMAND_TCPTIMEOUTS "tcp-timeouts"
#define NAMED_COMMAND_MODZONE "modzone"
#define NAMED_COMMAND_NOTIFY "notify"
#define NAMED_COMMAND_NOTRACE "notrace"
#define NAMED_COMMAND_NTA "nta"
#define NAMED_COMMAND_NULL "null"
#define NAMED_COMMAND_QUERYLOG "querylog"
#define NAMED_COMMAND_RECONFIG "reconfig"
#define NAMED_COMMAND_RECURSING "recursing"
#define NAMED_COMMAND_REFRESH "refresh"
#define NAMED_COMMAND_RELOAD "reload"
#define NAMED_COMMAND_RETRANSFER "retransfer"
#define NAMED_COMMAND_SCAN "scan"
#define NAMED_COMMAND_SECROOTS "secroots"
#define NAMED_COMMAND_SERVESTALE "serve-stale"
#define NAMED_COMMAND_FETCHLIMIT "fetchlimit"
#define NAMED_COMMAND_SHOWZONE "showzone"
#define NAMED_COMMAND_SIGN "sign"
#define NAMED_COMMAND_SIGNING "signing"
#define NAMED_COMMAND_STATUS "status"
#define NAMED_COMMAND_STOP "stop"
#define NAMED_COMMAND_SYNC "sync"
#define NAMED_COMMAND_TCPTIMEOUTS "tcp-timeouts"
#define NAMED_COMMAND_TESTGEN "testgen"
#define NAMED_COMMAND_THAW "thaw"
#define NAMED_COMMAND_TRACE "trace"
#define NAMED_COMMAND_UNFREEZE "unfreeze"
#define NAMED_COMMAND_VALIDATION "validation"
#define NAMED_COMMAND_ZONESTATUS "zonestatus"
isc_result_t
named_controls_create(named_server_t *server, named_controls_t **ctrlsp);

View File

@@ -108,6 +108,7 @@ struct named_server {
isc_tlsctx_cache_t *tlsctx_client_cache;
isc_signal_t *sighup;
isc_signal_t *sigusr1;
};
#define NAMED_SERVER_MAGIC ISC_MAGIC('S', 'V', 'E', 'R')

View File

@@ -1567,6 +1567,7 @@ main(int argc, char *argv[]) {
* Start things running
*/
isc_signal_start(named_g_server->sighup);
isc_signal_start(named_g_server->sigusr1);
/*
* Pause the loop manager in fatal.

View File

@@ -432,6 +432,9 @@ fatal(const char *msg, isc_result_t result);
static void
named_server_reload(void *arg);
static void
named_server_closelogswanted(void *arg, int signum);
#ifdef HAVE_LIBNGHTTP2
static isc_result_t
listenelt_http(const cfg_obj_t *http, const uint16_t family, bool tls,
@@ -9983,6 +9986,9 @@ shutdown_server(void *arg) {
isc_signal_stop(server->sighup);
isc_signal_destroy(&server->sighup);
isc_signal_stop(server->sigusr1);
isc_signal_destroy(&server->sigusr1);
/*
* We need to shutdown the interface before going
* exclusive (which would pause the netmgr).
@@ -10355,6 +10361,10 @@ named_server_create(isc_mem_t *mctx, named_server_t **serverp) {
server->sighup = isc_signal_new(
named_g_loopmgr, named_server_reloadwanted, server, SIGHUP);
/* Add SIGUSR2 closelogs handler */
server->sigusr1 = isc_signal_new(
named_g_loopmgr, named_server_closelogswanted, server, SIGUSR1);
isc_stats_create(server->mctx, &server->sockstats,
isc_sockstatscounter_max);
isc_nm_setstats(named_g_netmgr, server->sockstats);
@@ -10540,6 +10550,28 @@ named_server_reloadwanted(void *arg, int signum) {
isc_async_run(named_g_mainloop, named_server_reload, server);
}
/*
* Handle a reload event (from SIGUSR1).
*/
static void
named_server_closelogs(void *arg) {
UNUSED(arg);
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
"received SIGUSR1 signal to close log files");
isc_log_closefilelogs(named_g_lctx);
}
static void
named_server_closelogswanted(void *arg, int signum) {
named_server_t *server = (named_server_t *)arg;
REQUIRE(signum == SIGUSR1);
isc_async_run(named_g_mainloop, named_server_closelogs, server);
}
void
named_server_scan_interfaces(named_server_t *server) {
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,

View File

@@ -152,6 +152,15 @@ Currently supported commands are:
See also :option:`rndc delzone` and :option:`rndc modzone`.
.. option:: closelogs
This command closes currently open log files. It is intended to be used
by external log rotation tools following this proceedure.
1) rename the log files
2) run ``rndc closelogs``
3) optionally compress the log files
.. option:: delzone [-clean] zone [class [view]]
This command deletes a zone while the server is running.

View File

@@ -37,7 +37,7 @@ logging {
channel query_log {
file "query_log";
print-time yes;
buffered yes;
buffered no;
};
category queries { query_log; };
};

View File

@@ -28,6 +28,10 @@ test_with_retry() {
return 1
}
rndccmd() (
"$RNDC" -c ../_common/rndc.conf -p "${CONTROLPORT}" -s "$@"
)
status=0
n=0
@@ -276,6 +280,32 @@ test_with_retry -f ns1/named_unlimited.4 || ret=1
if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
status=$((status + ret))
n=$((n + 1))
echo_i "testing 'rndc closelogs' ($n)"
ret=0
test -f ns1/query_log || ret=1
mv ns1/query_log ns1/query_log.$n || ret=1
rndccmd 10.53.0.1 closelogs >rndc.out.test$n || ret=1
$DIG version.bind txt ch @10.53.0.1 -p ${PORT} >dig.out.test$n || ret=1
test -f ns1/query_log || ret=1
lines=$(wc -l <"ns1/query_log")
test ${lines:-0} -eq 1 || ret=1
if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
status=$((status + ret))
n=$((n + 1))
echo_i "testing 'kill -USR1' ($n)"
ret=0
test -f ns1/query_log || ret=1
mv ns1/query_log ns1/query_log.$n || ret=1
kill -USR1 $(cat ns1/named.pid) || ret=1
$DIG version.bind txt ch @10.53.0.1 -p ${PORT} >dig.out.test$n || ret=1
test -f ns1/query_log || ret=1
lines=$(wc -l <"ns1/query_log")
test ${lines:-0} -eq 1 || ret=1
if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
status=$((status + ret))
n=$((n + 1))
echo_i "testing default logfile using named -L file ($n)"
ret=0

View File

@@ -236,6 +236,8 @@ described in the following table. These signals can be sent using the
| ``SIGHUP`` | Causes the server to read :iscman:`named.conf` and reload |
| | the database. |
+--------------+-------------------------------------------------------------+
| ``SIGUSR1`` | Causes the server close the currently open log files |
+--------------+-------------------------------------------------------------+
| ``SIGTERM`` | Causes the server to clean up and exit. |
+--------------+-------------------------------------------------------------+
| ``SIGINT`` | Causes the server to clean up and exit. |

View File

@@ -1762,8 +1762,11 @@ isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
errno == ENOENT) ||
statbuf.st_size < FILE_MAXSIZE(channel))
{
(void)fclose(FILE_STREAM(channel));
FILE_STREAM(channel) = NULL;
if (FILE_STREAM(channel) != NULL) {
(void)fclose(
FILE_STREAM(channel));
FILE_STREAM(channel) = NULL;
}
FILE_MAXREACHED(channel) = false;
} else {
/*