Bläddra i källkod

Enable on-demand rotation.

Running "nssm rotate <service>" 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.
Iain Patterson 10 år sedan
förälder
incheckning
2cd1c7c29e
9 ändrade filer med 38 tillägg och 9 borttagningar
  1. 11 1
      README.txt
  2. 1 1
      gui.cpp
  3. 8 5
      io.cpp
  4. 1 0
      io.h
  5. BIN
      messages.mc
  6. 1 0
      nssm.cpp
  7. 3 0
      nssm.h
  8. 7 0
      service.cpp
  9. 6 2
      service.h

+ 11 - 1
README.txt

@@ -315,7 +315,17 @@ They will be rotated regardless of whether NSSM would otherwise have appended
 or replaced them.
 or replaced them.
 
 
 NSSM can also rotate files which hit the configured size threshold while the
 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 <servicename>
+
+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.
 value.
 
 
 Note that online rotation requires NSSM to intercept the application's I/O
 Note that online rotation requires NSSM to intercept the application's I/O

+ 1 - 1
gui.cpp

@@ -508,7 +508,7 @@ int configure(HWND window, nssm_service_t *service, nssm_service_t *orig_service
   /* Get rotation stuff. */
   /* Get rotation stuff. */
   if (SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE, BM_GETCHECK, 0, 0) & BST_CHECKED) {
   if (SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE, BM_GETCHECK, 0, 0) & BST_CHECKED) {
     service->rotate_files = true;
     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_SECONDS, &service->rotate_seconds);
     check_number(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW, &service->rotate_bytes_low);
     check_number(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW, &service->rotate_bytes_low);
   }
   }

+ 8 - 5
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. */
     /* Try online rotation only if a size threshold is set. */
     logger_t *stdout_logger = 0;
     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));
       stdout_logger = (logger_t *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(logger_t));
       if (stdout_logger) {
       if (stdout_logger) {
         /* Pipe between application's stdout and our logging handle. */
         /* 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->write_handle = stdout_handle;
           stdout_logger->size = (__int64) size.QuadPart;
           stdout_logger->size = (__int64) size.QuadPart;
           stdout_logger->tid_ptr = &service->stdout_tid;
           stdout_logger->tid_ptr = &service->stdout_tid;
+          stdout_logger->rotate_online = &service->rotate_stdout_online;
 
 
           /* Logging thread. */
           /* Logging thread. */
           service->stdout_thread = create_logging_thread(stdout_logger);
           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);
         log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_DUPLICATEHANDLE_FAILED, NSSM_REG_STDOUT, error_string(GetLastError()), 0);
         return 4;
         return 4;
       }
       }
