or replaced them.\r
\r
NSSM can also rotate files which hit the configured size threshold while the\r
-service is running. To enable this feature, set AppRotateOnline to a non-zero\r
+service is running. Additionally, you can trigger an on-demand rotation by\r
+running the command\r
+\r
+ nssm rotate <servicename>\r
+\r
+On-demand rotations will happen after the next line of data is read from\r
+the managed application, regardless of the value of AppRotateBytes. Be aware\r
+that if the application is not particularly verbose the rotation may not\r
+happen for some time.\r
+\r
+To enable online and on-demand rotation, set AppRotateOnline to a non-zero\r
value.\r
\r
Note that online rotation requires NSSM to intercept the application's I/O\r
/* Get rotation stuff. */\r
if (SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE, BM_GETCHECK, 0, 0) & BST_CHECKED) {\r
service->rotate_files = true;\r
- 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);\r
check_number(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW, &service->rotate_bytes_low);\r
}\r
\r
/* Try online rotation only if a size threshold is set. */\r
logger_t *stdout_logger = 0;\r
- if (service->rotate_files && service->rotate_stdout_online && size.QuadPart) {\r
+ if (service->rotate_files && service->rotate_stdout_online) {\r
stdout_logger = (logger_t *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(logger_t));\r
if (stdout_logger) {\r
/* Pipe between application's stdout and our logging handle. */\r
stdout_logger->write_handle = stdout_handle;\r
stdout_logger->size = (__int64) size.QuadPart;\r
stdout_logger->tid_ptr = &service->stdout_tid;\r
+ stdout_logger->rotate_online = &service->rotate_stdout_online;\r
\r
/* Logging thread. */\r
service->stdout_thread = create_logging_thread(stdout_logger);\r
log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_DUPLICATEHANDLE_FAILED, NSSM_REG_STDOUT, error_string(GetLastError()), 0);\r
return 4;\r
}\r
- service->rotate_stdout_online = false;\r
+ service->rotate_stdout_online = NSSM_ROTATE_OFFLINE;\r
}\r
\r
set_flags = true;\r
\r
/* Try online rotation only if a size threshold is set. */\r
logger_t *stderr_logger = 0;\r
- if (service->rotate_files && service->rotate_stderr_online && size.QuadPart) {\r
+ if (service->rotate_files && service->rotate_stderr_online) {\r
stderr_logger = (logger_t *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(logger_t));\r
if (stderr_logger) {\r
/* Pipe between application's stderr and our logging handle. */\r
stderr_logger->write_handle = stderr_handle;\r
stderr_logger->size = (__int64) size.QuadPart;\r
stderr_logger->tid_ptr = &service->stderr_tid;\r
+ stderr_logger->rotate_online = &service->rotate_stderr_online;\r
\r
/* Logging thread. */\r
service->stderr_thread = create_logging_thread(stderr_logger);\r
log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_DUPLICATEHANDLE_FAILED, NSSM_REG_STDERR, error_string(GetLastError()), 0);\r
return 7;\r
}\r
- service->rotate_stderr_online = false;\r
+ service->rotate_stderr_online = NSSM_ROTATE_OFFLINE;\r
}\r
}\r
\r
}\r
else if (ret) continue;\r
\r
- if (size + (__int64) in >= logger->size) {\r
+ if (*logger->rotate_online == NSSM_ROTATE_ONLINE_ASAP || (logger->size && size + (__int64) in >= logger->size)) {\r
/* Look for newline. */\r
unsigned long i;\r
for (i = 0; i < in; i++) {\r
size += (__int64) out;\r
\r
/* Rotate. */\r
+ *logger->rotate_online = NSSM_ROTATE_ONLINE;\r
TCHAR rotated[MAX_PATH];\r
rotated_filename(logger->path, rotated, _countof(rotated), 0);\r
\r
HANDLE write_handle;\r
__int64 size;\r
unsigned long *tid_ptr;\r
+ unsigned long *rotate_online;\r
} logger_t;\r
\r
int get_createfile_parameters(HKEY, TCHAR *, TCHAR *, unsigned long *, unsigned long, unsigned long *, unsigned long, unsigned long *, unsigned long);\r
if (str_equiv(argv[1], _T("pause"))) exit(control_service(SERVICE_CONTROL_PAUSE, argc - 2, argv + 2));\r
if (str_equiv(argv[1], _T("continue"))) exit(control_service(SERVICE_CONTROL_CONTINUE, argc - 2, argv + 2));\r
if (str_equiv(argv[1], _T("status"))) exit(control_service(SERVICE_CONTROL_INTERROGATE, argc - 2, argv + 2));\r
+ if (str_equiv(argv[1], _T("rotate"))) exit(control_service(NSSM_SERVICE_CONTROL_ROTATE, argc - 2, argv + 2));\r
if (str_equiv(argv[1], _T("install"))) {\r
if (! is_admin) {\r
print_message(stderr, NSSM_MESSAGE_NOT_ADMINISTRATOR_CANNOT_INSTALL);\r
/* How many milliseconds to wait before updating service status. */\r
#define NSSM_SERVICE_STATUS_DEADLINE 20000\r
\r
+/* User-defined service controls can be in the range 128-255. */\r
+#define NSSM_SERVICE_CONTROL_ROTATE 128\r
+\r
#endif\r
case SERVICE_CONTROL_PAUSE: return _T("PAUSE");\r
case SERVICE_CONTROL_CONTINUE: return _T("CONTINUE");\r
case SERVICE_CONTROL_INTERROGATE: return _T("INTERROGATE");\r
+ case NSSM_SERVICE_CONTROL_ROTATE: return _T("ROTATE");\r
default: return 0;\r
}\r
}\r
*/\r
log_service_control(service->name, control, false);\r
return ERROR_CALL_NOT_IMPLEMENTED;\r
+\r
+ case NSSM_SERVICE_CONTROL_ROTATE:\r
+ log_service_control(service->name, control, true);\r
+ if (service->rotate_stdout_online) service->rotate_stdout_online = NSSM_ROTATE_ONLINE_ASAP;\r
+ if (service->rotate_stdout_online) service->rotate_stderr_online = NSSM_ROTATE_ONLINE_ASAP;\r
+ return NO_ERROR;\r
}\r
\r
/* Unknown control */\r
#define NSSM_SHARE_INTERACTIVE_PROCESS NSSM_WIN32_SHARE_PROCESS _T("|") NSSM_INTERACTIVE_PROCESS\r
#define NSSM_UNKNOWN _T("?")\r
\r
+#define NSSM_ROTATE_OFFLINE 0\r
+#define NSSM_ROTATE_ONLINE 1\r
+#define NSSM_ROTATE_ONLINE_ASAP 2\r
+\r
typedef struct {\r
bool native;\r
TCHAR name[SERVICE_NAME_LENGTH];\r
HANDLE stderr_thread;\r
unsigned long stderr_tid;\r
bool rotate_files;\r
- bool rotate_stdout_online;\r
- bool rotate_stderr_online;\r
+ unsigned long rotate_stdout_online;\r
+ unsigned long rotate_stderr_online;\r
unsigned long rotate_seconds;\r
unsigned long rotate_bytes_low;\r
unsigned long rotate_bytes_high;\r