log rotation for nginx on windows - windows

I've found plenty of references on the web for rotating the nginx logs under linux.. just send the USR1 signal to the process. But... unix like signals don't exist on windows and I haven't been able to find any information on this. How can I accomplish the same thing with nginx on windows??

To rotate nginx logs in Windows, create a batch file like this one:
For /f "tokens=2-4 delims=/ " %%a in ('date /t') do (set YMD=%%c-%%a-%%b)
move C:\path\to\nginx\logs\Access.log C:\path\to\nginx\logs\Access_%YMD%.log
move C:\path\to\nginx\logs\Error.log C:\path\to\nginx\logs\Error_%YMD%.log
call C:\path\to\nginx\nginx -p C:\path\to\nginx -s reopen
That first line just creates a timestamp (credit to Jay)
Then create a scheduled task in Windows to run that batch file how ever often you want to rotate the logs.
If nginx is running as a service (such as through the Windows Service Wrapper described here) you can't simply call nginx commands like nginx -s reopen directly. Instead you have to run the commands as the user who the service is running as.
To do this, create a new user called nginx (for example) and configure both the service and the scheduled task to run as that user. You'll also have to make sure your user has "Logon as a batch job" rights.
If you want to test your rotation script on the command line without having to use a scheduled task you can use
runas /user:nginx "C:\path\to\rotateLogs.bat"

Actually (despite tons of googling) the answer can be found squarely in the doc pages. The command is nginx -s reopen but this only seems to work when running nginx from the command line – currently the only official way to run nginx on Windows at this time.
My next challenge is to figure out how to make this work when running nginx as a windows service as described in the answers to Run nginx as a Windows service.

with windows server 2008 R2, I create this batch file, and I schedule it one time a day at midnight:
#echo off
SET DATE=%date%
SET DAY=%DATE:~0,2%
SET MONTH=%DATE:~3,2%
SET YEAR=%DATE:~6,4%
SET DATE_FRM=%YEAR%-%MONTH%-%DAY%
ECHO %DATE_FRM%
REM ECHO %YEAR%
REM ECHO %MONTH%
REM ECHO %DAY%
move D:\nginx-1.11.1\logs\access.log D:\nginx-1.11.1\logs\access_%DATE_FRM%.log
move D:\nginx-1.11.1\logs\error.log D:\nginx-1.11.1\logs\error_%DATE_FRM%.log
call D:\nginx-1.11.1\nginx -p D:\nginx-1.11.1 -s reopen

1.first create a file to store your log file list, like "nginx_log.lst" with content:
D:\projects\example.com\data\log\access.log
D:\projects\example.com\data\log\error.log
2.save the following content to a bat file such as "nginx_log_rotate.bat":
#echo off
set YMD=%date:~0,4%%date:~5,2%%date:~8,2%
set LOG_FILE=
FOR /F "eol=; delims=, " %%i in (nginx_log.lst) do (
echo "%%i"
move "%%i" "%%i.%YMD%"
)
pushd C:\tools\nginx
nginx -s reopen
popd
pause
#echo on
3. create a schedule task to run the bat as you wish

I wrote small utility which rotates log files after stoppig nginx (which is running as windows service) for few seconds.
It had specific requirement to stop , then copy log files and then restart service nighly basis. You can download the code and change it whatever way you want.
Code is here : http://mandar.tumblr.com/post/5419161330/nginx-logrotate-windows
Thanks

For some reasons below batch file worked for me.
For /f "tokens=1-4 delims=/ " %%a in ('date /t') do (set YMD=%%c-%%a-%%b)
move .\logs\access.log .\logs\access.%YMD%.log
move .\logs\error.log .\logs\error.%YMD%.log
nginx.exe -s reload
It's more or less same as Tom's answer above.

