【问题标题】:SQL Server backup script (PowerShell) works on 2016 server but not 2012SQL Server 备份脚本 (PowerShell) 适用于 2016 服务器,但不适用于 2012
【发布时间】:2017-06-17 14:27:50
【问题描述】:

我有以下脚本:

$serverName = "."
$backupDirectory = "\\backup\server1"
$daysToStoreDailyBackups = 7
$daysToStoreWeeklyBackups = 28
$monthsToStoreMonthlyBackups = 3

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoExtended") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.ConnectionInfo") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoEnum") | Out-Null

$mySrvConn = new-object Microsoft.SqlServer.Management.Common.ServerConnection
$mySrvConn.ServerInstance=$serverName
$mySrvConn.LoginSecure = $false
$mySrvConn.Login = "sa"
$mySrvConn.Password = "myPass"

$server = new-object Microsoft.SqlServer.Management.SMO.Server($mySrvConn)

$dbs = $server.Databases
$startDate = (Get-Date)
"$startDate"

Get-ChildItem "$backupDirectory\*_daily.bak" |? { $_.lastwritetime -le (Get-Date).AddDays(-$daysToStoreDailyBackups)} |% {Remove-Item $_ -force }
"removed all previous daily backups older than $daysToStoreDailyBackups days"

foreach ($database in $dbs | where {$_.IsSystemObject -eq $False})
{
    $dbName = $database.Name      

    if ($dbName -ne "ReportServer" -and $dbName -ne "ReportServerTempDB")
    {
        $timestamp = Get-Date -format yyyy-MM-dd-HHmmss
        $targetPath = $backupDirectory + "\" + $dbName + "_" + $timestamp + "_daily.bak"

        $smoBackup = New-Object ("Microsoft.SqlServer.Management.Smo.Backup")
        $smoBackup.Action = "Database"
        $smoBackup.BackupSetDescription = "Full Backup of " + $dbName
        $smoBackup.BackupSetName = $dbName + " Backup"
        $smoBackup.Database = $dbName
        $smoBackup.MediaDescription = "Disk"
        $smoBackup.Devices.AddDevice($targetPath, "File")
        $smoBackup.SqlBackup($server) 
        "backed up $dbName ($serverName) to $targetPath"    
    }
    else
    {
        "$dbName backup skipped"
    }
}

if([Int] (Get-Date).DayOfWeek -eq 0)
{
    Get-ChildItem "$backupDirectory\*_weekly.bak" |? { $_.lastwritetime -le (Get-Date).AddDays(-$daysToStoreWeeklyBackups)} |% {Remove-Item $_ -force }
    "removed all previous daily backups older than $daysToStoreWeeklyBackups days"

    foreach ($database in $dbs | where { $_.IsSystemObject -eq $False})
    {
        $dbName = $database.Name  

        if ($dbName -ne "ReportServer" -and $dbName -ne "ReportServerTempDB")
        {    
            $timestamp = Get-Date -format yyyy-MM-dd-HHmmss
            $targetPath = $backupDirectory + "\" + $dbName + "_" + $timestamp + "_weekly.bak"

            $smoBackup = New-Object ("Microsoft.SqlServer.Management.Smo.Backup")
            $smoBackup.Action = "Database"
            $smoBackup.BackupSetDescription = "Full Backup of " + $dbName
            $smoBackup.BackupSetName = $dbName + " Backup"
            $smoBackup.Database = $dbName
            $smoBackup.MediaDescription = "Disk"
            $smoBackup.Devices.AddDevice($targetPath, "File")
            $smoBackup.SqlBackup($server) 
            "backed up $dbName ($serverName) to $targetPath"
        } 
        else
        {
            "$dbName backup skipped"
        }                   
    }
}

