使用凭据打破脚本块
Using Credential breaks the script block
概述:这是一个 PowerShell 脚本,用于自动执行 SQL 数据库备份,必须尽可能并行完成。
这很好用。
$ServerInstanceSource = ".\INSTANCE01"
$ServerInstanceDestination = ".\INSTANCE02"
$UserName = 'user'
$PassWord = 'pass'
$GetDBs = Invoke-Sqlcmd -ServerInstance $ServerInstanceSource -Username $UserName -Password $Password -Database tempdb -Query "SELECT name FROM sys.databases WHERE database_id > 4 AND recovery_model_desc != 'SIMPLE'"
$Date = (Get-Date -Format 'yyyyMMddhhmmss')
$BackupSourceDirectory = 'F:\DB-BACKUP\SQLBACKUP\Manual Logshipping Restoration\'
$BackupDestinationDirectory = 'D:\BACKUPS\'
Get-Job | Remove-Job -Force
Write-Output "Creating FULL backup. . ."
ForEach($db in $GetDBs.name){
$FileName = "FULL-$db-$Date.bak"
$FullBackupPath = Join-Path -Path $BackupSourceDirectory -ChildPath $FileName
$BackupFullScript = "BACKUP DATABASE $db TO DISK = N'$FullBackupPath' WITH NOFORMAT, NOINIT, NAME = N'$db-FULL Database Backup', SKIP, NOREWIND, NOUNLOAD, COMPRESSION, STATS = 10"
$SQLBackupFull = "Invoke-Sqlcmd -ServerInstance $ServerInstanceSource -Username $UserName -Password $Password -Database tempdb -Query `"$BackupFullScript`" -QueryTimeout 21600;" # 5 hours
[scriptblock]$cmdblock1 = [ScriptBlock]::Create($SQLBackupFull)
Start-Job $cmdblock1
}
Get-Job | Wait-Job
Get-Job | Receive-Job
但是,当我将代码转换为接受凭据而不是硬编码凭据时,出现错误:
$ServerInstanceSource = ".\INSTANCE01"
$ServerInstanceDestination = ".\INSTANCE02"
$Cred = Get-Credential
$GetDBs = Invoke-Sqlcmd -ServerInstance $ServerInstanceSource -Credential $Cred -Database tempdb -Query "SELECT name FROM sys.databases WHERE database_id > 4 AND recovery_model_desc != 'SIMPLE' -- Dynamic; Input specific databases only, if necessary."
$Date = (Get-Date -Format 'yyyyMMddhhmmss')
$BackupSourceDirectory = 'C:\Users\edgar.bayron\Music\Edgar\Trash Can\DB-BACKUP\SQLBACKUP\LAX-DBMON\' # "F:\DB-BACKUP\SQLBACKUP\Manual Logshipping Restoration\"
$BackupDestinationDirectory = 'C:\Users\edgar.bayron\Music\Edgar\Trash Can\DB-BACKUP\SQLBACKUP\DAL-INDBS01\' # "D:\BACKUPS\"
Get-Job | Remove-Job -Force
Write-Output "Creating FULL backup. . ."
ForEach($db in $GetDBs.name){
$FileName = "FULL-$db-$Date.bak"
$FullBackupPath = Join-Path -Path $BackupSourceDirectory -ChildPath $FileName
$BackupFullScript = "BACKUP DATABASE $db TO DISK = N'$FullBackupPath' WITH NOFORMAT, NOINIT, NAME = N'$db-FULL Database Backup', SKIP, NOREWIND, NOUNLOAD, COMPRESSION, STATS = 10"
$SQLBackupFull = "Invoke-Sqlcmd -ServerInstance $ServerInstanceSource -Credential $Cred -Database tempdb -Query `"$BackupFullScript`" -QueryTimeout 21600;" # 5 hours
[scriptblock]$cmdblock1 = [ScriptBlock]::Create($SQLBackupFull)
Start-Job $cmdblock1
}
Get-Job | Wait-Job
Get-Job | Receive-Job
错误:
Wait-Job : The Wait-Job cmdlet cannot finish working, because one or more jobs are blocked waiting for user interaction. Process interactive job
output by using the Receive-Job cmdlet, and then try again.
我正在尝试应用推荐的 here,但我无法完全应用它,因为在示例中,它只有一个参数,而我有多个。如果我尝试应用它,它会搜索其他变量。
我尝试使用 {PARAM($ServerInstanceSource, $cred, $BackupFullScript)
但它破坏了 $BackupFullScript
中的 SQL 查询。
谁能帮我解决这个问题?
您正在尝试将凭据对象用作字符串。发生的事情是 $Cred
使用它的 .ToString()
方法转换为字符串,它看起来像这样 System.Management.Automation.PSCredential
当作为参数传递给 -Credential
参数时显然不起作用你的脚本块。
您可以 return 使用用户名和密码的原始实现,您可以在其中传递从 $Cred
对象
中获取的用户名和密码
$SQLBackupFull = "Invoke-Sqlcmd -ServerInstance $ServerInstanceSource -Username $($Cred.UserName) -Password $($Cred.GetNetworkCredential().Password) -Database tempdb -Query `"$BackupFullScript`" -QueryTimeout 21600;" # 5 hours
或者您可以创建一个带有 param()
块的脚本块,您可以在其中将 $Cred
对象作为参数传入
编辑 - $cmd 脚本块移出到 foreach 之前,因此它只创建一次。
$cmd = {
param(
$ServerInstanceSource,
$Cred,
$BackupFullScript
)
Invoke-Sqlcmd -ServerInstance $ServerInstanceSource -Credential $Cred -Database tempdb -Query $BackupFullScript -QueryTimeout 21600;
}
ForEach ($db in $GetDBs.name) {
$FileName = "FULL-$db-$Date.bak"
$FullBackupPath = Join-Path -Path $BackupSourceDirectory -ChildPath $FileName
$BackupFullScript = "BACKUP DATABASE $db TO DISK = N'$FullBackupPath' WITH NOFORMAT, NOINIT, NAME = N'$db-FULL Database Backup', SKIP, NOREWIND, NOUNLOAD, COMPRESSION, STATS = 10"
Start-Job $cmd -ArgumentList $ServerInstanceSource, $Cred, $BackupFullScript
}
概述:这是一个 PowerShell 脚本,用于自动执行 SQL 数据库备份,必须尽可能并行完成。
这很好用。
$ServerInstanceSource = ".\INSTANCE01"
$ServerInstanceDestination = ".\INSTANCE02"
$UserName = 'user'
$PassWord = 'pass'
$GetDBs = Invoke-Sqlcmd -ServerInstance $ServerInstanceSource -Username $UserName -Password $Password -Database tempdb -Query "SELECT name FROM sys.databases WHERE database_id > 4 AND recovery_model_desc != 'SIMPLE'"
$Date = (Get-Date -Format 'yyyyMMddhhmmss')
$BackupSourceDirectory = 'F:\DB-BACKUP\SQLBACKUP\Manual Logshipping Restoration\'
$BackupDestinationDirectory = 'D:\BACKUPS\'
Get-Job | Remove-Job -Force
Write-Output "Creating FULL backup. . ."
ForEach($db in $GetDBs.name){
$FileName = "FULL-$db-$Date.bak"
$FullBackupPath = Join-Path -Path $BackupSourceDirectory -ChildPath $FileName
$BackupFullScript = "BACKUP DATABASE $db TO DISK = N'$FullBackupPath' WITH NOFORMAT, NOINIT, NAME = N'$db-FULL Database Backup', SKIP, NOREWIND, NOUNLOAD, COMPRESSION, STATS = 10"
$SQLBackupFull = "Invoke-Sqlcmd -ServerInstance $ServerInstanceSource -Username $UserName -Password $Password -Database tempdb -Query `"$BackupFullScript`" -QueryTimeout 21600;" # 5 hours
[scriptblock]$cmdblock1 = [ScriptBlock]::Create($SQLBackupFull)
Start-Job $cmdblock1
}
Get-Job | Wait-Job
Get-Job | Receive-Job
但是,当我将代码转换为接受凭据而不是硬编码凭据时,出现错误:
$ServerInstanceSource = ".\INSTANCE01"
$ServerInstanceDestination = ".\INSTANCE02"
$Cred = Get-Credential
$GetDBs = Invoke-Sqlcmd -ServerInstance $ServerInstanceSource -Credential $Cred -Database tempdb -Query "SELECT name FROM sys.databases WHERE database_id > 4 AND recovery_model_desc != 'SIMPLE' -- Dynamic; Input specific databases only, if necessary."
$Date = (Get-Date -Format 'yyyyMMddhhmmss')
$BackupSourceDirectory = 'C:\Users\edgar.bayron\Music\Edgar\Trash Can\DB-BACKUP\SQLBACKUP\LAX-DBMON\' # "F:\DB-BACKUP\SQLBACKUP\Manual Logshipping Restoration\"
$BackupDestinationDirectory = 'C:\Users\edgar.bayron\Music\Edgar\Trash Can\DB-BACKUP\SQLBACKUP\DAL-INDBS01\' # "D:\BACKUPS\"
Get-Job | Remove-Job -Force
Write-Output "Creating FULL backup. . ."
ForEach($db in $GetDBs.name){
$FileName = "FULL-$db-$Date.bak"
$FullBackupPath = Join-Path -Path $BackupSourceDirectory -ChildPath $FileName
$BackupFullScript = "BACKUP DATABASE $db TO DISK = N'$FullBackupPath' WITH NOFORMAT, NOINIT, NAME = N'$db-FULL Database Backup', SKIP, NOREWIND, NOUNLOAD, COMPRESSION, STATS = 10"
$SQLBackupFull = "Invoke-Sqlcmd -ServerInstance $ServerInstanceSource -Credential $Cred -Database tempdb -Query `"$BackupFullScript`" -QueryTimeout 21600;" # 5 hours
[scriptblock]$cmdblock1 = [ScriptBlock]::Create($SQLBackupFull)
Start-Job $cmdblock1
}
Get-Job | Wait-Job
Get-Job | Receive-Job
错误:
Wait-Job : The Wait-Job cmdlet cannot finish working, because one or more jobs are blocked waiting for user interaction. Process interactive job
output by using the Receive-Job cmdlet, and then try again.
我正在尝试应用推荐的 here,但我无法完全应用它,因为在示例中,它只有一个参数,而我有多个。如果我尝试应用它,它会搜索其他变量。
我尝试使用 {PARAM($ServerInstanceSource, $cred, $BackupFullScript)
但它破坏了 $BackupFullScript
中的 SQL 查询。
谁能帮我解决这个问题?
您正在尝试将凭据对象用作字符串。发生的事情是 $Cred
使用它的 .ToString()
方法转换为字符串,它看起来像这样 System.Management.Automation.PSCredential
当作为参数传递给 -Credential
参数时显然不起作用你的脚本块。
您可以 return 使用用户名和密码的原始实现,您可以在其中传递从 $Cred
对象
$SQLBackupFull = "Invoke-Sqlcmd -ServerInstance $ServerInstanceSource -Username $($Cred.UserName) -Password $($Cred.GetNetworkCredential().Password) -Database tempdb -Query `"$BackupFullScript`" -QueryTimeout 21600;" # 5 hours
或者您可以创建一个带有 param()
块的脚本块,您可以在其中将 $Cred
对象作为参数传入
编辑 - $cmd 脚本块移出到 foreach 之前,因此它只创建一次。
$cmd = {
param(
$ServerInstanceSource,
$Cred,
$BackupFullScript
)
Invoke-Sqlcmd -ServerInstance $ServerInstanceSource -Credential $Cred -Database tempdb -Query $BackupFullScript -QueryTimeout 21600;
}
ForEach ($db in $GetDBs.name) {
$FileName = "FULL-$db-$Date.bak"
$FullBackupPath = Join-Path -Path $BackupSourceDirectory -ChildPath $FileName
$BackupFullScript = "BACKUP DATABASE $db TO DISK = N'$FullBackupPath' WITH NOFORMAT, NOINIT, NAME = N'$db-FULL Database Backup', SKIP, NOREWIND, NOUNLOAD, COMPRESSION, STATS = 10"
Start-Job $cmd -ArgumentList $ServerInstanceSource, $Cred, $BackupFullScript
}