#echo off
SET DATE_FRM=%date%
REM set path of Nginx root folder.
SET NGINX_PATH="E:\nginx-1.14.2"
REM create old_logs folder if not exists , we will move old logs in this folder.
if not exist "%NGINX_PATH%\old_logs\NUL" mkdir "%NGINX_PATH%\old_logs"
REM move error.log in old_logs from logs folder and rename it
move %NGINX_PATH%\logs\access.log %NGINX_PATH%\old_logs\access_%DATE_FRM%.log
move %NGINX_PATH%\logs\error.log %NGINX_PATH%\old_logs\error_%DATE_FRM%.log
REM reopn nginx logs, this will create new error.log for nginx.
call %NGINX_PATH%\nginx -p %NGINX_PATH% -s reopen
REM compress error%DATE_FRM%.log, this will create error_%DATE_FRM%.log.zip file.
powershell Compress-Archive -Path %NGINX_PATH%\old_logs\access_%DATE_FRM%.log -DestinationPath %NGINX_PATH%\old_logs\access_%DATE_FRM%.log.zip -force
powershell Compress-Archive -Path %NGINX_PATH%\old_logs\error_%DATE_FRM%.log -DestinationPath %NGINX_PATH%\old_logs\error_%DATE_FRM%.log.zip -force
REM delete error%DATE_FRM%.log from old_logs.
del %NGINX_PATH%\old_logs\access_%DATE_FRM%.log
del %NGINX_PATH%\old_logs\error_%DATE_FRM%.log

I use NSSM to manage Nginx on Windows (checked on WhiteHorse). Although this utility has built-in rotate functionality, it probably doesn't work properly. The documentation warns about risk of online rotation.
Two service entries should be configured:
Nginx, and
Nginx Rotate Logs.
The solution doesn't support rotation based on file size or file age. It's possible to setup schedule to rotate logs using nginx -s reopen.
First,
create Nginx Rotate Logs service, using NSSM (note bene: you may use the same command to create main Nginx service).
Command below will create service entry:
nssm install "Nginx Rotate" C:\tools\nginx-1.21.6\nginx.exe
Next lines will configure service step-by-step, oneliner is not available here.
nssm set "Nginx Rotate" AppParameters "-s reopen"
nssm set "Nginx Rotate" AppExit Default Exit
nssm set "Nginx Rotate" AppStdout C:\tools\nginx-1.21.6\logs\access.log
nssm set "Nginx Rotate" AppStderr C:\tools\nginx-1.21.6\logs\error.log
nssm set "Nginx Rotate" AppRedirectHook 1
nssm set "Nginx Rotate" AppRotateFiles 1
nssm set "Nginx Rotate" AppRotateOnline 1
nssm set "Nginx Rotate" AppTimestampLog 1
nssm set "Nginx Rotate" Description "Some description"
nssm set "Nginx Rotate" DisplayName "Nginx Rotate Logs"
nssm set "Nginx Rotate" ObjectName DOMAIN\user "password"
nssm set "Nginx Rotate" Start SERVICE_DEMAND_START
nssm set "Nginx Rotate" Type SERVICE_WIN32_OWN_PROCESS
Then edit service:
nssm edit "Nginx Rotate"
At the last tab you need set:
Event = Log rotation + Before online log rotation
as shown in the picture below.
As a result, this service will be in manual mode. After start it rotates logs and stops.
Second,
create a schedule task.
schtasks /create /sc daily /st 03:30 /tn "Nginx Rotate Logs" /tr "C:\Program Files\PowerShell\7\pwsh.exe -command start-service 'Nginx Rotate Logs'"
Important,
use the same user both for Nginx, Nginx Rotate Logs and Schedule Task.
Usage:
While main Nginx is operating, the schedule task runs once a day, rotating files.
Aux:
You may add a daily task (or add to hook tab) to compress and purge old logs, for example:
# install PSCX module
Install-Module -Name Pscx -AllowPrerelease -AllowClobber
# compress
Get-ChildItem 'C:\tools\nginx-1.21.6\logs\*.log' | Where {$_.lastwritetime -lt (Get-Date).AddDays(-1)} | write-zip
# purge yesterday zip
Get-ChildItem 'C:\tools\nginx-1.21.6\logs\*.zip' | Where {$_.lastwritetime -lt (Get-Date).AddDays(-2)} | Remove-Item -Force

#echo off
net stop nginx
for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a"
set "YY=%dt:~2,2%" & set "YYYY=%dt:~0,4%" & set "MM=%dt:~4,2%" & set "DD=%dt:~6,2%"
set "HH=%dt:~8,2%" & set "Min=%dt:~10,2%" & set "Sec=%dt:~12,2%"
set "datestamp=%YYYY%%MM%%DD%" & set "timestamp=%HH%%Min%%Sec%"
set "fullstamp=%YYYY%-%MM%-%DD%_%HH%-%Min%-%Sec%"
echo move %~dp0\Access.log %~dp0\Old\Access_%fullstamp%.log
move %~dp0\Access.log %~dp0\Old\Access_%fullstamp%.log
echo move %~dp0\Error.log %~dp0\Old\Error_%fullstamp%.log
move %~dp0\Error.log %~dp0\Old\Error_%fullstamp%.log
net start nginx

