From: Iain Patterson Date: Sun, 12 Jan 2014 23:56:10 +0000 (+0000) Subject: Enable on-demand rotation. X-Git-Tag: v2.22~64 X-Git-Url: http://git.iain.cx/?p=nssm.git;a=commitdiff_plain;h=2cd1c7c29ef4d2d3df3c5afd3ca6c788aede2bef Enable on-demand rotation. Running "nssm rotate " will send user-defined service control 128 to the service, triggering a rotation of output files after the next call to ReadFile(), regardless of the value of AppRotateBytes*. Note that since ReadFile() is synchronous, we have no way to interrupt it, hence there may be a significant delay before the rotation happens. --- diff --git a/README.txt b/README.txt index 3769d4c..0affeb3 100644 --- a/README.txt +++ b/README.txt @@ -315,7 +315,17 @@ They will be rotated regardless of whether NSSM would otherwise have appended or replaced them. NSSM can also rotate files which hit the configured size threshold while the -service is running. To enable this feature, set AppRotateOnline to a non-zero +service is running. Additionally, you can trigger an on-demand rotation by +running the command + + nssm rotate + +On-demand rotations will happen after the next line of data is read from +the managed application, regardless of the value of AppRotateBytes. Be aware +that if the application is not particularly verbose the rotation may not +happen for some time. + +To enable online and on-demand rotation, set AppRotateOnline to a non-zero value. Note that online rotation requires NSSM to intercept the application's I/O diff --git a/gui.cpp b/gui.cpp index c09b363..64382f4 100644 --- a/gui.cpp +++ b/gui.cpp @@ -508,7 +508,7 @@ int configure(HWND window, nssm_service_t *service, nssm_service_t *orig_service /* Get rotation stuff. */ if (SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE, BM_GETCHECK, 0, 0) & BST_CHECKED) { service->rotate_files = true; - if (SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_ONLINE, BM_GETCHECK, 0, 0) & BST_CHECKED) service->rotate_stdout_online = service->rotate_stderr_online = true; + if (SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_ONLINE, BM_GETCHECK, 0, 0) & BST_CHECKED) service->rotate_stdout_online = service->rotate_stderr_online = NSSM_ROTATE_ONLINE; check_number(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS, &service->rotate_seconds); check_number(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW, &service->rotate_bytes_low); } diff --git a/io.cpp b/io.cpp index 2602dc2..79848e9 100644 --- a/io.cpp +++ b/io.cpp @@ -242,7 +242,7 @@ int get_output_handles(nssm_service_t *service, HKEY key, STARTUPINFO *si) { /* Try online rotation only if a size threshold is set. */ logger_t *stdout_logger = 0; - if (service->rotate_files && service->rotate_stdout_online && size.QuadPart) { + if (service->rotate_files && service->rotate_stdout_online) { stdout_logger = (logger_t *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(logger_t)); if (stdout_logger) { /* Pipe between application's stdout and our logging handle. */ @@ -256,6 +256,7 @@ int get_output_handles(nssm_service_t *service, HKEY key, STARTUPINFO *si) { stdout_logger->write_handle = stdout_handle; stdout_logger->size = (__int64) size.QuadPart; stdout_logger->tid_ptr = &service->stdout_tid; + stdout_logger->rotate_online = &service->rotate_stdout_online; /* Logging thread. */ service->stdout_thread = create_logging_thread(stdout_logger); @@ -283,7 +284,7 @@ int get_output_handles(nssm_service_t *service, HKEY key, STARTUPINFO *si) { log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_DUPLICATEHANDLE_FAILED, NSSM_REG_STDOUT, error_string(GetLastError()), 0); return 4; } - service->rotate_stdout_online = false; + service->rotate_stdout_online = NSSM_ROTATE_OFFLINE; } set_flags = true; @@ -321,7 +322,7 @@ int get_output_handles(nssm_service_t *service, HKEY key, STARTUPINFO *si) { /* Try online rotation only if a size threshold is set. */ logger_t *stderr_logger = 0; - if (service->rotate_files && service->rotate_stderr_online && size.QuadPart) { + if (service->rotate_files && service->rotate_stderr_online) { stderr_logger = (logger_t *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(logger_t)); if (stderr_logger) { /* Pipe between application's stderr and our logging handle. */ @@ -335,6 +336,7 @@ int get_output_handles(nssm_service_t *service, HKEY key, STARTUPINFO *si) { stderr_logger->write_handle = stderr_handle; stderr_logger->size = (__int64) size.QuadPart; stderr_logger->tid_ptr = &service->stderr_tid; + stderr_logger->rotate_online = &service->rotate_stderr_online; /* Logging thread. */ service->stderr_thread = create_logging_thread(stderr_logger); @@ -362,7 +364,7 @@ int get_output_handles(nssm_service_t *service, HKEY key, STARTUPINFO *si) { log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_DUPLICATEHANDLE_FAILED, NSSM_REG_STDERR, error_string(GetLastError()), 0); return 7; } - service->rotate_stderr_online = false; + service->rotate_stderr_online = NSSM_ROTATE_OFFLINE; } } @@ -510,7 +512,7 @@ unsigned long WINAPI log_and_rotate(void *arg) { } else if (ret) continue; - if (size + (__int64) in >= logger->size) { + if (*logger->rotate_online == NSSM_ROTATE_ONLINE_ASAP || (logger->size && size + (__int64) in >= logger->size)) { /* Look for newline. */ unsigned long i; for (i = 0; i < in; i++) { @@ -527,6 +529,7 @@ unsigned long WINAPI log_and_rotate(void *arg) { size += (__int64) out; /* Rotate. */ + *logger->rotate_online = NSSM_ROTATE_ONLINE; TCHAR rotated[MAX_PATH]; rotated_filename(logger->path, rotated, _countof(rotated), 0); diff --git a/io.h b/io.h index 23c8488..60c3fd5 100644 --- a/io.h +++ b/io.h @@ -21,6 +21,7 @@ typedef struct { HANDLE write_handle; __int64 size; unsigned long *tid_ptr; + unsigned long *rotate_online; } logger_t; int get_createfile_parameters(HKEY, TCHAR *, TCHAR *, unsigned long *, unsigned long, unsigned long *, unsigned long, unsigned long *, unsigned long); diff --git a/messages.mc b/messages.mc index 68b5289..d8f6f0e 100644 Binary files a/messages.mc and b/messages.mc differ diff --git a/nssm.cpp b/nssm.cpp index 8dd264a..498a213 100644 --- a/nssm.cpp +++ b/nssm.cpp @@ -108,6 +108,7 @@ int _tmain(int argc, TCHAR **argv) { if (str_equiv(argv[1], _T("pause"))) exit(control_service(SERVICE_CONTROL_PAUSE, argc - 2, argv + 2)); if (str_equiv(argv[1], _T("continue"))) exit(control_service(SERVICE_CONTROL_CONTINUE, argc - 2, argv + 2)); if (str_equiv(argv[1], _T("status"))) exit(control_service(SERVICE_CONTROL_INTERROGATE, argc - 2, argv + 2)); + if (str_equiv(argv[1], _T("rotate"))) exit(control_service(NSSM_SERVICE_CONTROL_ROTATE, argc - 2, argv + 2)); if (str_equiv(argv[1], _T("install"))) { if (! is_admin) { print_message(stderr, NSSM_MESSAGE_NOT_ADMINISTRATOR_CANNOT_INSTALL); diff --git a/nssm.h b/nssm.h index f6c3f35..79c2065 100644 --- a/nssm.h +++ b/nssm.h @@ -95,4 +95,7 @@ int usage(int); /* How many milliseconds to wait before updating service status. */ #define NSSM_SERVICE_STATUS_DEADLINE 20000 +/* User-defined service controls can be in the range 128-255. */ +#define NSSM_SERVICE_CONTROL_ROTATE 128 + #endif diff --git a/service.cpp b/service.cpp index d0141a1..b8c73ef 100644 --- a/service.cpp +++ b/service.cpp @@ -1281,6 +1281,7 @@ TCHAR *service_control_text(unsigned long control) { case SERVICE_CONTROL_PAUSE: return _T("PAUSE"); case SERVICE_CONTROL_CONTINUE: return _T("CONTINUE"); case SERVICE_CONTROL_INTERROGATE: return _T("INTERROGATE"); + case NSSM_SERVICE_CONTROL_ROTATE: return _T("ROTATE"); default: return 0; } } @@ -1368,6 +1369,12 @@ unsigned long WINAPI service_control_handler(unsigned long control, unsigned lon */ log_service_control(service->name, control, false); return ERROR_CALL_NOT_IMPLEMENTED; + + case NSSM_SERVICE_CONTROL_ROTATE: + log_service_control(service->name, control, true); + if (service->rotate_stdout_online) service->rotate_stdout_online = NSSM_ROTATE_ONLINE_ASAP; + if (service->rotate_stdout_online) service->rotate_stderr_online = NSSM_ROTATE_ONLINE_ASAP; + return NO_ERROR; } /* Unknown control */ diff --git a/service.h b/service.h index 8549fee..45680cf 100644 --- a/service.h +++ b/service.h @@ -28,6 +28,10 @@ #define NSSM_SHARE_INTERACTIVE_PROCESS NSSM_WIN32_SHARE_PROCESS _T("|") NSSM_INTERACTIVE_PROCESS #define NSSM_UNKNOWN _T("?") +#define NSSM_ROTATE_OFFLINE 0 +#define NSSM_ROTATE_ONLINE 1 +#define NSSM_ROTATE_ONLINE_ASAP 2 + typedef struct { bool native; TCHAR name[SERVICE_NAME_LENGTH]; @@ -68,8 +72,8 @@ typedef struct { HANDLE stderr_thread; unsigned long stderr_tid; bool rotate_files; - bool rotate_stdout_online; - bool rotate_stderr_online; + unsigned long rotate_stdout_online; + unsigned long rotate_stderr_online; unsigned long rotate_seconds; unsigned long rotate_bytes_low; unsigned long rotate_bytes_high;