删除OSS中的Bucket时提示“Bucket不为空”

问题描述

使用阿里云对象存储OSS过程中,对于不再需要的Bucket,在使用OSS SDK、ossutil等工具删除或者在控制台删除时,删除失败,相应的报错信息如下:

  • 使用OSS SDK或者ossutil工具删除Bucket时,提示“The bucket you tried to delete is not empty”错误。

  • OSS管理控制台中删除Bucket时,提示“Bucket不为空,请检查该Bucket是否包含未删除的Object或者未成功的Multipart碎片”错误。

问题原因

需要删除的Bucket中有未删除的Object、碎片、Livechannel或未完成的分片上传任务,为了防止误删除的发生,OSS不允许删除一个非空的Bucket。

解决方案

由于删除Bucket后数据不可恢复,请您确保数据备份完成后,删除该Bucket下的所有文件(Object)、碎片(Part)以及Livechannel,再次操作删除Bucket,请参见以下操作删除Bucket:

检查Bucket中是否存在未删除的文件和碎片

如何删除的Bucket中不存在文件和碎片,具体操作如下:

  1. 登录OSS管理控制台

  2. 单击左侧导航栏的Bucket 列表,然后单击目标Bucket名称。

  3. 文件列表页签下,查看下是否存在文件。

  4. 单击碎片管理页签,在碎片管理(Multipart)页面,删除碎片文件。

    • 如果要删除该存储空间所有的碎片文件,单击删除所有

    • 如果要删除部分碎片文件,选择或搜索碎片文件,然后单击删除

  5. 使用ossutil工具,执行以下命令,删除Bucket。如果还是存在Bucket不为空的报错,请继续执行下一步。

    ./ossutil rm oss://[$Bucket_Name] -bar
    说明

    [$Bucket_Name]为Bucket名称。

检查是否存在历史版本Object

版本控制是针对存储空间(Bucket)级别的数据保护功能。开启版本控制后,针对数据的覆盖和删除操作将会以历史版本的形式保存下来。在错误覆盖或者删除文件(Object)后,您可以将Bucket中存储的Object恢复至任意时刻的历史版本。但是通过控制台和工具查看(不指定版本号的查询)只显示最新数据,历史版本不显示。删除历史版本Object的方法如下:

使用OSS管理控制台

  1. 登录OSS管理控制台

  2. 单击Bucket 列表,然后单击目标Bucket名称。

  3. 在左侧导航栏,选中数据安全 > 版本控制,检查是否开启了版本控制功能。如果开启了版本控制功能,请执行以下操作,删除历史版本Object。

    1. 在左侧导航栏,选择文件管理 > 文件列表

    2. 找到不再需要的历史版本Object,单击右侧的彻底删除

    3. 单击确定

  4. 执行完以上操作后,可以尝试删除Bucket,测试是否可以删除成功。如果还是报错,请继续执行下一步。

使用ossutil工具

  1. 通过执行以下命令查看是否开启版本控制功能,详情请参见bucket-versioning(版本控制)

    ./ossutil bucket-versioning --method get oss://[$Bucket_Name]

    系统显示类似如下。

    bucket versioning status:Enabled
    • 如果开启了版本控制功能,则返回结果为Enabled,可执行以下命令,删除Bucket中的历史版本Object数据。

      ./ossutil rm oss://[$Bucket_Name]/ --all-versions -r

      系统显示类似如下。

    • 如果未开启版本控制功能,则返回结果为Disable。

  2. 执行完以上操作后,可以尝试删除Bucket,测试是否可以删除成功。如果还是报错,请继续执行下一步。

排查Bucket中是否存在LiveChannel

BucketLiveChannel查看和删除暂不支持通过工具和控制台操作,可以使用接口或者是SDK来实现操作,请参见DeleteLiveChannel,删除指定的LiveChannel。示例代码如下:

import java.util.List;
import com.alibaba.fastjson.JSON;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.CreateLiveChannelRequest;
import com.aliyun.oss.model.CreateLiveChannelResult;
import com.aliyun.oss.model.ListLiveChannelsRequest;
import com.aliyun.oss.model.LiveChannelGenericRequest;
import com.aliyun.oss.model.LiveChannelListing;
import com.aliyun.oss.model.LiveChannelStatus;
import com.aliyun.oss.model.LiveChannelTarget;
import com.aliyun.oss.model.LiveChannel;
import com.aliyun.oss.common.auth.*;

public class DeleteLiveChannel {
    private static String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
    
private static final

    /**
     * 通过环境变量获取访问凭证
     */
    private static final EnvironmentVariableCredentialsProvider CREDENTIALS_PROVIDER = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();

    private static String bucketName = "bucktname";
    
    public static void createLiveChannel() {

        // 创建OSSClient实例。
        String liveChannelName = "liveChannelName1";
        OSS oss = new OSSClientBuilder().build(endpoint, CREDENTIALS_PROVIDER);
        CreateLiveChannelRequest request = new CreateLiveChannelRequest(bucketName,
                liveChannelName, "desc", LiveChannelStatus.Enabled, new LiveChannelTarget());
        CreateLiveChannelResult result = oss.createLiveChannel(request);

        //获取推流地址。
        List<String> publishUrls = result.getPublishUrls();
        for (String item : publishUrls) {
            System.out.println(item);
        }

        //获取播放地址。
        List<String> playUrls = result.getPlayUrls();
        for (String item : playUrls) {
            System.out.println(item);
        }

        oss.shutdown();
    }
    public static void listLiveChannels() {
       

        // 创建OSSClient实例。
        OSS oss = new OSSClientBuilder().build(endpoint, CREDENTIALS_PROVIDER);

        ListLiveChannelsRequest request = new ListLiveChannelsRequest(bucketName);
        LiveChannelListing liveChannelListing = oss.listLiveChannels(request);
        List<LiveChannel> list = liveChannelListing.getLiveChannels();
        for(LiveChannel i:list){
            deleteLiveChannel(i.getName());
        }
        oss.shutdown();
    }
    public static void deleteLiveChannel(String liveChannelName) {

        // 创建OSSClient实例。
        OSS oss = new OSSClientBuilder().build(endpoint, CREDENTIALS_PROVIDER);
        LiveChannelGenericRequest request = new LiveChannelGenericRequest(bucketName, liveChannelName);
        System.out.println("Delete liveChanne "+liveChannelName+" Done");
        try {
            oss.deleteLiveChannel(request);
        } catch (OSSException ex) {
            ex.printStackTrace();
        } catch (ClientException ex) {
            ex.printStackTrace();
        } finally {
            oss.shutdown();
        }
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        DeleteLiveChannel.listLiveChannels();
    }

}