Related

How to auto restart a java application using Procrun by Exit Code

My application has a self-update feature.
It downloads a new version by itself, and when this occurrs at the end of the download process the JVM exits with code 2.
Is possible to configure the Procrun to auto-restart the service if the exit code 2 occurrs ?
I solved using another tool for running my application as a service: NSSM
With it, I register a parameter to NSSM like this:
nssm install my-service-name "java -jar snapshot.jar"
nssm set my-service-name AppEvents "Start/Pre" "cmd /c copy /y my-app.jar snapshot.jar"
nssm set my-service-name AppExit Default Exit
nssm set my-service-name AppExit 2 Restart
nssm set my-service-name AppDirectory "c:\path\to\my\app"
So, this lines will:
Register a windows service named my-service-name who launches a copy of my jar (java) application.
Set a parameter to NSSM to copy my-app.jar to snapshot.jar before start the service.
Set a parameter to NSSM to specify that, when my app terminates the default behavior is assuming that the service must stop
Set a parameter to NSSM to specify that, when my app terminates with the exit code 2 it must be restarted (my java application) and the service must continue to running.
Set a parameter to NSSM to specify that my app will using the current directory as c:\path\to\my\app
Another solution is creating a batch file to be on loop, like this (I called it run-app.bat):
#echo off
set java=C:\Program Files (x86)\Java\jre1.8.0_192
:start
copy /y my-app.jar snapshot.jar
if %errorlevel% equ 0 goto :run
if %errorlevel% neq 0 goto :end
:run
"%java%\bin\java.exe" -jar snapshot.jar --start
if %errorlevel% equ 2 goto :start
:end
exit /b %errorlevel%
And using the NSSM to register the service in a simple way:
nssm install my-service-name "cmd /c run-app.bat"
nssm set my-service-name AppDirectory "c:\path\to\my\app"
In this scenario, the NSSM will just launch my batch run-app.bat.
The batch will stay on loop (restarting my app) while the application exits with code 2.

Windows net stop start not working in bat file

I have the following script in a bat file. If I run NET STOP "XXX" and NET START "XXX", it will work. But when I execute the bat file, it does not restart the service as I expected. The log file however was renamed. I have tried to run the bat file as administrator but still no good.
#echo off
findstr /m "memory" "C:\Services\ServiceLogs\NZTA_OnTheMove_AlertSender.log"
if %errorlevel%==0 (
NET STOP "Jericho NZTA Alert Sender"
timeout 30
NET START "Jericho NZTA Alert Sender"
set HR=%time:~0,2%
set HR=%Hr: =0%
set HR=%HR: =%
rename "C:\Services\ServiceLogs\NZTA_OnTheMove_AlertSender.log" "NZTA_OnTheMove_AlertSender_%date:~10,4%-%date:~4,2%-%date:~7,2%_%HR%%time:~3,2%.err"
)
After bypassing the logic findstr /m "memory" "C:\Services\ServiceLogs\NZTA_OnTheMove_AlertSender.log"
if %errorlevel%==0
Script works again.

Runas SC stop remote service with spaces

I am using the sc command to remotely restart a process under runas. This works perfectly with a service that has no spaces, but if it has spaces, forcing me to use ' inside the runas "command" quotes, it fails and cannot find the service.
I have already checked the properties of this particular service to ensure the service name (it is the same as the display name).
#ECHO OFF
REM Prompt for Domain & Username. Password will be prompted when run.
set /P Domainn=Enter Domain Name:
set /P Usern=Enter Username:
set service=workingservice
REM set service='Not a working service'
REM Define Start Stops
set userrunasstop=runas /profile /user:%domainn%\%usern% "sc \\%domainn% stop %service%"
set userrunasstart=runas /profile /user:%domainn%\%usern% "sc \\%domainn% start %service%"
:optionmenu
CLS
ECHO 1 - Stop Service
ECHO 2 - Start Service
ECHO q - Quit
ECHO.
set /P optionnum=Enter command number:
GOTO option%optionnum%
:option1
REM Stop Client
%userrunasstop%
goto optionmenu
:option2
REM Start Client
%userrunasstart%
goto optionmenu
:optionq
EXIT
This script works great as shown, but when I comment out set service=workingservice and un-comment set service='Not a working service it doesn't work. Also, if I use runas to open its open cmd.exe, I can then successfully run the sc command with quotes around the service name.
I have set up a workaround for this issue by opening up a new command prompt under runas. And in the new command prompt calling another bat file that executes the sc stop service command. This removes the multiple quoting that was causing the error.
I am still working on passing variables from the runas batch file to the sc batch file to allow the %domain% variable to be input into the sc command.
File runas.bat
set /P Domainn=Enter Domain Name:
set /P Usern=Enter Username:
runas /profile /user:%domainn%\%usern% "cmd sc.bat"
File sc.bat (minus all the frills in the original script)
set service='Service with spaces'
sc \\domainname stop %service%

