Como ativar a cópia de sombra de volume em uma unidade específica (D :, E:, ...) e configurar a programação usando o Powershell?
Eu só preciso de algumas dicas de como começar.
Como ativar a cópia de sombra de volume em uma unidade específica (D :, E:, ...) e configurar a programação usando o Powershell?
Eu só preciso de algumas dicas de como começar.
Respostas:
Você pode criar uma cópia Shadow em uma unidade específica usando o objeto WMI, conforme explicado no Artigo da Microsoft .
Habilitar cópia de sombra de volume em uma unidade específica (D :, E:, ...) é duas coisas
Demorei um pouco para que isso funcionasse (depois de encontrar o erro simples que causava a falha) e a função está incompleta. Quero adicionar a capacidade de habilitá-lo em um computador remoto, o que provavelmente terá que ser feito por meio de uma tarefa executada uma vez. Se alguém modificar isso e adicionar isso, me avise!
function Enable-ShadowCopies {
param(
[String]$ComputerName = $Env:ComputerName,
[Parameter(Mandatory=$true)]
[String]$Drive
)
$volumeWMI = Get-WmiObject -ComputerName $ComputerName -Class Win32_Volume -Filter "DriveLetter = '$Drive'";
$volumeID = ($volumeWMI.DeviceID.SubString(10)).SubString(0,($volumeWMI.DeviceID.SubString(10)).Length-1);
$scheduler = New-Object -ComObject Schedule.Service
$scheduler.Connect($ComputerName)
$tskDef = $scheduler.NewTask(0);
$tskRegInfo = $tskDef.RegistrationInfo;
$tskSettings = $tskDef.Settings;
$tskTriggers = $tskDef.Triggers;
$tskActions = $tskDef.Actions;
$tskPrincipals = $tskDef.Principal;
# Registration Info
$tskRegInfo.Author = "PowerShell Script";
# Settings
$tskSettings.DisallowStartIfOnBatteries = $false;
$tskSettings.StopIfGoingOnBatteries = $false
$tskSettings.AllowHardTerminate = $false;
$tskSettings.IdleSettings.IdleDuration = "PT600S";
$tskSettings.IdleSettings.WaitTimeout = "PT3600S";
$tskSettings.IdleSettings.StopOnIdleEnd = $false;
$tskSettings.IdleSettings.RestartOnIdle = $false;
$tskSettings.Enabled = $true;
$tskSettings.Hidden = $false;
$tskSettings.RunOnlyIfIdle = $false;
$tskSettings.WakeToRun = $false;
$tskSettings.ExecutionTimeLimit = "PT259200S";
$tskSettings.Priority = "5";
$tskSettings.StartWhenAvailable = $false;
$tskSettings.RunOnlyIfNetworkAvailable = $false;
# Triggers
$tskTrigger1 = $tskTriggers.Create(3);
$tskTrigger2 = $tskTriggers.Create(3);
## Trigger 1
$tskTrigger1.Id = "Trigger1"
$tskTrigger1.StartBoundary = (Get-Date -format "yyyy-MM-dd")+"T07:00:00";
$tskTrigger1.DaysOfWeek = 0x3E; # Monday - Friday - http://msdn.microsoft.com/en-us/library/windows/desktop/aa384024(v=vs.85).aspx
$tskTrigger1.Enabled = $true;
## Trigger 2
$tskTrigger2.Id = "Trigger2";
$tskTrigger2.StartBoundary = (Get-Date -format "yyyy-MM-dd")+"T12:00:00";
$tskTrigger2.DaysOfWeek = 0x3E; # Monday - Friday - http://msdn.microsoft.com/en-us/library/windows/desktop/aa384024(v=vs.85).aspx
$tskTrigger2.Enabled = $true;
# Principals (RunAs User)
$tskPrincipals.Id = "Author";
$tskPrincipals.UserID = "SYSTEM";
$tskPrincipals.RunLevel = 1;
# Actions
$tskActions.Context = "Author"
$tskAction1 = $tskActions.Create(0);
# Action 1
$tskAction1.Path = "C:\Windows\system32\vssadmin.exe";
$tskAction1.Arguments = "Create Shadow /AutoRetry=15 /For="+$volumeWMI.DeviceID;
$tskAction1.WorkingDirectory = "%systemroot%\system32";
# Configure VSS, Add scheduled task
vssadmin Add ShadowStorage /For=$Drive /On=$Drive /MaxSize=10%;
$tskFolder = $scheduler.GetFolder("\")
$tskFolder.RegisterTaskDefinition("ShadowCopyVolume$volumeID", $tskDef, 6, "SYSTEM", $null,5);
}
Mesmo que isso funcione e imite o que acontece quando você o faz pela GUI, ele ainda é exibido como desativado para essa unidade. Mas se você habilitá-lo, nada muda! (LOL) Acho que há algo que também precisa ser modificado no registro.
$diskname = "C:\"
$VolumeWmi = gwmi Win32_Volume -Namespace root/cimv2 | ?{ $_.Name -eq $diskname }
$DeviceID = $VolumeWmi.DeviceID.ToUpper().Replace("\\?\VOLUME", "").Replace("\","")
$TaskName = "ShadowCopyVolume" + $DeviceID
$TaskFor = "\\?\Volume" + $DeviceID + "\"
$Task = "C:\Windows\system32\vssadmin.exe"
$Argument = "Create Shadow /AutoRetry=15 /For=$TaskFor"
$WorkingDir = "%systemroot%\system32"
$ScheduledAction = New-ScheduledTaskAction –Execute $Task -WorkingDirectory $WorkingDir -Argument $Argument
$ScheduledTrigger = @()
$ScheduledTrigger += New-ScheduledTaskTrigger -Daily -At 10:00
$ScheduledTrigger += New-ScheduledTaskTrigger -Daily -At 15:00
$ScheduledSettings = New-ScheduledTaskSettingsSet -Compatibility V1 -DontStopOnIdleEnd -ExecutionTimeLimit (New-TimeSpan -Days 3) -Priority 5
$ScheduledTask = New-ScheduledTask -Action $ScheduledAction -Trigger $ScheduledTrigger -Settings $ScheduledSettings
Register-ScheduledTask $TaskName -InputObject $ScheduledTask -User "NT AUTHORITY\SYSTEM"
Depois de um monte de bagunça com ele, ele funcionou de maneira um pouco diferente (também parece aparecer corretamente por meio da GUI).
Grite nesta página para obter ajuda: https://social.technet.microsoft.com/forums/windowsserver/en-US/fb69840d-5f52-4711-8168-2faa23088233/shadow-copy-schedule-per-script
A desvantagem de usar schtasks (o que essa página usa) é que você não pode ter vários gatilhos até onde posso ver.
Também por causa da maneira como resolvi o problema da solução (usei um bindiff de trabalhar / não funcionar em xml), não estou totalmente convencido de que os sinalizadores que utilizo sejam ótimos.
Mais simples significa usar schtasks que são exibidas na interface do usuário, compatíveis no PowerShell 2. Projetado para uma compilação padrão, pode ser necessário brincar com o $ volumeinfo [x] ao criar o $ taskrun para encontrar o volume apropriado.
$volumeinfo = GWMI -namespace root\cimv2 -class win32_volume
$volumeid = $volumeinfo[1].deviceid
$taskname = "ShadowCopyVolume" + $volumeid.replace("\","").replace("?Volume","")
$taskrun = "C:\Windows\system32\vssadmin.exe Create Shadow /AutoRetry=15 /For=$volumeid"
schtasks /create /RU SYSTEM /SC DAILY /ST 07:00 /RI 60 /DU 12:00 /K /V1 /TN $TaskName /TR "$taskrun "
Pode configurar os seguintes argumentos adequadamente:
OBSERVAÇÃO: A opção / TR EXIGE o espaço no final, se não estiver lá, substituirá a barra invertida final por uma citação dupla, fazendo com que a UI do VSS não reconheça a tarefa.
É isso que eu uso no PowerShell . É um link para o meu site, mas parece muito melhor do que colado aqui.
#Enable Volume Shadow copy
clear
$Continue = Read-Host "Enable Volume Shadowcopy (Y/N)?"
while("Y","N" -notcontains $Continue) {
$Continue = Read-Host "Enable Volume Shadowcopy (Y/N)?"
}
if ($Continue -eq "Y") {
#Enable Shadows
vssadmin add shadowstorage /for=C: /on=C: /maxsize=8128MB
vssadmin add shadowstorage /for=D: /on=D: /maxsize=8128MB
#Create Shadows
vssadmin create shadow /for=C:
vssadmin create shadow /for=D:
#Set Shadow Copy Scheduled Task for C: AM
$Action=new-scheduledtaskaction -execute "c:\windows\system32\vssadmin.exe" -Argument "create shadow /for=C:"
$Trigger=new-scheduledtasktrigger -daily -at 6:00AM
Register-ScheduledTask -TaskName ShadowCopyC_AM -Trigger $Trigger -Action $Action -Description "ShadowCopyC_AM"
#Set Shadow Copy Scheduled Task for C: PM
$Action=new-scheduledtaskaction -execute "c:\windows\system32\vssadmin.exe" -Argument "create shadow /for=C:"
$Trigger=new-scheduledtasktrigger -daily -at 6:00PM
Register-ScheduledTask -TaskName ShadowCopyC_PM -Trigger $Trigger -Action $Action -Description "ShadowCopyC_PM"
#Set Shadow Copy Scheduled Task for D: AM
$Action=new-scheduledtaskaction -execute "c:\windows\system32\vssadmin.exe" -Argument "create shadow /for=D:"
$Trigger=new-scheduledtasktrigger -daily -at 7:00AM
Register-ScheduledTask -TaskName ShadowCopyD_AM -Trigger $Trigger -Action $Action -Description "ShadowCopyD_AM"
#Set Shadow Copy Scheduled Task for D: PM
$Action=new-scheduledtaskaction -execute "c:\windows\system32\vssadmin.exe" -Argument "create shadow /for=D:"
$Trigger=new-scheduledtasktrigger -daily -at 7:00PM
Register-ScheduledTask -TaskName ShadowCopyD_PM -Trigger $Trigger -Action $Action -Description "ShadowCopyD_PM"
}
Na verdade, a Cópia de sombra é ativada criando tarefas que chamam vssadmin.exe.
O PowerShell 3.0 possui cmdlets que permitem criar tarefas, mas dependem de chamadas de sistema que não foram implementadas até o Windows 8 / Windows Server 2012. Você precisa dos três seguintes cmdlets para fazer isso da maneira do PowerShell:
register-scheduledTask
new-scheduledtaskaction
new-scheduledtasktrigger
Nas versões anteriores do Windows, você estará restrito ao uso do schtasks.exe.
No entanto - e é aqui que essa resposta difere das outras - a criação de uma tarefa de Cópia de Sombra dessa maneira não é a maneira correta de fazer as coisas, pois as alterações feitas não aparecerão na GUI. Como tal, um usuário não observador pode não perceber que a Cópia de Sombra foi ativada, resultando na habilitação de uma segunda instância ou sobrescrevendo silenciosamente sua tarefa (se você seguiu as convenções de nomenclatura do Windows (VolumeShadowCopy {$ GUID})).
O que você precisa fazer é criar uma via GUI (de preferência no Win7 / Win2008, pois as versões mais recentes do Windows usam o taskxml 1.2 por padrão, em vez do taskxml 1.1 mais compatível), exportar a tarefa como XML via schtasks, editar programaticamente esse XML , salve esse XML como UTF16 e importe-o. Felizmente, depois de passar pela GUI no início, tudo isso pode ser feito na linha de comando.
Gostaria de publicar o código, mas o que escrevi é proprietário e não tenho permissão do meu empregador. Espero que a dica XML economize, no mínimo, inúmeras horas. Acabei de implantar a solução XML em centenas de servidores gerenciados, com grande sucesso.
Obrigado a todos, que estava contribuindo para este tópico. Foi útil e me salvou muito trabalho. O seguinte script do PowerShell foi testado no Windows Server 2008 R2.
O exemplo a seguir cria um instantâneo a cada 2 horas entre Mo.-Fr. das 08: 00h às 18: 00h no Volume C:
Se você deseja modificar a programação, basta editar ou substituir os dados XML embutidos.
Atenção: Sem garantia. Nenhuma responsabilidade. Teste em seu próprio laboratório antes de usar no ambiente de produção.
# German Keyboard-Layout for Console Output. Can be skipped in english enviroments
#chcp 1252 >$null 2>&1
function ConfigureVolumeShadowCopies([string] $diskname, $vssMaxSizeInPercent) {
$xmlDocument = [xml] "<?xml version='1.0' encoding='UTF-16'?>
<Task version='1.1' xmlns='http://schemas.microsoft.com/windows/2004/02/mit/task'>
<RegistrationInfo>
<Author>Administrator</Author>
</RegistrationInfo>
<Triggers>
<CalendarTrigger>
<StartBoundary>2018-01-01T08:00:00</StartBoundary>
<Enabled>true</Enabled>
<ScheduleByWeek>
<DaysOfWeek>
<Monday />
<Tuesday />
<Wednesday />
<Thursday />
<Friday />
</DaysOfWeek>
<WeeksInterval>1</WeeksInterval>
</ScheduleByWeek>
</CalendarTrigger>
<CalendarTrigger>
<StartBoundary>2018-01-01T10:00:00</StartBoundary>
<Enabled>true</Enabled>
<ScheduleByWeek>
<DaysOfWeek>
<Monday />
<Tuesday />
<Wednesday />
<Thursday />
<Friday />
</DaysOfWeek>
<WeeksInterval>1</WeeksInterval>
</ScheduleByWeek>
</CalendarTrigger>
<CalendarTrigger>
<StartBoundary>2018-01-01T12:00:00</StartBoundary>
<Enabled>true</Enabled>
<ScheduleByWeek>
<DaysOfWeek>
<Monday />
<Tuesday />
<Wednesday />
<Thursday />
<Friday />
</DaysOfWeek>
<WeeksInterval>1</WeeksInterval>
</ScheduleByWeek>
</CalendarTrigger>
<CalendarTrigger>
<StartBoundary>2018-01-01T14:00:00</StartBoundary>
<Enabled>true</Enabled>
<ScheduleByWeek>
<DaysOfWeek>
<Monday />
<Tuesday />
<Wednesday />
<Thursday />
<Friday />
</DaysOfWeek>
<WeeksInterval>1</WeeksInterval>
</ScheduleByWeek>
</CalendarTrigger>
<CalendarTrigger>
<StartBoundary>2018-01-01T16:00:00</StartBoundary>
<Enabled>true</Enabled>
<ScheduleByWeek>
<DaysOfWeek>
<Monday />
<Tuesday />
<Wednesday />
<Thursday />
<Friday />
</DaysOfWeek>
<WeeksInterval>1</WeeksInterval>
</ScheduleByWeek>
</CalendarTrigger>
<CalendarTrigger>
<StartBoundary>2018-01-01T18:00:00</StartBoundary>
<Enabled>true</Enabled>
<ScheduleByWeek>
<DaysOfWeek>
<Monday />
<Tuesday />
<Wednesday />
<Thursday />
<Friday />
</DaysOfWeek>
<WeeksInterval>1</WeeksInterval>
</ScheduleByWeek>
</CalendarTrigger>
</Triggers>
<Principals>
<Principal id='Author'>
<UserId>S-1-5-18</UserId>
<RunLevel>HighestAvailable</RunLevel>
</Principal>
</Principals>
<Settings>
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
<IdleSettings>
<Duration>PT600S</Duration>
<WaitTimeout>PT3600S</WaitTimeout>
<StopOnIdleEnd>false</StopOnIdleEnd>
<RestartOnIdle>false</RestartOnIdle>
</IdleSettings>
<Enabled>true</Enabled>
<Hidden>false</Hidden>
<RunOnlyIfIdle>false</RunOnlyIfIdle>
<WakeToRun>false</WakeToRun>
<ExecutionTimeLimit>PT259200S</ExecutionTimeLimit>
<Priority>5</Priority>
</Settings>
<Actions Context='Author'>
<Exec>
<Command>C:\Windows\system32\vssadmin.exe</Command>
<Arguments>Create Shadow /AutoRetry=15 /For=\\?\Volume{REPLACEME}\</Arguments>
<WorkingDirectory>%systemroot%\system32</WorkingDirectory>
</Exec>
</Actions>
</Task>"
# Query Volume GUID of the given Volume
$VolumeWmi = gwmi Win32_Volume -Namespace root/cimv2 | ?{ $_.Name -eq ($diskname +"\") }
# Build Variables
$DeviceID = $VolumeWmi.DeviceID.ToUpper().Replace("\\?\VOLUME", "").Replace("\","")
$TaskName = "ShadowCopyVolume" + $DeviceID
$TaskFor = "\\?\Volume" + $DeviceID + "\"
# Replace Volume GUID in XML-Data
$xmlDocument.Task.Actions.Exec.Arguments = "Create Shadow /AutoRetry=15 /For=$TaskFor"
# Write temporary XML-File for Import of scheduled Task with schtask
$xmlDocumentFileName = $PSScriptRoot + "\" + $TaskName + ".xml"
$xmlDocument.Save($xmlDocumentFileName)
# Try to Delete existing Task for VSS
try {
schtasks /delete /TN $Taskname /f
}
catch {
#If Task can not be found: do nothing
}
# Create Scheduled Task
schtasks /Create /XML $xmlDocumentFileName /TN $TaskName
# Create (First) Snapshot
vssadmin Create Shadow /For=$diskname /AutoRetry=15
# Define Max Size of VSS Shadow Storage
vssadmin resize shadowstorage /For=$diskname /On=$diskname /MaxSize=$vssMaxSizeInPercent
# Delete temporary XML Document
Remove-Item $xmlDocumentFileName -Force
}
# Start Configuration - for Example on Volume C: with 10% MaxSize
ConfigureVolumeShadowCopies "C:" "10%"
Consegui exatamente o que precisava com o código a seguir, meu requisito era configurar o VSS, mas também precisava estar visível na GUI. A parte principal para torná-lo visível na GUI é adicionar o ID do volume no nome da tarefa agendada, conforme apontado pelo user261949 (isso é um pouco estranho, honestamente, eu estava procurando por uma chave do Registro, mas não encontrei absolutamente nada ..). Acabei com o seguinte código que atende às minhas necessidades:
#Enable Volume Shadow copy
#Enable Shadows
vssadmin add shadowstorage /for=C: /on=C: /maxsize=8128MB
#Create Shadows
vssadmin create shadow /for=C:
#create scheduled tasks
$diskname = "C:\"
$VolumeWmi = gwmi Win32_Volume -Namespace root/cimv2 | ?{ $_.Name -eq $diskname }
$DeviceID = $VolumeWmi.DeviceID.ToUpper().Replace("\\?\VOLUME", "").Replace("\","")
$TaskName = "ShadowCopyVolume" + $DeviceID
$TaskFor = "\\?\Volume" + $DeviceID + "\"
$Task = "C:\Windows\system32\vssadmin.exe"
$Argument = "Create Shadow /AutoRetry=15 /For=$TaskFor"
$WorkingDir = "%systemroot%\system32"
$ScheduledAction = New-ScheduledTaskAction -Execute $Task -WorkingDirectory
$WorkingDir -Argument $Argument
$ScheduledTrigger = @()
$ScheduledTrigger += New-ScheduledTaskTrigger -Daily -At 07:00
$ScheduledTrigger += New-ScheduledTaskTrigger -Daily -At 12:00
$ScheduledSettings = New-ScheduledTaskSettingsSet -Compatibility V1 -DontStopOnIdleEnd -ExecutionTimeLimit (New-TimeSpan -Days 3) -Priority 5
$ScheduledTask = New-ScheduledTask -Action $ScheduledAction -Trigger
$ScheduledTrigger -Settings $ScheduledSettings
Register-ScheduledTask $TaskName -InputObject $ScheduledTask -User 'NT AUTHORITY\SYSTEM'
Obrigado a todos por suas informações úteis!