Here is the script.
DECLARE @name VARCHAR(50) -- database name
DECLARE @path VARCHAR(256) -- path for backup files
DECLARE @fileName VARCHAR(256) -- filename for backup
DECLARE @fileDate VARCHAR(20) -- used for file name
DECLARE @DeleteBakDate DATETIME = Dateadd(day, -5, Getdate()); -- 5-day retention for .bak files
DECLARE @DeleteTxtDate DATETIME = Dateadd(day, -30, Getdate()); -- 30-day retention for .txt files
DECLARE @outputFile VARCHAR(256) -- output log file
-- specify database backup directory
SET @path = '\\servername\foldername\'
-- specify filename format for backup
SELECT @fileDate = CONVERT(VARCHAR(20), Getdate(), 112) + '_' + Replace(CONVERT(VARCHAR(20), Getdate(), 108), ':', '')
-- specify output file for job with date format
SET @outputFile = @path + 'Backup_Job_Output_' + @fileDate + '.txt'
DECLARE db_cursor CURSOR read_only FOR
SELECT NAME
FROM master.dbo.sysdatabases
WHERE NAME NOT IN ('master', 'model', 'msdb', 'tempdb') -- exclude these databases
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @name
WHILE @@FETCH_STATUS = 0
BEGIN
SET @fileName = @path + @name + '_' + @fileDate + '.bak'
-- Backup database and capture the output using xp_cmdshell
DECLARE @cmd VARCHAR(1024)
SET @cmd = 'ECHO Backing up database ' + @name + ' to ' + @fileName + ' >> ' + @outputFile
EXEC xp_cmdshell @cmd
BACKUP DATABASE @name TO DISK = @fileName
WITH copy_only, noformat, noinit, skip, norewind, nounload, compression,
STATS = 10
-- Log the backup operation result to the output file
SET @cmd = 'ECHO Backup of database ' + @name + ' completed successfully to ' + @fileName + ' >> ' + @outputFile
EXEC xp_cmdshell @cmd
FETCH NEXT FROM db_cursor INTO @name
END
-- Delete old .bak files (older than 5 days)
EXEC master.sys.Xp_delete_file 0, @path, 'BAK', @DeleteBakDate, 0
-- Delete old .txt files (older than 30 days)
EXEC master.sys.Xp_delete_file 0, @path, 'TXT', @DeleteTxtDate, 0
CLOSE db_cursor
DEALLOCATE db_cursor
-- Final log entry
DECLARE @cmdFinal VARCHAR(1024)
SET @cmdFinal = 'ECHO Backup process completed at ' + CONVERT(VARCHAR(20), GETDATE(), 120) + ' >> ' + @outputFile
EXEC xp_cmdshell @cmdFinal
Try this script
======
DECLARE @BackupPath NVARCHAR(500) = 'D:\Backups\' -- Change this to your desired path
DECLARE @BackupRetentionDays INT = 10
DECLARE @LogRetentionDays INT = 30
DECLARE @CurrentDate DATETIME = GETDATE()
DECLARE @LogPath NVARCHAR(500) = @BackupPath + 'Logs\'
DECLARE @FileName NVARCHAR(500)
DECLARE @DatabaseName NVARCHAR(128)
DECLARE @LogMessage NVARCHAR(MAX)
DECLARE @BackupDeleteDate DATETIME = DATEADD(DAY, -@BackupRetentionDays, @CurrentDate)
DECLARE @LogDeleteDate DATETIME = DATEADD(DAY, -@LogRetentionDays, @CurrentDate)
-- Create directories if they don't exist
DECLARE @CreateDirSQL NVARCHAR(1000)
SET @CreateDirSQL = 'xp_cmdshell ''if not exist "' + @BackupPath + '" mkdir "' + @BackupPath + '"'''
EXEC sp_configure 'show advanced options', 1
RECONFIGURE
EXEC sp_configure 'xp_cmdshell', 1
RECONFIGURE
EXEC(@CreateDirSQL)
EXEC('xp_cmdshell ''if not exist "' + @LogPath + '" mkdir "' + @LogPath + '"''')
-- Log file setup
DECLARE @LogFile NVARCHAR(500) = @LogPath + 'BackupLog_' +
REPLACE(REPLACE(REPLACE(CONVERT(NVARCHAR(20), @CurrentDate, 120), ':', ''), '-', ''), ' ', '_') + '.txt'
-- Initialize log
SET @LogMessage = 'Backup process started at: ' + CONVERT(NVARCHAR(30), @CurrentDate, 120) + CHAR(13) + CHAR(10)
EXEC master.dbo.xp_cmdshell 'echo %LogMessage% > "' + @LogFile + '"', no_output
-- Cursor to iterate through all user databases
DECLARE db_cursor CURSOR FOR
SELECT name
FROM sys.databases
WHERE name NOT IN ('master', 'model', 'msdb', 'tempdb')
AND state = 0 -- Online databases only
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @DatabaseName
WHILE @@FETCH_STATUS = 0
BEGIN
BEGIN TRY
-- Generate backup file name
SET @FileName = @BackupPath + @DatabaseName + '_Full_' +
REPLACE(REPLACE(REPLACE(CONVERT(NVARCHAR(20), @CurrentDate, 120), ':', ''), '-', ''), ' ', '_') + '.bak'
-- Backup command
BACKUP DATABASE @DatabaseName
TO DISK = @FileName
WITH INIT, STATS = 5, COMPRESSION
-- Log success
SET @LogMessage = 'SUCCESS: Backup completed for database: ' + @DatabaseName + ' at ' + CONVERT(NVARCHAR(30), GETDATE(), 120) + CHAR(13) + CHAR(10)
EXEC master.dbo.xp_cmdshell 'echo %LogMessage% >> "' + @LogFile + '"', no_output
END TRY
BEGIN CATCH
-- Log error
SET @LogMessage = 'ERROR: Failed to backup database: ' + @DatabaseName + ' - ' + ERROR_MESSAGE() + ' at ' + CONVERT(NVARCHAR(30), GETDATE(), 120) + CHAR(13) + CHAR(10)
EXEC master.dbo.xp_cmdshell 'echo %LogMessage% >> "' + @LogFile + '"', no_output
END CATCH
FETCH NEXT FROM db_cursor INTO @DatabaseName
END
CLOSE db_cursor
DEALLOCATE db_cursor
-- Cleanup old backup files (older than backup retention period)
BEGIN TRY
DECLARE @DeleteBackupCmd NVARCHAR(1000)
SET @DeleteBackupCmd = 'forfiles /p "' + @BackupPath + '" /s /m *.bak /d -' + CAST(@BackupRetentionDays AS NVARCHAR(3)) + ' /c "cmd /c del /q @path"'
EXEC xp_cmdshell @DeleteBackupCmd
SET @LogMessage = 'Cleanup: Old backup files deleted (older than ' + CAST(@BackupRetentionDays AS NVARCHAR(3)) + ' days)' + CHAR(13) + CHAR(10)
EXEC master.dbo.xp_cmdshell 'echo %LogMessage% >> "' + @LogFile + '"', no_output
END TRY
BEGIN CATCH
SET @LogMessage = 'ERROR during backup cleanup: ' + ERROR_MESSAGE() + CHAR(13) + CHAR(10)
EXEC master.dbo.xp_cmdshell 'echo %LogMessage% >> "' + @LogFile + '"', no_output
END CATCH
-- Cleanup old log files (older than log retention period)
BEGIN TRY
DECLARE @DeleteLogCmd NVARCHAR(1000)
SET @DeleteLogCmd = 'forfiles /p "' + @LogPath + '" /s /m *.txt /d -' + CAST(@LogRetentionDays AS NVARCHAR(3)) + ' /c "cmd /c del /q @path"'
EXEC xp_cmdshell @DeleteLogCmd
SET @LogMessage = 'Cleanup: Old log files deleted (older than ' + CAST(@LogRetentionDays AS NVARCHAR(3)) + ' days)' + CHAR(13) + CHAR(10)
EXEC master.dbo.xp_cmdshell 'echo %LogMessage% >> "' + @LogFile + '"', no_output
END TRY
BEGIN CATCH
SET @LogMessage = 'ERROR during log cleanup: ' + ERROR_MESSAGE() + CHAR(13) + CHAR(10)
EXEC master.dbo.xp_cmdshell 'echo %LogMessage% >> "' + @LogFile + '"', no_output
END CATCH
-- Final log entry
SET @LogMessage = 'Backup process completed at: ' + CONVERT(NVARCHAR(30), GETDATE(), 120) + CHAR(13) + CHAR(10)
EXEC master.dbo.xp_cmdshell 'echo %LogMessage% >> "' + @LogFile + '"', no_output
-- Reset xp_cmdshell for security
EXEC sp_configure 'xp_cmdshell', 0
RECONFIGURE
EXEC sp_configure 'show advanced options', 0
RECONFIGURE
PRINT 'Backup process completed. Check log file at: ' + @LogFile
======
This blog post will break down the provided PowerShell code, Understanding when and why your server rebooted is crucial for troubleshooting performance issues, security incidents, and overall system health. PowerShell, a powerful scripting language, provides a convenient way to extract this information from the Windows Event Log. This blog post will dissect the following PowerShell command and explain how it can be used to uncover your server’s reboot history:
Here’s a fantastic PowerShell script that can simplify our daily tasks by helping us search for events in the Windows Event Viewer. To use this script, open PowerShell ISE and run it. The output will be generated in the specified location. In this example, we’ve chosen the C:\Results folder, but feel free to customize it according to your requirements. You can also add or remove event IDs as needed. The script will create a CSV file that we can review
Code shown as follows:
Here is another good PowerShell script that can make a SQL Admin’s life easier. This script can be used to check the health of SQL servers and retrieve information about them. The collected data will be saved in both CSV and HTML formats. Additionally, an error log file is generated, allowing you to manually review any failed servers.
To implement this, follow these steps:
[code type="sql"]
SELECT @@servername[Servername],getdate() [TimeNow],command, r.session_id, r.blocking_session_id,s.text,
start_time,
percent_complete,
CAST(((DATEDIFF(s,start_time,GetDate()))/3600) as varchar) + ' hour(s), '
+ CAST((DATEDIFF(s,start_time,GetDate())%3600)/60 as varchar) + 'min, '
+ CAST((DATEDIFF(s,start_time,GetDate())%60) as varchar) + ' sec' as running_time,
CAST((estimated_completion_time/3600000) as varchar) + ' hour(s), '
+ CAST((estimated_completion_time %3600000)/60000 as varchar) + 'min, '
+ CAST((estimated_completion_time %60000)/1000 as varchar) + ' sec' as est_time_to_go,
dateadd(second,estimated_completion_time/1000, getdate()) as est_completion_time
FROM sys.dm_exec_requests r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) s
WHERE r.command in ('RESTORE DATABASE', 'BACKUP DATABASE', 'RESTORE LOG', 'BACKUP LOG','DBCC')
[/code]
use master
go
BEGIN SET nocount ON
IF EXISTS (SELECT 1 FROM tempdb..sysobjects WHERE [Id] = Object_id('tempdb..#DBFileInfo')) BEGIN DROP TABLE #dbfileinfo END
IF EXISTS (SELECT 1 FROM tempdb..sysobjects WHERE [Id] = Object_id('Tempdb..#LogSizeStats')) BEGIN DROP TABLE #logsizestats END
IF EXISTS (SELECT 1 FROM tempdb..sysobjects WHERE [Id] = Object_id('Tempdb..#DataFileStats')) BEGIN DROP TABLE #datafilestats END
IF EXISTS (SELECT 1 FROM tempdb..sysobjects WHERE [Id] = Object_id('Tempdb..#FixedDrives')) BEGIN DROP TABLE #fixeddrives END
CREATE TABLE #fixeddrives ( DriveLetter VARCHAR(10), MB_Free DEC(20, 2) )
CREATE TABLE #datafilestats ( DBName VARCHAR(255), DBId INT, FileId TINYINT, [FileGroup] TINYINT, TotalExtents DEC(20, 2), UsedExtents DEC(20, 2), [Name] VARCHAR(255), [FileName] VARCHAR(400) )
CREATE TABLE #logsizestats ( DBName VARCHAR(255) NOT NULL PRIMARY KEY CLUSTERED, DBId INT, LogFile REAL, LogFileUsed REAL, Status BIT )
CREATE TABLE #dbfileinfo ( [ServerName] VARCHAR(255), [DBName] VARCHAR(65), [LogicalFileName] VARCHAR(400), [UsageType] VARCHAR (30), [Size_MB] DEC(20, 2), [SpaceUsed_MB] DEC(20, 2), [MaxSize_MB] DEC(20, 2), [NextAllocation_MB] DEC(20, 2), [GrowthType] VARCHAR(65), [FileId] SMALLINT, [GroupId] SMALLINT, [PhysicalFileName] VARCHAR(400), [DateChecked] DATETIME )
DECLARE @SQLString VARCHAR(3000) DECLARE @MinId INT DECLARE @MaxId INT DECLARE @DBName VARCHAR(255) DECLARE @tblDBName TABLE ( RowId INT IDENTITY(1, 1), DBName VARCHAR(255), DBId INT)
INSERT INTO @tblDBName (DBName, DBId) SELECT [Name], DBId FROM master..sysdatabases WHERE ( Status & 512 ) = 0 /*NOT IN (536,528,540,2584,1536,512,4194841)*/ ORDER BY [Name]
INSERT INTO #logsizestats (DBName, LogFile, LogFileUsed, Status) EXEC ('DBCC sqlperf(logspace) WITH no_infomsgs')
UPDATE #logsizestats SET DBId = Db_id(DBName)
INSERT INTO #fixeddrives EXEC master..Xp_fixeddrives
SELECT @MinId = Min(RowId), @MaxId = Max(RowId) FROM @tblDBName
WHILE ( @MinId <= @MaxId ) BEGIN SELECT @DBName = [DBName] FROM @tblDBName WHERE RowId = @MinId
SELECT @SQLString = 'SELECT ServerName = @@SERVERNAME,' + ' DBName = ''' + @DBName + ''',' + ' LogicalFileName = [name],' + ' UsageType = CASE WHEN (64&[status])=64 THEN ''Log'' ELSE ''Data'' END,' + ' Size_MB = [size]*8/1024.00,' + ' SpaceUsed_MB = NULL,' + ' MaxSize_MB = CASE [maxsize] WHEN -1 THEN -1 WHEN 0 THEN [size]*8/1024.00 ELSE maxsize/1024.00*8 END,'+ ' NextExtent_MB = CASE WHEN (1048576&[status])=1048576 THEN ([growth]/100.00)*([size]*8/1024.00) WHEN [growth]=0 THEN 0 ELSE [growth]*8/1024.00 END,'+ ' GrowthType = CASE WHEN (1048576&[status])=1048576 THEN ''%'' ELSE ''Pages'' END,'+ ' FileId = [fileid],' + ' GroupId = [groupid],' + ' PhysicalFileName= [filename],' + ' CurTimeStamp = GETDATE()' + 'FROM [' + @DBName + ']..sysfiles'
PRINT @SQLString
INSERT INTO #dbfileinfo EXEC (@SQLString)
UPDATE #dbfileinfo SET SpaceUsed_MB = Size_MB / 100.0 * (SELECT LogFileUsed FROM #logsizestats WHERE DBName = @DBName) WHERE UsageType = 'Log' AND DBName = @DBName
SELECT @SQLString = 'USE [' + @DBName + '] DBCC SHOWFILESTATS WITH NO_INFOMSGS'
INSERT #datafilestats (FileId, [FileGroup], TotalExtents, UsedExtents, [Name], [FileName]) EXECUTE(@SQLString)
UPDATE #dbfileinfo SET [SpaceUsed_MB] = S.[UsedExtents] * 64 / 1024.00 FROM #dbfileinfo AS F INNER JOIN #datafilestats AS S ON F.[FileId] = S.[FileId] AND F.[GroupId] = S.[FileGroup] AND F.[DBName] = @DBName
TRUNCATE TABLE #datafilestats
SELECT @MinId = @MinId + 1 END
SELECT [ServerName], [DBName], [LogicalFileName], [UsageType] AS SegmentName, B.MB_Free AS FreeSpaceInDrive, [Size_MB], [SpaceUsed_MB], [Size_MB] - [SpaceUsed_MB] AS FreeSpace_MB, Cast(( [Size_MB] - [SpaceUsed_MB] ) / [Size_MB] AS DECIMAL(4, 2)) AS FreeSpace_Pct, [MaxSize_MB], [NextAllocation_MB], ( [Size_MB] - [SpaceUsed_MB] ) - ( [NextAllocation_MB] ) AS alert_switch, ( B.MB_Free ) + ( ( [Size_MB] - [SpaceUsed_MB] ) - ( [NextAllocation_MB] ) ) AS will_be_on_drive, CASE MaxSize_MB WHEN -1 THEN Cast(Cast(( [NextAllocation_MB] / [Size_MB] ) * 100 AS INT ) AS VARCHAR(10)) + ' %' ELSE 'Pages' END AS [GrowthType], [FileId], [GroupId], [PhysicalFileName], CONVERT(SYSNAME, Databasepropertyex([DBName], 'Status')) AS Status, CONVERT(SYSNAME, Databasepropertyex([DBName], 'Updateability')) AS Updateability, CONVERT(SYSNAME, Databasepropertyex([DBName], 'Recovery')) AS RecoveryMode, CONVERT(SYSNAME, Databasepropertyex([DBName], 'UserAccess')) AS UserAccess, CONVERT(SYSNAME, Databasepropertyex([DBName], 'Version')) AS Version, [DateChecked] FROM #dbfileinfo AS A LEFT JOIN #fixeddrives AS B ON Substring(A.PhysicalFileName, 1, 1) = B.DriveLetter ORDER BY ( [Size_MB] - [SpaceUsed_MB] ) - ( [NextAllocation_MB] )
IF EXISTS (SELECT 1 FROM tempdb..sysobjects WHERE [Id] = Object_id('Tempdb..#DBFileInfo')) BEGIN DROP TABLE #dbfileinfo END
IF EXISTS (SELECT 1 FROM tempdb..sysobjects WHERE [Id] = Object_id('Tempdb..#LogSizeStats')) BEGIN DROP TABLE #logsizestats END
IF EXISTS (SELECT 1 FROM tempdb..sysobjects WHERE [Id] = Object_id('Tempdb..#DataFileStats')) BEGIN DROP TABLE #datafilestats END
IF EXISTS (SELECT 1 FROM tempdb..sysobjects WHERE [Id] = Object_id('Tempdb..#FixedDrives')) BEGIN DROP TABLE #fixeddrives END
SET nocount OFF END
Hello this is the code test
SELECT @@servername[Servername],getdate() [TimeNow],command, r.session_id, r.blocking_session_id,s.text,
start_time,
percent_complete,
CAST(((DATEDIFF(s,start_time,GetDate()))/3600) as varchar) + ' hour(s), '
+ CAST((DATEDIFF(s,start_time,GetDate())%3600)/60 as varchar) + 'min, '
+ CAST((DATEDIFF(s,start_time,GetDate())%60) as varchar) + ' sec' as running_time,
CAST((estimated_completion_time/3600000) as varchar) + ' hour(s), '
+ CAST((estimated_completion_time %3600000)/60000 as varchar) + 'min, '
+ CAST((estimated_completion_time %60000)/1000 as varchar) + ' sec' as est_time_to_go,
dateadd(second,estimated_completion_time/1000, getdate()) as est_completion_time
FROM sys.dm_exec_requests r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) s
WHERE r.command in ('RESTORE DATABASE', 'BACKUP DATABASE', 'RESTORE LOG', 'BACKUP LOG','DBCC')
SELECT @@servername[Servername],getdate() [TimeNow],command, r.session_id, r.blocking_session_id,s.text,
start_time,
percent_complete,
CAST(((DATEDIFF(s,start_time,GetDate()))/3600) as varchar) + ' hour(s), '
+ CAST((DATEDIFF(s,start_time,GetDate())%3600)/60 as varchar) + 'min, '
+ CAST((DATEDIFF(s,start_time,GetDate())%60) as varchar) + ' sec' as running_time,
CAST((estimated_completion_time/3600000) as varchar) + ' hour(s), '
+ CAST((estimated_completion_time %3600000)/60000 as varchar) + 'min, '
+ CAST((estimated_completion_time %60000)/1000 as varchar) + ' sec' as est_time_to_go,
dateadd(second,estimated_completion_time/1000, getdate()) as est_completion_time
FROM sys.dm_exec_requests r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) s
WHERE r.command in ('RESTORE DATABASE', 'BACKUP DATABASE', 'RESTORE LOG', 'BACKUP LOG','DBCC')