

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 刪除儲存磁碟區的快照
<a name="DeletingASnapshot"></a>

您可以刪除儲存磁碟區的快照。例如，如果您已在一段時間後建立儲存磁碟區的多個快照，而且不需要較舊的快照，則建議您執行這項操作。因為快照是增量備份，所以如果您刪除快照，則只會刪除其他快照中不需要的資料。

**Topics**
+ [使用適用於 Java 的 AWS 開發套件刪除快照](#DeletingSnapshotsUsingJava)
+ [使用適用於 .NET 的 AWS SDK 刪除快照](#DeletingSnapshotsUsingDotNet)
+ [使用 刪除快照 AWS Tools for Windows PowerShell](#DeletingSnapshotsUsingPowerShell)

在 Amazon EBS 主控台上，您一次可以刪除一個快照。如需如何使用 Amazon EBS 主控台刪除快照的資訊，請參閱《Amazon EC2 使用者指南》**中的[刪除 Amazon EBS 快照](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-deleting-snapshot.html)。

 若要一次刪除多個快照，您可以使用其中一個支援 Storage Gateway 操作 AWS SDKs。如需範例，請參閱 [使用適用於 Java 的 AWS 開發套件刪除快照](#DeletingSnapshotsUsingJava)、[使用適用於 .NET 的 AWS SDK 刪除快照](#DeletingSnapshotsUsingDotNet)和[使用 刪除快照 AWS Tools for Windows PowerShell](#DeletingSnapshotsUsingPowerShell)。

## 使用適用於 Java 的 AWS 開發套件刪除快照
<a name="DeletingSnapshotsUsingJava"></a>

若要刪除與某個磁碟區建立關聯的多個快照，您可以使用程式設計方式。下列範例示範如何使用適用於 Java 的 AWS 軟體開發套件來刪除快照。若要使用範例程式碼，您應該熟悉如何執行 Java 主控台應用程式。如需詳細資訊，請參閱《適用於 Java 的AWS 軟體開發套件開發人員指南》**中的[入門](https://docs.aws.amazon.com/AWSSdkDocsJava/latest/DeveloperGuide/java-dg-setup.html)。如果您只需要刪除一些快照，請使用主控台，如[刪除儲存磁碟區的快照](#DeletingASnapshot)所述。

**Example ：使用適用於 Java 的 AWS 開發套件刪除快照**  
下列 Java 程式碼範例列出閘道之每個磁碟區的快照，以及快照開始時間早於還是晚於指定的日期。它使用適用於 Storage Gateway 和 Amazon EC2 的適用於 Java 的 AWS SDK API。Amazon EC2 API 包含使用快照的操作。  
更新程式碼以提供服務端點、閘道 Amazon Resource Name (ARN)，以及您要儲存快照的天數。會刪除此截止時間之前所建立的快照。您也需要指定布林值 `viewOnly`，指出要檢視要刪除的快照，還是實際執行快照刪除。首先，僅使用檢視選項來執行程式碼 (即，將 `viewOnly` 設定為 `true`)，以查看程式碼所刪除的內容。如需可與 Storage Gateway 搭配使用 AWS 的服務端點清單，請參閱《[AWS Storage Gateway 》中的端點和配額](https://docs.aws.amazon.com/general/latest/gr/sg.html)*AWS 一般參考*。  

```
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import com.amazonaws.auth.PropertiesCredentials;
import com.amazonaws.services.ec2.AmazonEC2Client;
import com.amazonaws.services.ec2.model.DeleteSnapshotRequest;
import com.amazonaws.services.ec2.model.DescribeSnapshotsRequest;
import com.amazonaws.services.ec2.model.DescribeSnapshotsResult;
import com.amazonaws.services.ec2.model.Filter;
import com.amazonaws.services.ec2.model.Snapshot;
import com.amazonaws.services.storagegateway.AWSStorageGatewayClient;
import com.amazonaws.services.storagegateway.model.ListVolumesRequest;
import com.amazonaws.services.storagegateway.model.ListVolumesResult;
import com.amazonaws.services.storagegateway.model.VolumeInfo;

public class ListDeleteVolumeSnapshotsExample {

    public static AWSStorageGatewayClient sgClient;
    public static AmazonEC2Client ec2Client;    
    static String serviceURLSG = "https://storagegateway.us-east-1.amazonaws.com";
    static String serviceURLEC2 = "https://ec2.us-east-1.amazonaws.com"; 
    
    // The gatewayARN
    public static String gatewayARN = "*** provide gateway ARN ***";
    
    // The number of days back you want to save snapshots. Snapshots before this cutoff are deleted
    // if viewOnly = false.
    public static int daysBack = 10;
    
    // true = show what will be deleted; false = actually delete snapshots that meet the daysBack criteria
    public static boolean viewOnly = true;

    public static void main(String[] args) throws IOException {

        // Create a Storage Gateway and amazon ec2 client
        sgClient = new AWSStorageGatewayClient(new PropertiesCredentials(
                ListDeleteVolumeSnapshotsExample.class.getResourceAsStream("AwsCredentials.properties")));    
        sgClient.setEndpoint(serviceURLSG);
        
        ec2Client = new AmazonEC2Client(new PropertiesCredentials(
                ListDeleteVolumeSnapshotsExample.class.getResourceAsStream("AwsCredentials.properties")));
        ec2Client.setEndpoint(serviceURLEC2);        
        
        List<VolumeInfo> volumes = ListVolumesForGateway();
        DeleteSnapshotsForVolumes(volumes, daysBack);        
        
    }
    public static List<VolumeInfo> ListVolumesForGateway()
    {
        List<VolumeInfo> volumes = new ArrayList<VolumeInfo>();

        String marker = null;
        do {
            ListVolumesRequest request = new ListVolumesRequest().withGatewayARN(gatewayARN);
            ListVolumesResult result = sgClient.listVolumes(request);
            marker = result.getMarker();
            
            for (VolumeInfo vi : result.getVolumeInfos())
            {
                volumes.add(vi);
                System.out.println(OutputVolumeInfo(vi));
            }           
        } while (marker != null);

        return volumes;
    }
    private static void DeleteSnapshotsForVolumes(List<VolumeInfo> volumes,
            int daysBack2) {
        
        // Find snapshots and delete for each volume 
        for (VolumeInfo vi : volumes) {
            
            String volumeARN = vi.getVolumeARN();
            String volumeId = volumeARN.substring(volumeARN.lastIndexOf("/")+1).toLowerCase();
            Collection<Filter> filters = new ArrayList<Filter>();
            Filter filter = new Filter().withName("volume-id").withValues(volumeId);
            filters.add(filter);
            
            DescribeSnapshotsRequest describeSnapshotsRequest =
                new DescribeSnapshotsRequest().withFilters(filters);
            DescribeSnapshotsResult describeSnapshotsResult =
                ec2Client.describeSnapshots(describeSnapshotsRequest);
            
            List<Snapshot> snapshots = describeSnapshotsResult.getSnapshots();
            System.out.println("volume-id = " + volumeId);
            for (Snapshot s : snapshots){
                StringBuilder sb = new StringBuilder();
                boolean meetsCriteria = !CompareDates(daysBack, s.getStartTime());
                sb.append(s.getSnapshotId() + ", " + s.getStartTime().toString());                
                sb.append(", meets criteria for delete? " + meetsCriteria);
                sb.append(", deleted? ");
                if (!viewOnly & meetsCriteria) {
                    sb.append("yes");
                    DeleteSnapshotRequest deleteSnapshotRequest = 
                        new DeleteSnapshotRequest().withSnapshotId(s.getSnapshotId());
                    ec2Client.deleteSnapshot(deleteSnapshotRequest);
                }
                else {
                    sb.append("no");
                }
                System.out.println(sb.toString());                    
            }        
        }
    }

    private static String OutputVolumeInfo(VolumeInfo vi) {
        
        String volumeInfo = String.format(
                 "Volume Info:\n" + 
                 "  ARN: %s\n" +
                 "  Type: %s\n",
                 vi.getVolumeARN(),
                 vi.getVolumeType());
        return volumeInfo; 
     }
    
    // Returns the date in two formats as a list
    public static boolean CompareDates(int daysBack, Date snapshotDate) {
        Date today = new Date();
        Calendar cal = new GregorianCalendar();
        cal.setTime(today);
        cal.add(Calendar.DAY_OF_MONTH, -daysBack);
        Date cutoffDate = cal.getTime();        
        return (snapshotDate.compareTo(cutoffDate) > 0) ? true : false;
    }

}
```

## 使用適用於 .NET 的 AWS SDK 刪除快照
<a name="DeletingSnapshotsUsingDotNet"></a>

若要刪除與某個磁碟區建立關聯的多個快照，您可以使用程式設計方式。下列範例示範如何使用適用於 .NET 的 AWS 軟體開發套件第 2 版和第 3 版來刪除快照。若要使用範例程式碼，您應該熟悉如何執行 .NET 主控台應用程式。如需詳細資訊，請參閱《適用於 .NET 的AWS 軟體開發套件開發人員指南》**中的[入門](https://docs.aws.amazon.com/sdk-for-net/v4/developer-guide/net-dg-config.html)。如果您只需要刪除一些快照，請使用主控台，如[刪除儲存磁碟區的快照](#DeletingASnapshot)所述。

**Example ：使用適用於 .NET 的 AWS SDK 刪除快照**  
在下列 C\$1 程式碼範例中， AWS Identity and Access Management 使用者可以列出閘道每個磁碟區的快照。使用者接著可以判斷快照開始時間早於還是晚於指定的日期 (保留期)，以及刪除已過保留期的快照。此範例使用適用於 Storage Gateway 和 Amazon EC2 的 AWS .NET API 開發套件。Amazon EC2 API 包含使用快照的操作。  
下列程式碼範例使用適用於 .NET 的 AWS SDK 第 2 版和第 3 版。您可以將較舊版本的 .NET 遷移至較新版本。如需詳細資訊，請參閱[遷移適用於 .NET 的 AWS SDK 專案](https://docs.aws.amazon.com/sdk-for-net/v4/developer-guide/net-dg-migrating.html)。  
更新程式碼以提供服務端點、閘道 Amazon Resource Name (ARN)，以及您要儲存快照的天數。會刪除此截止時間之前所建立的快照。您也需要指定布林值 `viewOnly`，指出要檢視要刪除的快照，還是實際執行快照刪除。首先，僅使用檢視選項來執行程式碼 (即，將 `viewOnly` 設定為 `true`)，以查看程式碼所刪除的內容。如需可與 Storage Gateway 搭配使用 AWS 的服務端點清單，請參閱《[AWS Storage Gateway 》中的端點和配額](https://docs.aws.amazon.com/general/latest/gr/sg.html)*AWS 一般參考*。  
 首先，您建立使用者，並將最小 IAM 政策連接至使用者。然後，您排定閘道的自動化快照。  
下列程式碼會建立允許使用者刪除快照的最小政策。在此範例中，政策命名為 **sgw-delete-snapshot**。    
****  

```
{
      "Version":"2012-10-17",		 	 	 
      "Statement": [
          {
              "Sid": "StmtEC2Snapshots",
              "Effect": "Allow",
              "Action": [
                  "ec2:DeleteSnapshot",
                  "ec2:DescribeSnapshots"
              ],
              "Resource": [
                  "*"
              ]
          },
          {
              "Sid": "StmtSgwListVolumes",
              "Effect": "Allow",
              "Action": [
                  "storagegateway:ListVolumes"
              ],
              "Resource": [
                  "*"
              ]
          }
      ]
  }
```
下列 C\$1 程式碼會找出指定閘道中符合磁碟區和指定截止期間的所有快照，然後予以刪除。  

```
using System;
using System.Collections.Generic;
using System.Text;
using Amazon.EC2;
using Amazon.EC2.Model;
using Amazon.StorageGateway.Model;
using Amazon.StorageGateway;

namespace DeleteStorageGatewaySnapshotNS
{
    class Program
    {
        /*
         * Replace the variables below to match your environment.
         */
         
         /* IAM AccessKey */
        static String AwsAccessKey = "AKIA................";
        
        /* IAM SecretKey */
        static String AwsSecretKey = "*******************************";
        
        /* Account number, 12 digits, no hyphen */
        static String OwnerID = "123456789012";
        
        /* Your Gateway ARN. Use a Storage Gateway ID, sgw-XXXXXXXX* */ 
        static String GatewayARN = "arn:aws:storagegateway:ap-southeast-2:123456789012:gateway/sgw-XXXXXXXX";
        
        /* Snapshot status: "completed", "pending", "error" */                                                                                                      
        static String SnapshotStatus = "completed";
        
        /* Region where your gateway is activated */ 
        static String AwsRegion = "ap-southeast-2";
        
        /* Minimum age of snapshots before they are deleted (retention policy) */
        static int daysBack = 30; 

        /*
         * Do not modify the four lines below.
         */
        static AmazonEC2Config ec2Config;
        static AmazonEC2Client ec2Client;
        static AmazonStorageGatewayClient sgClient;
        static AmazonStorageGatewayConfig sgConfig;

        static void Main(string[] args)
        {
            // Create an EC2 client.
            ec2Config = new AmazonEC2Config();
            ec2Config.ServiceURL = "https://ec2." + AwsRegion + ".amazonaws.com";
            ec2Client = new AmazonEC2Client(AwsAccessKey, AwsSecretKey, ec2Config);

            // Create a Storage Gateway client.
            sgConfig = new AmazonStorageGatewayConfig();
            sgConfig.ServiceURL = "https://storagegateway." + AwsRegion + ".amazonaws.com";
            sgClient = new AmazonStorageGatewayClient(AwsAccessKey, AwsSecretKey, sgConfig);

            List<VolumeInfo> StorageGatewayVolumes = ListVolumesForGateway();
            List<Snapshot> StorageGatewaySnapshots = ListSnapshotsForVolumes(StorageGatewayVolumes, 
                                                     daysBack);
            DeleteSnapshots(StorageGatewaySnapshots);
        }

        /*
         * List all volumes for your gateway
         * returns: A list of VolumeInfos, or null.
         */
        private static List<VolumeInfo> ListVolumesForGateway()
        {
            ListVolumesResponse response = new ListVolumesResponse();
            try
            {
                ListVolumesRequest request = new ListVolumesRequest();
                request.GatewayARN = GatewayARN;
                response = sgClient.ListVolumes(request);

                foreach (VolumeInfo vi in response.VolumeInfos)
                {
                    Console.WriteLine(OutputVolumeInfo(vi));
                }
            }
            catch (AmazonStorageGatewayException ex)
            {
                Console.WriteLine(ex.Message);
            }
            return response.VolumeInfos;
        }

        /*
         * Gets the list of snapshots that match the requested volumes
         * and cutoff period.
         */
        private static List<Snapshot> ListSnapshotsForVolumes(List<VolumeInfo> volumes, int snapshotAge)
        {
            List<Snapshot> SelectedSnapshots = new List<Snapshot>();
            try
            {
                foreach (VolumeInfo vi in volumes)
                {
                    String volumeARN = vi.VolumeARN;
                    String volumeID = volumeARN.Substring(volumeARN.LastIndexOf("/") + 1).ToLower();

                    DescribeSnapshotsRequest describeSnapshotsRequest = new DescribeSnapshotsRequest();

                    Filter ownerFilter = new Filter();
                    List<String> ownerValues = new List<String>();
                    ownerValues.Add(OwnerID);
                    ownerFilter.Name = "owner-id";
                    ownerFilter.Values = ownerValues;
                    describeSnapshotsRequest.Filters.Add(ownerFilter);

                    Filter statusFilter = new Filter();
                    List<String> statusValues = new List<String>();
                    statusValues.Add(SnapshotStatus);
                    statusFilter.Name = "status";
                    statusFilter.Values = statusValues;
                    describeSnapshotsRequest.Filters.Add(statusFilter);

                    Filter volumeFilter = new Filter();
                    List<String> volumeValues = new List<String>();
                    volumeValues.Add(volumeID);
                    volumeFilter.Name = "volume-id";
                    volumeFilter.Values = volumeValues;
                    describeSnapshotsRequest.Filters.Add(volumeFilter);

                    DescribeSnapshotsResponse describeSnapshotsResponse = 
                      ec2Client.DescribeSnapshots(describeSnapshotsRequest);

                    List<Snapshot> snapshots = describeSnapshotsResponse.Snapshots;
                    Console.WriteLine("volume-id = " + volumeID);
                    foreach (Snapshot s in snapshots)
                    {
                        if (IsSnapshotPastRetentionPeriod(snapshotAge, s.StartTime))
                        {
                            Console.WriteLine(s.SnapshotId + ", " + s.VolumeId + ", 
                               " + s.StartTime + ", " + s.Description);
                            SelectedSnapshots.Add(s);
                        }
                    }
                }
            }
            catch (AmazonEC2Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            return SelectedSnapshots;
        }

        /*
         * Deletes a list of snapshots.
         */
        private static void DeleteSnapshots(List<Snapshot> snapshots)
        {
            try
            {
                foreach (Snapshot s in snapshots)
                {

                    DeleteSnapshotRequest deleteSnapshotRequest = new DeleteSnapshotRequest(s.SnapshotId);
                    DeleteSnapshotResponse response = ec2Client.DeleteSnapshot(deleteSnapshotRequest);
                    Console.WriteLine("Volume: " +
                              s.VolumeId +
                              " => Snapshot: " +
                              s.SnapshotId +
                              " Response: "
                              + response.HttpStatusCode.ToString());
                }
            }
            catch (AmazonEC2Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        /*
         * Checks if the snapshot creation date is past the retention period.
         */
        private static Boolean IsSnapshotPastRetentionPeriod(int daysBack, DateTime snapshotDate)
        {
            DateTime cutoffDate = DateTime.Now.Add(new TimeSpan(-daysBack, 0, 0, 0));
            return (DateTime.Compare(snapshotDate, cutoffDate) < 0) ? true : false;
        }

        /*
         * Displays information related to a volume.
         */
        private static String OutputVolumeInfo(VolumeInfo vi)
        {
            String volumeInfo = String.Format(
                "Volume Info:\n" +
                "  ARN: {0}\n" +
                "  Type: {1}\n",
                vi.VolumeARN,
                vi.VolumeType);
            return volumeInfo;
        }
    }
}
```

## 使用 刪除快照 AWS Tools for Windows PowerShell
<a name="DeletingSnapshotsUsingPowerShell"></a>

若要刪除與某個磁碟區建立關聯的多個快照，您可以使用程式設計方式。下列範例示範如何使用 AWS Tools for Windows PowerShell來刪除快照。若要使用範例指令碼，您應該熟悉如何執行 PowerShell 指令碼。如需詳細資訊，請參閱《[》](https://docs.aws.amazon.com/powershell/latest/userguide/pstools-getting-started.html)*中的AWS Tools for Windows PowerShell入門*。如果您只需要刪除一些快照，請使用主控台，如[刪除儲存磁碟區的快照](#DeletingASnapshot)所述。

**Example ：使用 刪除快照 AWS Tools for Windows PowerShell**  
下列 PowerShell 指令碼範例列出閘道之每個磁碟區的快照，以及快照開始時間早於還是晚於指定的日期。它使用適用於 Storage Gateway 和 Amazon EC2 的 AWS Tools for Windows PowerShell cmdlet。Amazon EC2 API 包含使用快照的操作。  
您需要更新指令碼，並提供閘道 Amazon Resource Name (ARN) 和您要儲存快照的天數。會刪除此截止時間之前所建立的快照。您也需要指定布林值 `viewOnly`，指出要檢視要刪除的快照，還是實際執行快照刪除。首先，僅使用檢視選項來執行程式碼 (即，將 `viewOnly` 設定為 `true`)，以查看程式碼所刪除的內容。  

```
<#
.DESCRIPTION
    Delete snapshots of a specified volume that match given criteria.
    
.NOTES
    PREREQUISITES:
    1) AWS Tools for Windows PowerShell from https://aws.amazon.com/powershell/
    2) Credentials and AWS Region stored in session using Initialize-AWSDefault.
    For more info see, https://docs.aws.amazon.com/powershell/latest/userguide/specifying-your-aws-credentials.html 

.EXAMPLE
    powershell.exe .\SG_DeleteSnapshots.ps1  
#>

# Criteria to use to filter the results returned.
$daysBack = 18
$gatewayARN = "*** provide gateway ARN ***"
$viewOnly = $true;

#ListVolumes
$volumesResult = Get-SGVolume -GatewayARN $gatewayARN
$volumes = $volumesResult.VolumeInfos
Write-Output("`nVolume List")
foreach ($volumes in $volumesResult)
  { Write-Output("`nVolume Info:")
    Write-Output("ARN:  " + $volumes.VolumeARN)
    write-Output("Type: " + $volumes.VolumeType)
  }

Write-Output("`nWhich snapshots meet the criteria?")
foreach ($volume in $volumesResult)
  { 
    $volumeARN = $volume.VolumeARN
    
    $volumeId = ($volumeARN-split"/")[3].ToLower()
  
    $filter = New-Object Amazon.EC2.Model.Filter
    $filter.Name = "volume-id"
    $filter.Value.Add($volumeId)
    
    $snapshots = get-EC2Snapshot -Filter $filter    
    Write-Output("`nFor volume-id = " + $volumeId)
    foreach ($s in $snapshots)
    {
       $d = ([DateTime]::Now).AddDays(-$daysBack)
       $meetsCriteria = $false
       if ([DateTime]::Compare($d, $s.StartTime) -gt 0)
       {
            $meetsCriteria = $true
       }
       
       $sb = $s.SnapshotId + ", " + $s.StartTime + ", meets criteria for delete? " + $meetsCriteria
       if (!$viewOnly -AND $meetsCriteria) 
       {
           $resp = Remove-EC2Snapshot -SnapshotId $s.SnapshotId
           #Can get RequestId from response for troubleshooting.
           $sb = $sb + ", deleted? yes"
       }
       else {
           $sb = $sb + ", deleted? no"
       }
       Write-Output($sb) 
    }
  }
```