Skip to main content

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.

FilePurpose
nginx.exeThe Nginx executable
conf\nginx.confMain configuration file
logs\error.logError log
logs\access.logAccess log
html\Default web root

Key Nginx Signal Commands

SignalCommandDescription
StartnginxLaunch Nginx
Stop (fast)nginx -s stopImmediately terminate
Quit (graceful)nginx -s quitFinish active requests, then stop
Reloadnginx -s reloadReload configuration without downtime
Reopen logsnginx -s reopenReopen 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
info

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

  1. Always test config before reload/restart: Run nginx.exe -t to catch syntax errors.
  2. Use graceful quit (-s quit) over fast stop (-s stop): Allows active requests to complete.
  3. Use reload for config changes: -s reload applies changes without dropping connections.
  4. Run from the Nginx directory: Use pushd/popd or -p prefix to ensure correct path resolution.
  5. 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.