-      service->rotate_stdout_online = false;
+      service->rotate_stdout_online = NSSM_ROTATE_OFFLINE;
     }
     }
 
 
     set_flags = true;
     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. */
       /* Try online rotation only if a size threshold is set. */
       logger_t *stderr_logger = 0;
       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));
         stderr_logger = (logger_t *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(logger_t));
         if (stderr_logger) {
         if (stderr_logger) {
           /* Pipe between application's stderr and our logging handle. */
           /* 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->write_handle = stderr_handle;
             stderr_logger->size = (__int64) size.QuadPart;
             stderr_logger->size = (__int64) size.QuadPart;
             stderr_logger->tid_ptr = &service->stderr_tid;
             stderr_logger->tid_ptr = &service->stderr_tid;
+            stderr_logger->rotate_online = &service->rotate_stderr_online;
 
 
             /* Logging thread. */
             /* Logging thread. */
             service->stderr_thread = create_logging_thread(stderr_logger);
             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);
           log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_DUPLICATEHANDLE_FAILED, NSSM_REG_STDERR, error_string(GetLastError()), 0);
           return 7;
           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;
     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. */
       /* Look for newline. */
       unsigned long i;
       unsigned long i;
       for (i = 0; i < in; i++) {
       for (i = 0; i < in; i++) {
@@ -527,6 +529,7 @@ unsigned long WINAPI log_and_rotate(void *arg) {
           size += (__int64) out;
           size += (__int64) out;
 
 
           /* Rotate. */
           /* Rotate. */
+          *logger->rotate_online = NSSM_ROTATE_ONLINE;
           TCHAR rotated[MAX_PATH];
           TCHAR rotated[MAX_PATH];
           rotated_filename(logger->path, rotated, _countof(rotated), 0);
           rotated_filename(logger->path, rotated, _countof(rotated), 0);
 
 

+ 1 - 0
io.h

@@ -21,6 +21,7 @@ typedef struct {
   HANDLE write_handle;
   HANDLE write_handle;
   __int64 size;
   __int64 size;
   unsigned long *tid_ptr;
   unsigned long *tid_ptr;
+  unsigned long *rotate_online;
 } logger_t;
 } logger_t;
 
 
 int get_createfile_parameters(HKEY, TCHAR *, TCHAR *, unsigned long *, unsigned long, unsigned long *, unsigned long, unsigned long *, unsigned long);
 int get_createfile_parameters(HKEY, TCHAR *, TCHAR *, unsigned long *, unsigned long, unsigned long *, unsigned long, unsigned long *, unsigned long);

BIN
messages.mc


+ 1 - 0
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("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("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("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 (str_equiv(argv[1], _T("install"))) {
       if (! is_admin) {
       if (! is_admin) {
         print_message(stderr, NSSM_MESSAGE_NOT_ADMINISTRATOR_CANNOT_INSTALL);
         print_message(stderr, NSSM_MESSAGE_NOT_ADMINISTRATOR_CANNOT_INSTALL);

+ 3 - 0
nssm.h

@@ -95,4 +95,7 @@ int usage(int);
 /* How many milliseconds to wait before updating service status. */
 /* How many milliseconds to wait before updating service status. */
 #define NSSM_SERVICE_STATUS_DEADLINE 20000
 #define NSSM_SERVICE_STATUS_DEADLINE 20000
 
 
+/* User-defined service controls can be in the range 128-255. */
+#define NSSM_SERVICE_CONTROL_ROTATE 128
+
 #endif
 #endif

+ 7 - 0
service.cpp

@@ -1281,6 +1281,7 @@ TCHAR *service_control_text(unsigned long control) {
     case SERVICE_CONTROL_PAUSE: return _T("PAUSE");
     case SERVICE_CONTROL_PAUSE: return _T("PAUSE");
     case SERVICE_CONTROL_CONTINUE: return _T("CONTINUE");
     case SERVICE_CONTROL_CONTINUE: return _T("CONTINUE");
     case SERVICE_CONTROL_INTERROGATE: return _T("INTERROGATE");
     case SERVICE_CONTROL_INTERROGATE: return _T("INTERROGATE");
+    case NSSM_SERVICE_CONTROL_ROTATE: return _T("ROTATE");
     default: return 0;
     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);
       log_service_control(service->name, control, false);
       return ERROR_CALL_NOT_IMPLEMENTED;
       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 */
   /* Unknown control */

+ 6 - 2
service.h

@@ -28,6 +28,10 @@
 #define NSSM_SHARE_INTERACTIVE_PROCESS NSSM_WIN32_SHARE_PROCESS _T("|") NSSM_INTERACTIVE_PROCESS
 #define NSSM_SHARE_INTERACTIVE_PROCESS NSSM_WIN32_SHARE_PROCESS _T("|") NSSM_INTERACTIVE_PROCESS
 #define NSSM_UNKNOWN _T("?")
 #define NSSM_UNKNOWN _T("?")
 
 
+#define NSSM_ROTATE_OFFLINE 0
+#define NSSM_ROTATE_ONLINE 1
+#define NSSM_ROTATE_ONLINE_ASAP 2
+
 typedef struct {
 typedef struct {
   bool native;
   bool native;
   TCHAR name[SERVICE_NAME_LENGTH];
   TCHAR name[SERVICE_NAME_LENGTH];
@@ -68,8 +72,8 @@ typedef struct {
   HANDLE stderr_thread;
   HANDLE stderr_thread;
   unsigned long stderr_tid;
   unsigned long stderr_tid;
   bool rotate_files;
   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_seconds;
   unsigned long rotate_bytes_low;
   unsigned long rotate_bytes_low;
   unsigned long rotate_bytes_high;
   unsigned long rotate_bytes_high;