How to Start and Stop Nginx from a Batch Script
Nginx is a high-performance web server, reverse proxy, and load balancer renowned for its efficiency with static content and concurrent connections. While Nginx is primarily associated with Linux, it runs natively on Windows and can be fully managed from Batch scripts. Automating Nginx lifecycle operations is essential for deployment pipelines, configuration changes, and maintenance tasks.
In this guide, we will explore how to start, stop, reload, and manage Nginx from a Batch Script on Windows.
Prerequisites
Nginx for Windows is a standalone application (no installation required). Download and extract it to a directory like C:\nginx.
| File | Purpose |
|---|---|
nginx.exe | The Nginx executable |
conf\nginx.conf | Main configuration file |
logs\error.log | Error log |
logs\access.log | Access log |
html\ | Default web root |
Key Nginx Signal Commands
| Signal | Command | Description |
|---|---|---|
| Start | nginx | Launch Nginx |
| Stop (fast) | nginx -s stop | Immediately terminate |
| Quit (graceful) | nginx -s quit | Finish active requests, then stop |
| Reload | nginx -s reload | Reload configuration without downtime |
| Reopen logs | nginx -s reopen | Reopen log files (for rotation) |
Method 1: Basic Start and Stop
@echo off
setlocal enabledelayedexpansion
set "NGINX_HOME=C:\nginx"
if "%~1"=="" (
echo Usage: nginx.bat [start^|stop^|quit^|reload^|restart]
pause
exit /b 1
)
if not exist "%NGINX_HOME%\nginx.exe" (
echo [ERROR] Nginx not found at %NGINX_HOME%\nginx.exe
pause
exit /b 1
)
pushd "%NGINX_HOME%"
set "handled=0"
if /i "%~1"=="start" (
set "handled=1"
tasklist /fi "imagename eq nginx.exe" 2>nul | findstr /i "nginx.exe" >nul
if !errorlevel!==0 (
echo [WARNING] Nginx is already running. Use reload or restart instead.
) else (
echo Starting Nginx...
start "" nginx.exe
echo [OK] Nginx start initiated.
)
)
if /i "%~1"=="stop" (
set "handled=1"
echo Stopping Nginx (fast^)...
nginx.exe -s stop
if !errorlevel!==0 (
echo [OK] Nginx stopped.
) else (
echo [ERROR] Stop failed. Is Nginx running?
)
)
if /i "%~1"=="quit" (
set "handled=1"
echo Stopping Nginx (graceful^)...
nginx.exe -s quit
if !errorlevel!==0 (
echo [OK] Graceful shutdown initiated.
) else (
echo [ERROR] Graceful stop failed. Is Nginx running?
)
)
if /i "%~1"=="reload" (
set "handled=1"
echo Reloading Nginx configuration...
nginx.exe -s reload
if !errorlevel!==0 (
echo [OK] Configuration reloaded.
) else (
echo [ERROR] Reload failed. Is Nginx running?
)
)
if /i "%~1"=="restart" (
set "handled=1"
echo Restarting Nginx...
nginx.exe -s quit 2>nul
timeout /t 3 /nobreak >nul
start "" nginx.exe
echo [OK] Nginx restart initiated.
)
if "!handled!"=="0" (
echo [ERROR] Unknown command: %~1
echo Valid commands: start, stop, quit, reload, restart
)
popd
pause
On Windows, Nginx must be started from its installation directory (or use the -p flag to specify the prefix path). The pushd/popd pattern ensures Nginx can find its configuration and log files.
Method 2: Start with Configuration Test and Health Check
@echo off
setlocal enabledelayedexpansion
set "NGINX_HOME=C:\nginx"
set "health_url=http://localhost:80"
set "max_retries=10"
set "retry_delay=2"
echo =============================================
echo NGINX STARTUP
echo =============================================
echo.
if not exist "%NGINX_HOME%\nginx.exe" (
echo [ERROR] Nginx not found at %NGINX_HOME%\nginx.exe
pause
exit /b 1
)
pushd "%NGINX_HOME%"
:: Step 1: Test configuration
echo [1/3] Testing configuration...
nginx.exe -t 2> "%temp%\nginx_test.txt"
if %errorlevel% neq 0 (
echo [FAIL] Configuration error:
type "%temp%\nginx_test.txt"
del "%temp%\nginx_test.txt" 2>nul
popd
pause
exit /b 1
)
echo Configuration OK.
del "%temp%\nginx_test.txt" 2>nul
:: Step 2: Check if already running
tasklist /fi "imagename eq nginx.exe" 2>nul | findstr /i "nginx.exe" >nul
if %errorlevel%==0 (
echo [INFO] Nginx is already running. Use reload or restart.
popd
pause
exit /b 0
)
:: Step 3: Start
echo [2/3] Starting Nginx...
start "" nginx.exe
:: Step 4: Health check
echo [3/3] Verifying...
set "attempt=0"
:check
set /a attempt+=1
powershell -noprofile -command ^
"try { $r = Invoke-WebRequest -Uri '%health_url%' -UseBasicParsing -TimeoutSec 2; ^
if ($r.StatusCode -eq 200) { exit 0 } else { exit 1 } } catch { exit 1 }" >nul 2>&1
if !errorlevel!==0 (
echo.
echo [SUCCESS] Nginx is running at %health_url%
popd
exit /b 0
)
if !attempt! geq %max_retries% (
echo.
echo [ERROR] Nginx did not respond after %max_retries% attempts.
echo Check: %NGINX_HOME%\logs\error.log
popd
pause
exit /b 1
)
echo Attempt !attempt!/%max_retries%...
timeout /t %retry_delay% /nobreak >nul
goto check
Method 3: Nginx Management Console
@echo off
title Nginx Manager
setlocal enabledelayedexpansion
set "NGINX_HOME=C:\nginx"
if not exist "%NGINX_HOME%\nginx.exe" (
echo [ERROR] Nginx not found at %NGINX_HOME%\nginx.exe
pause
exit /b 1
)
:menu
cls
echo =============================================
echo NGINX MANAGER
echo Home: %NGINX_HOME%
echo =============================================
echo.
:: Check status
tasklist /fi "imagename eq nginx.exe" 2>nul | findstr /i "nginx.exe" >nul
if %errorlevel%==0 (
echo Status: RUNNING
for /f %%C in ('tasklist /fi "imagename eq nginx.exe" 2^>nul ^| find /c "nginx.exe"') do echo Processes: %%C
) else (
echo Status: STOPPED
)
echo.
echo [1] Start
echo [2] Stop (graceful^)
echo [3] Stop (fast^)
echo [4] Reload configuration
echo [5] Restart
echo [6] Test configuration
echo [7] View error log (last 30 lines^)
echo [8] View access log (last 20 lines^)
echo [9] Show version and compile info
echo [0] Exit
echo.
set /p "choice=Select: "
pushd "%NGINX_HOME%"
if "!choice!"=="1" (
tasklist /fi "imagename eq nginx.exe" 2>nul | findstr /i "nginx.exe" >nul
if !errorlevel!==0 (
echo Nginx is already running. Use Reload or Restart instead.
pause
) else (
echo Starting...
start "" nginx.exe
timeout /t 2 /nobreak >nul
)
)
if "!choice!"=="2" (
echo Graceful stop...
nginx.exe -s quit
timeout /t 3 /nobreak >nul
)
if "!choice!"=="3" (
echo Fast stop...
nginx.exe -s stop
timeout /t 2 /nobreak >nul
)
if "!choice!"=="4" (
echo Testing config first...
nginx.exe -t
if !errorlevel!==0 (
nginx.exe -s reload
if !errorlevel!==0 (
echo [OK] Reloaded.
) else (
echo [ERROR] Reload failed. Is Nginx running?
)
) else (
echo [ERROR] Config invalid. Not reloaded.
)
pause
)
if "!choice!"=="5" (
echo Restarting...
nginx.exe -s quit 2>nul
timeout /t 3 /nobreak >nul
start "" nginx.exe
timeout /t 2 /nobreak >nul
)
if "!choice!"=="6" (
echo.
nginx.exe -t
pause
)
if "!choice!"=="7" (
echo.
powershell -noprofile -command "Get-Content '%NGINX_HOME%\logs\error.log' -Tail 30"
pause
)
if "!choice!"=="8" (
echo.
powershell -noprofile -command "Get-Content '%NGINX_HOME%\logs\access.log' -Tail 20"
pause
)
if "!choice!"=="9" (
echo.
nginx.exe -V
pause
)
popd
if "!choice!"=="0" exit /b 0
goto menu
Method 4: Configuration Reload (Zero-Downtime Updates)
The most common production operation is reloading configuration after changes:
@echo off
setlocal
set "NGINX_HOME=C:\nginx"
echo =============================================
echo NGINX CONFIG RELOAD
echo =============================================
echo.
if not exist "%NGINX_HOME%\nginx.exe" (
echo [ERROR] Nginx not found at %NGINX_HOME%\nginx.exe
pause
exit /b 1
)
pushd "%NGINX_HOME%"
:: Verify Nginx is running
tasklist /fi "imagename eq nginx.exe" 2>nul | findstr /i "nginx.exe" >nul
if %errorlevel% neq 0 (
echo [ERROR] Nginx is not running. Start it before reloading.
popd
pause
exit /b 1
)
:: Test before reloading
echo Testing configuration...
nginx.exe -t 2>&1
if %errorlevel% neq 0 (
echo.
echo [ABORT] Configuration has errors. Not reloading.
echo Fix the configuration and try again.
popd
pause
exit /b 1
)
echo.
echo Configuration is valid. Reloading...
nginx.exe -s reload
if %errorlevel%==0 (
echo [SUCCESS] Nginx reloaded with new configuration.
echo Active connections were not interrupted.
) else (
echo [ERROR] Reload command failed.
)
popd
pause
Method 5: Deploy and Reload
Update web content and reload Nginx:
@echo off
setlocal
set "NGINX_HOME=C:\nginx"
set "web_root=%NGINX_HOME%\html\mysite"
set "source=C:\Build\Output\frontend"
echo =============================================
echo DEPLOY AND RELOAD
echo =============================================
echo.
:: Step 1: Deploy new files
echo [1/3] Deploying files...
robocopy "%source%" "%web_root%" /mir /r:2 /w:3 /np /ndl /nfl >nul
if %errorlevel% gtr 7 (
echo [ERROR] File copy failed.
pause
exit /b 1
)
echo Files updated.
:: Step 2: Test config
echo [2/3] Testing configuration...
pushd "%NGINX_HOME%"
nginx.exe -t 2>"%temp%\nginx_test.txt"
if %errorlevel% neq 0 (
echo [ERROR] Configuration error after deploy:
type "%temp%\nginx_test.txt"
del "%temp%\nginx_test.txt" 2>nul
popd
pause
exit /b 1
)
del "%temp%\nginx_test.txt" 2>nul
echo Config OK.
:: Step 3: Reload
echo [3/3] Reloading Nginx...
nginx.exe -s reload
set "reload_rc=%errorlevel%"
popd
if %reload_rc%==0 (
echo.
echo [SUCCESS] Deployment complete. Nginx reloaded.
) else (
echo.
echo [ERROR] Reload failed. Is Nginx running?
)
pause
Log Rotation
Nginx on Windows does not rotate logs automatically. Use a script to rotate them:
@echo off
setlocal enabledelayedexpansion
set "NGINX_HOME=C:\nginx"
set "log_dir=%NGINX_HOME%\logs"
for /f "tokens=2 delims==" %%T in ('wmic os get LocalDateTime /value') do set "dt=%%T"
set "timestamp=%dt:~0,8%"
:: Rename current logs
set "rotated=0"
if exist "%log_dir%\access.log" (
move "%log_dir%\access.log" "%log_dir%\access_%timestamp%.log" >nul 2>&1
if !errorlevel!==0 (set /a rotated+=1) else (echo [WARNING] Could not rotate access.log)
)
if exist "%log_dir%\error.log" (
move "%log_dir%\error.log" "%log_dir%\error_%timestamp%.log" >nul 2>&1
if !errorlevel!==0 (set /a rotated+=1) else (echo [WARNING] Could not rotate error.log)
)
if !rotated!==0 (
echo [INFO] No logs were rotated.
) else (
:: Tell Nginx to reopen log files (creates new ones)
pushd "%NGINX_HOME%"
nginx.exe -s reopen
popd
echo [OK] !rotated! log file(s^) rotated.
)
:: Clean old logs (keep 30 days)
forfiles /p "%log_dir%" /m "access_*.log" /d -30 /c "cmd /c del @path" 2>nul
forfiles /p "%log_dir%" /m "error_*.log" /d -30 /c "cmd /c del @path" 2>nul
echo [OK] Old logs cleaned up.
Common Mistakes
The Wrong Way: Starting Multiple Nginx Instances
:: WRONG - Running start multiple times creates duplicate processes
start "" nginx.exe
start "" nginx.exe
:: Two master processes, port conflict
Output Concern:
Always check if Nginx is already running before starting. Multiple instances cause port binding conflicts and unpredictable behavior. Use tasklist to verify before starting.
The Wrong Way: Reloading Without Config Test
:: WRONG - Bad config causes reload to fail and may stop serving
nginx.exe -s reload
:: If nginx.conf has errors, worker processes may not restart
Always run nginx.exe -t to validate the configuration before reloading. Unlike Apache, Nginx's reload on Windows can behave unpredictably with invalid configurations.
Best Practices
- Always test config before reload/restart: Run
nginx.exe -tto catch syntax errors. - Use graceful quit (
-s quit) over fast stop (-s stop): Allows active requests to complete. - Use reload for config changes:
-s reloadapplies changes without dropping connections. - Run from the Nginx directory: Use
pushd/popdor-p prefixto ensure correct path resolution. - Implement log rotation: Nginx on Windows does not auto-rotate logs. Schedule rotation scripts.
Conclusion
Starting and stopping Nginx from a Batch Script involves running nginx.exe with signal commands (-s stop, -s quit, -s reload). The key to reliable Nginx management on Windows is always validating configuration with nginx.exe -t before any reload or restart, checking for existing instances before starting, and using graceful quit to avoid dropping active connections. By combining configuration testing, health checks, deployment workflows, and log rotation into management scripts, administrators maintain robust Nginx operations on Windows servers.