2

Powershellスクリプトを使用して現在のSQLTXログバックアップファイルに「-PrevDay」を追加して名前を変更するジョブを実行するSQL2005インスタンスがあります(その後、「XXX-PrevDay.bak」という名前のバックアップが存在する場合は削除します) )、DBがシンプルモードでない場合は、DBの完全バックアップとTXログバックアップを実行します。

SQL Serverエージェントジョブは、各ジョブステップでCMDを介してPowershellスクリプトを開始し、PowerShellスクリプトは「Invoke-SQLCmd」コマンドレットを使用してSQLバックアップを開始します。SQLジョブは引き続き「成功」と表示されるため、バックアップが失敗しない限り、これはうまく機能します。これは、CMDプロンプトを介してPowershellスクリプトを開始するSQLジョブが、Powershellスクリプトが実行されたかどうかのみを考慮し、スクリプト内のコマンドが実際に成功したか失敗したかを考慮しないためです。

PowerShell(または実際には任意の方法)でエラートラップを使用して、PowerShellスクリプトでスクリプトを実行するcmdプロンプトアクションを「失敗」させて、SQLジョブが失敗を報告することは可能ですか?

これも意味がありますか?笑

SQLジョブのステップタイプが「Powershellスクリプト」であるSQL2008を使用できた場合(ステップタイプがオペレーティングシステムである必要はありません... PSスクリプトを開始します)、これはできません。問題になることはありません...しかし...それはオプションではありません。

現在、ジョブステップは、DBName、Path、およびServernameのパラメーターを使用してCMDを介してPowerShellスクリプトを実行し、次のようになります。

powershell.exe "C:\SQLBackupScriptsTest\SQLServerBackup.ps1" -DBName 'Angel_Food' -Path 'E:\SQLBackup1' -Server 'DEVSQLSRV'

実際のPowershellスクリプトは次のようになります。

Param($DBName,$Path,$Server)

## Add sql snapins...must have for Invoke-Sqlcmd with powershell 2.0 ##

