diff --git a/bin/named/control.c b/bin/named/control.c index a3e009799e..d2aa5a9260 100644 --- a/bin/named/control.c +++ b/bin/named/control.c @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -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)) { diff --git a/bin/named/include/named/control.h b/bin/named/include/named/control.h index ee938a5973..6f3660ad0f 100644 --- a/bin/named/include/named/control.h +++ b/bin/named/include/named/control.h @@ -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); diff --git a/bin/named/include/named/server.h b/bin/named/include/named/server.h index 52a13d5658..9ad18bde7f 100644 --- a/bin/named/include/named/server.h +++ b/bin/named/include/named/server.h @@ -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') diff --git a/bin/named/main.c b/bin/named/main.c index 6cb3392005..e5a17b2f45 100644 --- a/bin/named/main.c +++ b/bin/named/main.c @@ -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. diff --git a/bin/named/server.c b/bin/named/server.c index fd12287d33..3c5ba6d5e9 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -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, diff --git a/bin/rndc/rndc.rst b/bin/rndc/rndc.rst index da9f0710e4..62603d1da8 100644 --- a/bin/rndc/rndc.rst +++ b/bin/rndc/rndc.rst @@ -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. diff --git a/bin/tests/system/logfileconfig/ns1/named.unlimited.in b/bin/tests/system/logfileconfig/ns1/named.unlimited.in index f806eddd62..8cfd205e5b 100644 --- a/bin/tests/system/logfileconfig/ns1/named.unlimited.in +++ b/bin/tests/system/logfileconfig/ns1/named.unlimited.in @@ -37,7 +37,7 @@ logging { channel query_log { file "query_log"; print-time yes; - buffered yes; + buffered no; }; category queries { query_log; }; }; diff --git a/bin/tests/system/logfileconfig/tests.sh b/bin/tests/system/logfileconfig/tests.sh index e738dbd66f..1b411174cd 100644 --- a/bin/tests/system/logfileconfig/tests.sh +++ b/bin/tests/system/logfileconfig/tests.sh @@ -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 diff --git a/doc/arm/dns-ops.inc.rst b/doc/arm/dns-ops.inc.rst index abb6bcf766..d5a8b7aa86 100644 --- a/doc/arm/dns-ops.inc.rst +++ b/doc/arm/dns-ops.inc.rst @@ -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. | diff --git a/lib/isc/log.c b/lib/isc/log.c index 472c57d956..53785df3c6 100644 --- a/lib/isc/log.c +++ b/lib/isc/log.c @@ -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 { /*