Quantcast
Channel: Windows PowerShell forum
Viewing all articles
Browse latest Browse all 21975

Writing a powershell script that will get the archive bit status of SQL backup files

$
0
0

Hi All,

I started looking at a project to check the archive bit of SQL backup files. The scope of the project is as follows.

  1. Connect to a SQL instance from an inventory DB
  2. Get a list of the backup drives by querying msdb and working out the directories used for backups in the last 7 days.
  3. Connect to the SQL instance via the network path
  4. Check the backup directory returned in step 2
  5. Get the list of all the .bak files etc in the directory and check the archive bit status in the last 36 hours.
  6. Once the archive bit status has been retrieved from step 5, store the details on a table
  7. Generate a CSV file with the results from step 6

I have had to overcome a lot of challanges to get the script to this level, but I know it should be better. One of my limitations is the fact that I am only using powershell V2 and thats what deployed to PC's at this shop. I would like recomendations on improvements on the following areas.

I believe the script can be improved, but I am looking for constructive feedback. I only recently started coding powershell.

  1. The script converts local folders onto UNc network paths, can this be re-written or improved to use local paths ?
  2. My SQL connectivity scripts, I believe they can be better.
  3. Output to a CSV file, at the moment I am struggling to export the contents of the array onto a CSV file.
  4. Other tips.

Thanks in advance.

See the code below.

# Chcek server list for the archive bit.
# This is a wrapper script for checking the list of servers. Script will get server list from a SQL instance.



#Function for connecting to a SQL server instance.
function Invoke-Sqlcmd3
{
    param
    (
        [string]$ServerInstance,#="localhost",
        [string]$Database,
        [string]$Query,
        [Int32]$CommandTimeout=30
    )
    $connectionString = "Server={0};Database={1};Integrated Security=True" -f $ServerInstance, $Database
    $connection = New-Object System.Data.SqlClient.SQLConnection($connectionString)
    try
    {
        $connection.Open()
        $command = $connection.CreateCommand()
        $command.CommandTimeout = $QueryTimeout
        $command.CommandType = [System.Data.CommandType]::Text
        $command.CommandText = $Query
        $dataSet = New-Object System.Data.DataSet
        $dataAdapter = New-Object System.Data.SqlClient.SqlDataAdapter($command)
        [void]$dataAdapter.Fill($dataSet)
        $dataSet.Tables[0]
    }
    finally
    {
        if ($connection.State -eq [System.Data.ConnectionState]::Open)
        {
            $connection.Close()
        }
    }
}




Function Get-ArchiveStatus
{

    param
    (
    [string] $path ,
    [string] $NetworkPath,
    [string] $Server,
    [string] $DBServer,
    [string] $Database,
    [int]    $HoursThreshold
    )


    $files = Get-ChildItem -Path $NetworkPath -include *.diff,*.trn,*.bak,*.sysbak -Recurse
    $attribute = [io.fileattributes]::archive


    #Construct filename
    $Outfilename = "J:\Log\BackupCheck_"+ (Get-Date -format ddMMyyyy) + ".csv"
    #Set up database connection Params.
    $con = "server=$DBServer;database=$Database;Integrated Security=sspi"


    $ResultsArray = @()
    $ThresholdDate = (get-date).AddHours(-$HoursThreshold)

    # Check for the Archive Bit for the servers.
        Foreach($file in $files)

        {

            IF ($file.CreationTime -lt $ThresholdDate)
            {

                 If((Get-ItemProperty -Path $file.fullname).attributes -band $attribute )

                  { 
                    write-host "I got her"              
                    $FileDate = $file.CreationTime "$file.fullname does not appear to have been backed up" 
                    $sql = " INSERT INTO dbo.tblCheckArchiveBit ([ServerName],[Directory],[DirectoryFile] ,[FileCreationDate],[Archived])  SELECT  '$Server', '$path',  '$file', '$FileDate','N' "
                    Invoke-Sqlcmd3 -serverinstance $DBServer -database $Database -query $sql
                    $ResultsArray += New-Object PSObject -Property @{ServerName=$Server;FilePath=$path;FileName=$file;FileCreationDate=$FileDate; ThresholdDate=$ThresholdDate}
                    ResultsArray | Export-csv $Outfilename  -NoTypeInformation
                    $MyServerName | out-file J:\Log\Serversxx.txt -append
                    }

                 ELSE

                  { 
                  
                    "$file.fullname does appear to have $attribute bit set and backed up."
                    }
       }  



    } #end loop
     
    
    

} #end of function
 


$Server = "SERVERNAME"
$Database = "InventoryDB"


$con = "server=$Server;database=$Database;Integrated Security=sspi"
$cmd = "SELECT TOP 1 [ServerName]  FROM Inventory WHERE  Env = 'PROD'  "
$da = new-object System.Data.SqlClient.SqlDataAdapter ($cmd, $con)
$dt = new-object System.Data.DataTable
$da.fill($dt) | out-null # get a list of all the server names and put them in a table
    foreach ($srv in $dt) # check every server in the table
        {

        #Ping the server here
        $MyServerName = $srv.ServerName     
        $Reply = Test-Connection -ComputerName $MyServerName -Count 1 -Quiet # ping server to see if it's alive
           if ($Reply –eq “True”)  
                {
                 $MyServerName | out-file J:\Log\Servers.txt -append
                
                #Get the backup directory and the server name again from SQL
                
                $sqlcommand = "SELECT distinct @@SERVERNAME SQLServer
		          ,   SUBSTRING(BMF.physical_device_name,1,LEN(BMF.physical_device_name)-CHARINDEX('\',REVERSE(BMF.physical_device_name))) AS BackupDirectory
                FROM 
                msdb.dbo.backupset B
                JOIN msdb.dbo.backupmediafamily BMF ON B.media_set_id = BMF.media_set_id
                WHERE B.backup_finish_date <= GETDATE() - 7
                AND SUBSTRING(BMF.physical_device_name,1,LEN(BMF.physical_device_name)-CHARINDEX('\',REVERSE(BMF.physical_device_name))) NOT LIKE 'VNBU%'"
                #Run command to get the backup directory                
                $con = "server=$MyServerName;database='msdb';Integrated Security=sspi"
                $da = new-object System.Data.SqlClient.SqlDataAdapter ($sqlcommand, $con)
                $instances = new-object System.Data.DataTable
                $da.fill($instances) | out-null # get a list of all the server names and put them in a table
                    foreach ($servers in $instances) # check every server in the table
                    {
                            $ServerToCheck = $servers.SQLServer               
                            $NativeBackup =  $servers.BackupDirectory             
                            $BackupDirectory = $servers.BackupDirectory        
                            $BackupDirectory  = "\\" + $servers.SQLServer +"\"+ $BackupDirectory.Replace(":","$")   
                            $firstcharacter = $BackupDirectory.trim().Substring(0,1)
                             write-host $BackupDirectory 
                             write-host $servers.SQLServer"The server is " + $ServerToCheck + " and the directory is " + $BackupDirectory + " first character is " + $firstcharacter   | Out-File J:\Log\Log.txt -append

                                if ((Test-Path $BackupDirectory -PathType Container) -eq $true)
                                {
                                    Get-ArchiveStatus -path $NativeBackup -NetworkPath $BackupDirectory -Server $servers.SQLServer  -DBServer "SERVERNAME" -Database  "DBCentral" -HoursThreshold  36
                                    $ResultsArray | out-file J:\Log\FinalOutput.txt 
                                }
                        }        

                
                
                }
                

    
        }
    







Viewing all articles
Browse latest Browse all 21975

Trending Articles