add-pssnapin sqlserverprovidersnapin100
add-pssnapin sqlservercmdletsnapin100
[reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") | out-null

## Set parameter for finding DB recovery model ##
$Recovery = (Invoke-Sqlcmd -Query "SELECT recovery_model_desc FROM sys.databases WHERE name = '$DBName'" -Server $Server)

## Do full backup of DB ##
(Invoke-Sqlcmd -Query "BACKUP DATABASE $DBName TO  DISK = N'$Path\$DBName\$DBName.bak' WITH NOFORMAT, INIT,  NAME = N'$DBNameTEST', SKIP, NOREWIND, NOUNLOAD,  STATS = 10, CHECKSUM" -Server $Server -ConnectionTimeout 0 -QueryTimeout 65535)

############################################################################################################
## Check recovery mode, if FULL, check for Log-PrevDay.bak. If exists then delete.  If not exist, move on ##
## Then check for Current TX log backup.  If exists, rename to Log-PreDay.bak. If not exist, move on      ##
## Then perform TX Log backup                                                                             ##
## If recovery mode NOT FULL, do nothing                                                                  ##
############################################################################################################
    IF
    ($Recovery.recovery_model_desc -eq 'FULL')
    #THEN#
    {
            ## Look to see if PrevDay TX log exists.  If so, delete, if not, move on ##
            IF 
            (Test-Path $Path\$DBName\$DBName-Log-PrevDay.bak) 
            #THEN#
            {remove-item $Path\$DBName\$DBName-Log-PrevDay.bak -force}
            ELSE
            {}
                ## Look to see if current TX log exists, if so, rename to Prev Day TX Log, if not, move on ##
                IF
                (Test-Path $Path\$DBName\$DBName-Log.bak)
                #THEN#
                {rename-item $Path\$DBName\$DBName-Log.bak -newname $DBName-Log-PrevDay.bak -force}
                ELSE
                {}

    Invoke-Sqlcmd -Query "BACKUP LOG $DBName TO  DISK = N'$Path\$DBName\$DBName-Log.bak' WITH NOFORMAT, INIT,  NAME = N'$DBName LogTEST (Init)', SKIP, NOREWIND, NOUNLOAD,  STATS = 10, CHECKSUM" -Server $Server -ConnectionTimeout 0 -QueryTimeout 65535}
    ELSE
    {}
4

1 に答える 1

1

さて、いくつかのブログと少しの試行錯誤/運を見た後...私はそれが私が望むことをするようになりました。

Powershellの終了コードをCMDEXECに返送する必要があると判断しました。ただし、私が見つけたところによると、Powershellは常にデフォルトの終了コード0(成功)です...2つのPSスクリプトを使用していくつかのフープをジャンプしない限り...これは本当にやりたくありませんでした。そこで、エラーをトラップすることにしました。エラーがトラップされた場合は、何があっても、コード1でPSスクリプトを終了します。正直なところ...私が本当に欲しかったのは、0(成功)または1(失敗)の信頼できる終了コードだけでした。だから...長い話を短く...これが私のコードを変更した方法です。

各ステップのCMDEXECを次のように変更しました。

powershell.exe -noprofile C:\SQLBackupScriptsTest\SQLServerBackup2.ps1 -DBName 'Angel_Food' -Path 'E:\SQLBackup' -Server 'DEVSQLSRV'
@Echo %errorlevel%

次に、PSスクリプトを次のように変更しました。

Param($DBName,$Path,$Server)

## Add sql snapins...must have for Invoke-Sqlcmd with powershell 2.0 ##

add-pssnapin sqlserverprovidersnapin100
add-pssnapin sqlservercmdletsnapin100
[reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") | out-null

## Set parameter for finding DB recovery model ##
$Recovery = (Invoke-Sqlcmd -Query "SELECT recovery_model_desc FROM sys.databases WHERE name = '$DBName'" -Server $Server)

## Do full backup of DB ##
trap {$_.Exception.Message; exit 1; continue}Invoke-Sqlcmd -Query "BACKUP DATABASE $DBName TO  DISK = N'$Path\$DBName\$DBName.bak' WITH NOFORMAT, INIT,  NAME = N'$DBNameTEST', SKIP, NOREWIND, NOUNLOAD,  STATS = 10, CHECKSUM" -Server $Server -ConnectionTimeout 0 -QueryTimeout 65535 -ea stop

############################################################################################################
## Check recovery mode, if FULL, check for Log-PrevDay.bak. If exists then delete.  If not exist, move on ##
## Then check for Current TX log backup.  If exists, rename to Log-PreDay.bak. If not exist, move on      ##
## Then perform TX Log backup                                                                             ##
## If recovery mode NOT FULL, do nothing                                                                  ##
############################################################################################################
    IF
    ($Recovery.recovery_model_desc -eq 'FULL')
    #THEN#
    {
            ## Look to see if PrevDay TX log exists.  If so, delete, if not, move on ##
            IF 
            (Test-Path $Path\$DBName\$DBName-Log-PrevDay.bak) 
            #THEN#
            {remove-item $Path\$DBName\$DBName-Log-PrevDay.bak -force}
            ELSE
            {}
                ## Look to see if current TX log exists, if so, rename to Prev Day TX Log, if not, move on ##
                IF
                (Test-Path $Path\$DBName\$DBName-Log.bak)
                #THEN#
                {rename-item $Path\$DBName\$DBName-Log.bak -newname $DBName-Log-PrevDay.bak -force}
                ELSE
                {}

            trap {$_.Exception.Message; exit 1; continue}Invoke-Sqlcmd -Query "BACKUP LOG $DBName TO  DISK = N'$Path\$DBName\$DBName-Log.bak' WITH NOFORMAT, INIT,  NAME = N'$DBName LogTEST (Init)', SKIP, NOREWIND, NOUNLOAD,  STATS = 10, CHECKSUM" -Server $Server -ConnectionTimeout 0 -QueryTimeout 65535 -ea stop}
    ELSE
    {}

基本的に、各ステートメントtrap {$_.Exception.Message; exit 1; continue}の直前に追加し、各ステートメントを。Invoke-Sqlcmdで終了しました。Invoke-Sqlcmd-ea stop

trap $_.Exception.Messageエラーをトラップします...エラーメッセージを収集し、すぐexit 1にPSスクリプトを終了コード.で終了します1

SQLジョブは、0または1のいずれかで各ステップを読み取り、0を成功として、1を失敗として自動的に解釈し、SQLジョブを成功または失敗として正しくマークします。さらに、実際のエラーメッセージをキャプチャしたので、SQLジョブ履歴に表示されます。

これはまさに私が必要としているものでした。:)

興味があれば...これが私を最も助けてくれたブログです:

于 2010-09-30T21:49:02.940 に答える