if([Int] (Get-Date).Day -eq 1)
{
    Get-ChildItem "$backupDirectory\*_monthly.bak" |? { $_.lastwritetime -le (Get-Date).AddMonths(-$monthsToStoreMonthlyBackups)} |% {Remove-Item $_ -force }
    "removed all previous monthly backups older than $monthsToStoreMonthlyBackups days"

    foreach ($database in $dbs | where { $_.IsSystemObject -eq $False})
    {
        $dbName = $database.Name  

        if ($dbName -ne "ReportServer" -and $dbName -ne "ReportServerTempDB")
        {
            $timestamp = Get-Date -format yyyy-MM-dd-HHmmss
            $targetPath = $backupDirectory + "\" + $dbName + "_" + $timestamp + "_monthly.bak"

            $smoBackup = New-Object ("Microsoft.SqlServer.Management.Smo.Backup")
            $smoBackup.Action = "Database"
            $smoBackup.BackupSetDescription = "Full Backup of " + $dbName
            $smoBackup.BackupSetName = $dbName + " Backup"
            $smoBackup.Database = $dbName
            $smoBackup.MediaDescription = "Disk"
            $smoBackup.Devices.AddDevice($targetPath, "File")
            $smoBackup.SqlBackup($server) 
            "backed up $dbName ($serverName) to $targetPath" 
        } 
        else
        {
            "$dbName backup skipped"
        }               
    }
}

这在我的一台服务器(运行服务器 2016)上完美运行,另一台服务器(运行服务器 2012)却没有,它给了我以下错误:

Exception calling "SqlBackup" with "1" argument(s): "Backup failed for Server 'Server1'. "
At C:\Users\Administrator\Documents\Scripts\sqlFullBackup.ps1:43 char:9
+         $smoBackup.SqlBackup($server)
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : FailedOperationException

任何想法如何解决这个问题?

提前致谢

--- 编辑 ------------------

运行时

$error[0] | fl -force

我得到以下信息:

System.Data.SqlClient.SqlException: Cannot open backup device '\\ServerAddress\Folder\file_2017-06-17-110451_daily.bak'. Operating system error 5(Access is denied.).

【问题讨论】:

    标签: sql-server powershell


    【解决方案1】:

    我在 sql server 2012 上测试了你的脚本并成功备份到本地文件夹。

    您的脚本运行良好。

    尝试(用于测试)备份到服务器上的本地文件夹。

    确定:

    • 您安装了 Microsoft Windows PowerShell Extensions for Microsoft SQL Server 2012(带有 SMO)。 详情看我的回答:What do I need to execute a SQL Server PowerShell module

    • 您的服务器有权访问共享文件夹“\\backup\server1”。 在服务器 2012 中,设置 MSSQLSERVER 帐户对共享文件夹“\\backup\server1”的读写权限

    编辑:

    根据您的评论,脚本使用本地文件夹可以正常工作。 所以,问题在于共享文件夹的设置。

    在工作组环境中

    如果你的 sql server 2012 在 WORKGROUP 环境下工作:

    • 在 sql server 2012 和备份服务器(使用计算机管理器)上使用相同的密码(例如“sql2012”)创建相同的窗口用户帐户。

    • 将此账号(sql2012/password)设置为运行sql服务的账号(使用Sql Server配置管理器工具)。

    • 在备份服务器中将共享文件夹Full R/W中的权限设置为账号sql2012

    在域环境中

    • 使用域账户作为运行sql服务的账户(使用Sql Server配置管理器工具)

    • 在备份服务器中将共享文件夹 Full R/W 中的权限设置为该域帐户。

    【讨论】:

    • 是的,它适用于本地文件夹,我无法将 MSSQLSERVER 添加为权限,因为备份服务器没有安装 Sql Server
    • 服务器 2012 工作环境是什么:工作组还是域? sql server 服务帐户是内置帐户还是用户帐户(来自 Sql Server 配置管理器)?
    • 啊,非常感谢你的工作。它在一个工作组上,更改 SQL 配置管理器中的帐户就可以了。
    猜你喜欢
    • 2018-04-09
    • 2012-08-04
    • 2017-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多