Windows Batch script leaves console window open

I'm trying to set up a friends Windows 7 computer to run Nginx & PHP5. I found a script online for starting and stopping Nginx & PHP, after adding the directory change line I was able to make it work. However, there seems to be an issue causing it to leave the second console window that starts PHP open. Is there a way to make that console window close?
Batch script:
#ECHO OFF
CD C:\nginx
tasklist /FI "IMAGENAME eq nginx.exe" | find /I "nginx.exe" > NUL && (
GOTO STOP
) || (
GOTO START
)
:START
ECHO Starting nginx
start nginx
ECHO Starting PHP
start php\php-cgi.exe -b 127.0.0.1:9000 -c c:\nginx\php\php.ini
GOTO DONE
:STOP
ECHO Stopping nginx
start nginx -s quit
ECHO Stopping PHP
taskkill /f /IM php-cgi.exe
:DONE
TIMEOUT 3
You could use the /b parameter on START to start the application without opening another cmd window
START /b php\php-cgi.exe -b 127.0.0.1:9000 -c c:\nginx\php\php.ini
Update:
It appears this is the behavior of php-cgi.exe. See this article for the full story and workaround. http://wiki.nginx.org/PHPFastCGIOnWindows
After being launched, php-cgi.exe will keep listening for connections
in a command prompt window. To hide that window, use the tiny utility
RunHiddenConsole
Basically, you just need to d/l and unzip RunHiddenConsole to your nginx directory, then change this line to:
RunHiddenConsole.exe php\php-cgi.exe -b 127.0.0.1:9000 -c c:\nginx\php\php.ini
You're looking for
start php\php-cgi.exe -b 127.0.0.1:9000 -c c:\nginx\php\php.ini
/exit b
To run a .BAT Invisible you can use a simple vbs script.
Put this in a .VBS file :
CreateObject("Wscript.Shell").Run """" & WScript.Arguments(0) & """", 0, False
And then run your BAT like this :
wscript.exe "C:\invisible.vbs" "C:\YourBat.bat"

How to write batch file to retsart services with varying names

I'm trying to write a batch file that will restart a service from a program my company uses called Bomgar that allows our help desk technicians to remote into an employees computer. I know how to write a batch file that restarts services, the problem is that each service has a unique number ID on it (example; bomgar-ps-10000000-10000000) that is completely different machine to machine. Is there a way to restart services whose name falls within a "range"? Say any service whose name contains "bomgar-ps" as an example.
Really not sure how to handle this. The problem we're having is that this service is failing to start up occasionally and when an employee calls with a problem, they aren't tech savvy so a lot of time is wasted trying to guide them into services.msc and manually restarting the service.
This should work also.
#echo off
set "servicename="
for /f "tokens=*" %%a in ('net start ^| find /i "bomgar-ps") do set "servicename=%%a"
if defined servicename net stop "%servicename%"
ping -n 3 localhost >nul
net start "%servicename%"
echo servicename "%servicename%" has attempted to restart
If you are merely guiding someone over the phone to restart the service then this will print the name to the console, in a fairly simple manner (add /i to the find command if bomgar can be mixed case"
net start|find "bomgar"
Try this, I used it to search for the print spooler name and restart it. You should be able to replace spool with boomgar-ps, you may even be able to remove the SERVICE_NAME: part.
#ECHO OFF
>%TEMP%\~sc.log (sc queryex type= service state= all)
for /F "tokens=1,* delims=: " %%I in ('type %TEMP%\~sc.log^|find "SERVICE_NAME: Spool"') do set scname=%%J
ECHO RESTARTING %scname%
sc stop %scname%
sc start %scname%

Resources