简体   繁体   中英

How to show progress in a batch file using sqlcmd?

I'm doing a backup of a large database in a dos batch file (not powershell), using sqlcmd ( sqlcmd reference ). It takes about 30 minutes.

sqlcmd -S 127.0.0.1 -d DbNameHere -E -Q "BACKUP DATABASE [DbNameHere] TO DISK = N'c:\Temp\MyBackup.bak' WITH COPY_ONLY, NOFORMAT, INIT, NAME = N'My Full Database Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10"

If you run the BACKUP command in SQL Management Studio, you get the output, as it happens:

10 percent processed.
20 percent processed.
...

In a DOS batch, at best, I get all the 10,20,30..100 all appearing on the screen at once, when the backup is finished.

I've tried playing with these parameters, but I still don't get the desired progress update on screen:

-m-1
-V 1
-r1

These progress messages are buffered, and that might be part of the problem. This is dicsussed here for example: How do I flush the PRINT buffer in TSQL? But I have a single long running command, not multiple commands.

You can run a separate SQL statement elsewhere, and that tells you the progress and even the estimated finished time:

SELECT session_id as SPID, command, a.text AS Query, start_time, percent_complete, dateadd(second,estimated_completion_time/1000, getdate()) as estimated_completion_time 
FROM sys.dm_exec_requests r CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) a 
WHERE r.command in ('BACKUP DATABASE','RESTORE DATABASE')

But to use that, I would have to create a second batch file (with a sqlcmd executing this statement), make it open in a new window just before running sqlcmd backup, and run it in a loop on a 1 minute timer maybe, and end it when the backup is finished. All that in batch. Ideally, I'd rather keep it all in a single batch file! Outputting the standard progress messages would be much simpler!

Any ideas?

I've come up with a sort of solution. Downside is that it involves a second batchfile. It basically launches a progress window with a given name. This progress window refreshes regularly. Once the main process is finished, it calls taskkill using the given name. The progress batch relies on timeout . Both are on my Windows 8 workstation and 2008 R2 and 2012 servers.

Main backup batch:

@echo off
rem lots of other lines in my main batch file here

start "BACKUP_PROGRESS" /belownormal cmd /d /c "backup_progress2.cmd"

sqlcmd -S 127.0.0.1 -d DBNameHere-E -Q "BACKUP DATABASE [DBNameHere] TO DISK = N'c:\Temp\DBNameHere.bak' WITH COPY_ONLY, NOFORMAT, INIT, NAME = N'DBNameHere-Full Database Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10"

taskkill /FI "WINDOWTITLE eq BACKUP_PROGRESS" /F > nul

rem my main batch file continues here with lots of other lines

Progress batch file (called backup_progress2.cmd in the main batch). The setlocal enableextensions enabledelayedexpansion is just so that I can display the time with seconds using !time! .

@echo off
rem http://stackoverflow.com/questions/21434982/windows-batch-scripting-catch-user-reaction-to-timeout-command
SET timeout=60

:loop
cls
setlocal enableextensions enabledelayedexpansion
echo.
echo Time now: !time!
echo.
endlocal
sqlcmd -S 127.0.0.1 -d DBNameHere -E -Q "SET NOCOUNT ON;SELECT start_time,cast(percent_complete as int) as progress,dateadd(second,estimated_completion_time/1000, getdate()) as estimated_completion_time, cast(estimated_completion_time/1000/60 as int) as minutes_left FROM sys.dm_exec_requests r WHERE r.command='BACKUP DATABASE'"
echo.
echo Refreshing every %timeout% seconds.
timeout %timeout% > nul
goto loop

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM