【手摸手学ModelArts】偶遇OBS“惊天”大Bug!

举报
胡琦 发表于 2020/07/18 18:54:21 2020/07/18
【摘要】 一根烟,一杯茶,一个Bug修一天!

偶遇OBS"惊天"大Bug

本文首次发表于华为云社区 ModelArts 版块,主要是作者在学习使用 AI 开发平台 ModelArts 过程中的一些经验产出。此次分享的是上次在ModelArts 上体验 MindSpore[1]时遇到OBS的一个Bug,经过华为云工程师长达40分钟的耐心解答,终于搞懂了这个“惊天大Bug”的来龙去脉,期间我尝试了moxingobsutilsOBS SDK等方式来解决Bug,最后问题终于得到解决。如果您对 AI 感谢兴趣,欢迎【点击阅读原文】参与“2020 华为云 AI 实战营”[2],7 月 31 号前参与还可积分兑好礼!

start.png

↑开局一张图,故事全靠编。

缘起

bigball.jpg

做开发的尤其是前端,你永远不知道用户会怎么使用你的产品,比如页面上一个输入框,你永远不知道用户会输入什么。这次能遇到OBS的这个Bug,也是我无意间做了不当的“输入”,导致上传到OBS的文件无法正常显示,也无法正常操作(如:删除)。先来看看问题究竟是啥,请看下图:1. 无法显示正常的文件信息;2. 点击删除无法正常删除文件,是怎么删都不能删的!; 3. 其他操作也不正常,如分享复制出来的链接访问是NoSuchKeyThe specified key does not exist等等。导致问题出现的原因,大概就是工单解决方案中提到的:上传的对象带了特殊字符,OBS 服务后台不能正常的转义。

显示异常 无法删除
no-message.png no-delete.png

复现

我究竟是做了什么操作才导致OBS无法正常转义呢?为了复现这个问题,我找到了上一次实践的错误代码,罪魁祸首就是它了:

cd ~cd workmkdir mytestcd mytestwget http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gztar -zxvf ./train-images-idx3-ubyte.gz

terminal.png

通过一波Terminal操作,我下载了一个train-images-idx3-ubyte.gz文件,并错误地执行了tar -zxvf ./train-images-idx3-ubyte.gz,这里其实已经是“罪恶的源头”了,我们通过执行ls,可以看到如下文件:

sh-$ls'<'        ''$'\224'  ''$'\374\374\356'  ''$'\376\035'  ''$'\313\367\372\375\375\375\257''9'   train-images-idx3-ubyte.gz''$'\315'  ''$'\341'  ''$'\374\375\216'  ''$'\f'        'm'$'\v\002'

其实这里已经是问题的所在了,因为解压不当导致了一些特殊字符的文件名的生成,当然,如果不上传这些文件到OBS,是不会偶遇文章开头的问题。为了复现,我们通过Moxing将文件上传到OBS上,代码如下:

import os 
import moxing as mox  
mox.file.copy_parallel('./mytest', 'obs://mindspore-labs/mytest')print('Upload done!')

上传之后,回到OBS,发现我们刚解压出来的文件已经存在, 而且如“幽灵”一般存在,它们没有名字,无法删除,就算分享出来也无法正常访问,这里姑且称它们为“影子文件”。

求解

遇到这样的Bug,我还是很兴奋的,作为Copy攻城狮,我平时很少独立思考,这次却破天荒地费了的脑力想想了--还是提工单吧!本来提了工单可能就万事无忧了,不过对于未知事物的好奇,我也开始一步步探索。

网页操作

首先,从结果来论证,直接面向用户的前端页面最能直接展现问题。我分别查看了正常情况和“影子文件”的network,发现了有意思额情况,正常的返回在XMLContents下包含key、size等返回信息,也就是我们能看到的文件名、文件大小、修改时间之类的,而“影子文件”返回的数据Contents下没有任何信息,所以我们看不到文件相关的信息,也无法正常操作文件。

正常文件 影子文件
normal-network.png error-network.png

Moxing列举

其次,通过Moxing列举正常能读取的文件和“影子文件”,也发现了些猫腻,正常文件列表是可以被读取到的,而尝试读取“影子文件”目录就会报错。
执行代码:

import moxing as mox  
# 列举正常文件mox.file.list_directory('obs://mindspore-labs/experiment_1/MNIST/', recursive=True)# 列举影子文件mox.file.list_directory('obs://mindspore-labs/mytest/', recursive=True)

moxing-compare.png
通过以上两步尝试,也预示我们无法通过OBS网页端和Moxing来删除“影子文件”,根据大佬给出的指导,应该使用obsutil[3]或者SDK[4]去删除文件对象。值得注意的是,这两种方法都需要获取访问密钥即AK/SK(Access Key ID/Secret Access Key),获取AK/SK的细节这里就不赘述了。

obsutil体验

不得不提下这款用于访问管理OBS的命令行工具,它具有四大优势:

  • 简单、易用;

  • 无需安装,轻便小巧,即下即用;

  • 同时支持Windows/Linux/macOS三大平台;

  • 配置多元化,性能卓越。
    我是windows系统,下载之后运行obsutil.exe,执行config -i=ak -k=sk -e=endpoint进行初始化配置,ak就是访问密钥的AKsk访问密钥的SKendpoint对应桶所在的终端节点如:obs.cn-north-4.myhuaweicloud.com就是华北-北京4endpoint可访问地区和终端节点[5]查看。
    我尝试列出“影子文件”,结果还是抛了异常Error: Status [0], error code [], error message [XML syntax error on line 1: illegal character code U+000C], request id [000001735BD0E90D440F97BC745F201C],如果要知道究竟发生了什么,可以工单并向华为云工程师大佬提供这个request id,其实通过报错信息我们也能察觉到是有非法字符导致的。
    然后我满怀信心的敲下了rm obs://mindspore-labs/mytest -r -f,以为这样就能删除掉,结果:

[________________________________________________________] ?% tps:0.00 0/0 52ms
Warn: No task to run

List objects in the bucket [mindspore-labs] to delete failed, status [0], error code [], error message [XML syntax error on line 1: illegal character code U+000C], request id [000001735BD70EBE44149CE8B9E179C9]

obsutil.png

是的,删除失败!!!去网页端查看,文件依旧如磐石般岿然不动!
again-success.png

OBS SDK体验

既然前面三种方法都没能删除顽固的“影子文件”,那试试仅有的一丝希望--OBS SDK。由于我是JavaScript技术栈,尽管工单那头的大佬极力推荐Java SDK,我还是毅然决然地选择了Node.js SDK。赶紧下载官方文档提供的Demo代码[6],开始我认为的最后一根破除稻草:
安装依赖:

npm install esdk-obs-nodejs

找到examples\delete-objects-sample.js开干,替换access_key_id的值为访问密钥的AK,secret_access_key的值为访问密钥的SK,server的值为桶所在的终端节点如:"https://obs.cn-north-4.myhuaweicloud.com";其实和**obsutil**的配置大同小异.
我们先通过listObjects列举一下“影子文件”:

var obs = new ObsClient({
    access_key_id: '您的访问访问AK',
    secret_access_key: '您的访问密钥CK',
    server : '桶所在的终端节点'});var bucketName = 'mindspore-labs'; // 桶名obs.listObjects({
    Bucket: bucketName,
    Prefix: 'mytest/' // 前缀,列举mytest下文件}).then((result) => {
    if(result.CommonMsg.Status < 300){
        console.log('List all objects in folder mytest/ \n');
        for(let j=0;j<result.InterfaceResult.Contents.length;j++){
            console.log('\tKey-->' + result.InterfaceResult.Contents[j]['Key']);
            console.log('\tETag-->' + result.InterfaceResult.Contents[j]['ETag']);
        }
        console.log('\n');
    }});

得到的结果出乎我的意料,不仅是影子文件,其他正常的文件也能正常列出,这足以说明Copy攻城狮功力到位了,也是能够解决问题的:

$ node examples/delete-objects-sample.js
List all objects in folder src0/

        Key-->mytest/
        ETag-->"d41d8cd98f00b204e9800998ecf8427e"
        Key-->mytest/
        ETag-->"d41d8
        ETag-->"d41d8cd98f00b204e9800998ecf8427e"
        Key-->mytest/<
        ETag-->"d41d8cd98f00b204e9800998ecf8427e"
        Key-->mytest/md98f00b204e9800998ecf8427e"
        Key-->mytest/t
        ETag-->"d41d8cd98f00b204e9800998ecf8427e"
        Key-->mytest/train-images-idx3-ubyte.gz

影子文件神秘的面纱已经揭开,因为OBS后台无法解析特殊符号如小于号,导致解析进程中断了,亦或是文件路径名不能有特殊字符。既然问题到这,已经非常透彻了,接下来应该是破局的时候了。

破局

既然最终找到了问题的根本,尝试解决吧,依旧使用我们的SDK来处理,只需在上面列举中调用deleteObject

obs.listObjects({
    Bucket: bucketName,
    Prefix: 'mytest/'}).then((result) => {
    if(result.CommonMsg.Status < 300){
        console.log('List all objects in folder mytest/ \n');
        for(let j=0;j<result.InterfaceResult.Contents.length;j++){
            console.log('\tKey-->' + result.InterfaceResult.Contents[j]['Key']);
            console.log('\tETag-->' + result.InterfaceResult.Contents[j]['ETag']);
            obs.deleteObject({
                Bucket: bucketName,
                Key: result.InterfaceResult.Contents[j]['Key']
            }, (err, result) => {
                if(err){
                       console.error('Error-->' + err);
                }else{
                       console.log('Status-->' + result.CommonMsg.Status);
                       console.log('CommonMsg-->' + JSON.stringify(result.CommonMsg));
                }
            });
        }
        console.log('\n');
    }});

end.png

尽管这是最愚笨的方式,但我已经达到了我的预期,无法删除的“影子文件”终于可以通通删除了,感觉世界终于清静了!
温馨提示:以上方法会清除目录下的所有文件,如有要保留特定的文件请通过编写代码实现

最后在OBS网页端再确认一下,终于完成了!
end2.png

加入组织

MDG 是 ModelArts Developer Groups 的缩写。是由 ModelArts 开发者发起的开放、创新、多元的开发者社区组织。致力于帮助开发者学习提升、互动交流、挖掘机会,推动 AI、互联网等产业生态的建立和发展。MDG 是面向人工智能、AI 技术、开源项目及 ModelArts 平台技术感兴趣的公益性开发者社区,相关开发者、软件工程师、创业者、运营人、产品人、大学生、老师等都可以参加到 MDG 社区。
MDG 秉承开放、创新、多元的社区文化,完全由各地志愿者自发组织和建立。目前,我们已在北京、上海、杭州、重庆建立了社区组织。自 2019 年12月起陆续开展了多次线上、线下活动。许多小伙伴正是参与了华为云 ModelArts 的相关活动后,申请加入MDG志愿者组织,从而更深入地了解ModelArts平台。

1048095jdntqe5crxewsqq.png

关于作者

新晋华为云云享专家Copy攻城狮,我是胡琦,近期有幸参与【2020华为云AI实战营】,学习ModelArts并加入【MDG社区】,期待在这里与你相遇!

0.jpg

参考链接

[1] https://bbs.huaweicloud.com/forum/thread-65345-1-1.html

[2] http://2020.huaweicloud.ai

[3] https://support.huaweicloud.com/utiltg-obs/obs_11_0001.html

[4] https://support.huaweicloud.com/sdkreference-obs/obs_02_0001.html

[5] https://developer.huaweicloud.com/endpoint?OBS

[6] https://obssdk.obs.cn-north-1.myhuaweicloud.com/current/nodejs/nodejs.zip


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。