hb-lee 的博客


  • Home

  • Archives

SSH 免密登录原理

Posted on 2020-01-07

SSH 免密登录原理

SSH登录过程

下面一张图解密SSH登录的过程:

先在自己的机器上生成一份公钥和私钥(ssh-keygen -t rsa),然后将公钥放在目标服务器的授权列表中;这个就是authorized_keys文件;
验证过程:当你在自己机器上申请连接服务器时,目标服务器在authorized_keys中查找,若存在则利用这个公钥进行加密并返回给你所在机器,你自己的机器上会利用私钥进行解密,然后返回给要连接的机器,然后完成验证的过程。

免密登录配置

在源服务器上生成公钥和私钥
ssh-keygen -t rsa

默认会在/root/.ssh下生成id_rsa, id_rsa_pub文件

拷贝公钥到要登录的服务器
ssh-copy-id [目标服务器IP]

至此已经完成了源服务器到目标服务器上的免密登录。为了让一个集群中的节点相互之间互相免密登录,可以将id_rsa, id_rsa.pub拷贝一份到所有节点即可。

Mdtest测试工具使用

Posted on 2019-11-19

Mdtest参数说明

选项 说明
-F 只创建文件
-D 只针对目录进行测试
-L 只在目录树的子目录层创建文件/目录
-z 目录树深度(从根到叶子节点的深度)
-b 目录树的分支数(非叶子节点的分支)
-I 每个节点下的目录或文件数
-u 为每个工作任务指定工作目录
-d 指出测试运行的目录
-i c测试循环的次数
-n 每个进程将要创建/统计/删除的目录和文件数目
-w 文件创建以后写入多少bytes
-p 循环前的时间延迟

nova(基于NVM的文件系统)安装

Posted on 2019-09-06

nova(基于NVM的文件系统)安装

NOVA简单介绍

NOVA是一个基于日志结构的NVM文件系统;它用到了DAX和持久化内存pmem。源码在官方提供的地址:https://github.com/NVSL/linux-nova

笔者所用环境

  • 系统:CentOS Linux release 7.3.1611 (Core)
  • 硬件:Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz; DELL, OptiPlex 7040
  • 以最新的5.1版本为例,代码链接:https://github.com/NVSL/linux-nova/tree/5.1

最初的nova是只适合在4.3的内核上运行,后面nova更新后已经做到内核里去了;新的网址提供了很多不同内核的版本,经过笔者亲测,基本都可以下载下来直接编译可用!无不佩服其工程能力。

Nova安装

解压
unzip linux-nova-5.1.zip
cd linux-nova-5.1
配置内核编译选项
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@bogon linux-nova-5.1]# make nconfig
Device Drivers --->
<*> NVDIMM (Non-Volatile Memory Device) Support --->
<*> PMEM: Persistent memory block device support (NEW)
<*> BLK: Block data window (aperture) device support (NEW)
[*] BTT: Block Translation Table (atomic sector updates)
Processor type and features --->
<*> Support non-standard NVDIMMs and ADR protected memory
Memory Management options --->
[*] Allow for memory hot-add
[*] Online the newly added memory blocks by default
[*] Allow for memory hot remove
[*] Device memory (pmem, HMM, etc...) hotplug support
File systems --->
[*] Direct Access (DAX) support
<*> NOVA: log-structured file system for non-volatile memories
编译
1
2
3
make -j4
make modules_install
make install
设置pmem设备大小
1
2
3
vim /etc/default/grub
在`GRUB_CMDLINE_LINUX`这一行中加入`memmap=4G!12G`;表示将16GB的内存划分为12GB DRAM + 4GB的PMEM
grub2-mkconfig -o /boot/grub2/grub.cfg 【更新grub】

Nova使用

1
2
3
mkdir /mnt/ramdisk
modprobe nova
mount -t NOVA -o init /dev/pmem0 /mnt/ramdisk

安装过程中遇到的坑

1. 内核更新后启动不了,直接进行emergency mode

分析

在某种内核下进入emergency mode键盘可用,这时输入journalctl可以看到相关日志,发现/sysroot系统安装失败,进一步分析是由于这个挂载的是xfs文件系统,而编译内核的时候默认没有选上这个模块;按照以下方式选择这个模块编入即可!

1
2
3
4
5
6
[root@bogon linux-nova-5.1]# make nconfig
File systems --->
<*> XFS filesystem support
[*] XFS Quota support
[*] XFS POSIX ACL support
...
2. 按照nova官方文档,选择CONFIG_LIBNVDIMM, CONFIG_BLK_DEV_PMEM, CONFIG_FS_DAX, CONFIG_NOVA_FS,重启后/dev目录下没有看到pmem设备

分析

相关的配置选项没有选择完全;如以下:

1
2
Processor type and features  --->
<*> Support non-standard NVDIMMs and ADR protected memory
3. 执行挂载nova的时候报错,dmesg | tail输出device does not support DAX

分析

是由于没有配置MEMORY_HOTPLUG,这一个编译选项在新的内核里已经移植到了Memory Management options中,如果找不到可以在编译选项配置中进行搜索;

1
2
3
4
5
Memory Management options  --->
[*] Allow for memory hot-add
[*] Online the newly added memory blocks by default
[*] Allow for memory hot remove
[*] Device memory (pmem, HMM, etc...) hotplug support

总结

基本都是内核编译选项没选择对。

参考文献

http://pmem.io/2016/02/22/pm-emulation.html
https://github.com/NVSL/linux-nova/blob/master/Documentation/filesystems/nova.txt

指针相关

Posted on 2019-09-04

指针相关

智能指针

  • 智能指针原理
    智能指针是一个类,这个类的构造函数中传入一个普通指针,胸骨函数中释放传入的指针。智能指针的类都是栈上的对象,所以当函数(或程序)结束时会自动被释放。可以避免内存泄露。

  • 常见的智能指针
    C++11引入了智能指针有:auto_ptr, unique_ptr, shared_ptr和weak_ptr;shared_ptr是基于引用计数的智能指针,可随意赋值,直到内存的引用计数为0的时候这个内存会被释放。

CentOS升级GCC

Posted on 2019-09-04

升级GCC

有时升级内核,安装软件需要更高级的gcc,而CentOS默认的gcc版本是4.8.5;这里我们升级到gcc-6.4

编译安装(无网络的情况下)

  • 下载
    下载gcc-6.4:https://ftp.gnu.org/gnu/gcc/gcc-6.4.0/gcc-6.4.0.tar.gz

  • 安装依赖
    需要安装的依赖有gmp, mpfr, mpc, isl;下载路径依次为:

    • gmp: https://gmplib.org/download/gmp
    • mpfr: https://www.mpfr.org/mpfr-current
    • mpc: https://ftp.gnu.org/gnu/mpc
    • isl:http://isl.gforge.inria.fr
1
2
3
4
【安装依赖的步骤】
./configure
make
make install
  • 更新库新加的库
1
2
vim /etc/profile
添加 `export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib`避免找不到库;
  • 安装gcc
1
2
3
4
【安装步骤】
./configure -enable-checking=release -enable-languages=c,c++ -disable-multilib
make
make install

报错解决

1
isl_space_dim, isl_id_alloc, isl_id_get_user等等未声明;

这些变量是isl库中的参数,通过查找grep -rn "xxx" /usr/local/include/isl知道是在isl/id.h, isl/space.h这些头文件中,在报错的文件中加入头文件即可!

1
2
3
4
vim gcc/graphite.h

#include <isl/id.h>
#include <isl/space.h>

然后重新编译gcc后即可成功。

1
2
3
4
5
[root@bogon gcc-6.4.0]# gcc --version
gcc (GCC) 6.4.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

程序内存布局

Posted on 2019-09-04

程序内存布局

程序在内存中的运行会涉及到以下布局:

  • 栈(高地址)
    存局部变量,临时变量,返回值,指针…
  • 堆
    存new出来的对象
  • BBS段
    存未初始化的全局变量+静态变量
  • 代码段
    存二进制代码片段,一般只读
  • 数据段
    存已经初始化的全局变量+静态变量+常量

BSS段+数据段共同组成DATA区

程序例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int a = 0;                   //全局初始化区  数据段

char *p1; //全局未初始化区 BSS段

int main() {
int b; // 栈

char s[] = "abc"; //栈

char *p2; //栈

char *p3 = "123456"; //123456\0在常量区,而p3在栈上。

static int c = 0; //全局(静态)初始化区

p1 = (char *)malloc(10);

p2 = (char *)malloc(20); //分配得来得10和20字节的区域就在堆区。

strcpy(p1, "123456"); //123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。

return 0;
}

参考

https://www.jianshu.com/p/4c74a19ad03b

S3的RESTful接口特点总结

Posted on 2019-07-08

S3的RESTful接口特点总结

  • 删除桶
1
2
DELETE /
Host bucket.endpoint

分析:request无必要参数

  • 删除对象
1
2
DELETE /obj
Host bucket.endpoint

分析:request无必要参数

  • 列举桶中对象
1
2
GET /  | GET /?xx
Host bucket.endpoint

分析:request后面有可选参数

  • 删除多个对象(批量删)
1
2
POST /?delete
Host bucket.endpoint

分析:request参数中带delete

  • 上传对象

PUT 方式

1
2
PUT /obj
Host bucket.endpoint

分析:request无必要参数

POST 方式

1
2
POST /
Host bucket.endpoint

分析:待定,暂不考虑

COPY 方式

1
2
3
PUT /obj
Host bucket.endpoint
x-amz-copy-source /srcbucket/srcobj

分析:含有x-amz-copy-source选项,mv是会多一个Delete

  • 下载对象
1
2
GET /obj
Host bucket.endpoint

分析:request无必要参数

  • 分块上传
1
2
PUT /obj?partNumber=xx&uploadId=xx
Host bucket.endpoint

分析:可以用带有uploadId参数来进行区分



Other


  • 删除Bucket的一些配置
1
2
DELETE /<bucket-name>?someconfopt
Host bucket.endpoint

是可选的,有一些要带这个,只要不是/则说明都不是删除桶

  • 获取Bucket的一些配置
1
2
GET /?someconfopt
Host bucket.endpoint

需要区别于列举桶中对象的请求

  • HEAD 判断bucket是否存在和是否有访问权限
1
2
HEAD /
Host bucket.endpoint

HEAD标志

  • 设置Bucket的一些配置 (对象也是一致)
1
2
PUT /?someconfopt
Host bucket.endpoint

只要不是/则说明都不是创建桶

  • 创建桶
1
2
PUT /
Host bucket.endpoint

一定是/

  • 获取对象属性
1
2
GET /obj?attr
Host bucket.endpoint

后面有参数

  • HEAD返回对象元数据信息
1
2
HEAD /obj
Host bucket.endpoint

Head 标志,不是/

  • 终止分段上传 (分段上传的都有uploadId这个参数)
1
2
DELETE /obj?uploadId=xxx
Host bucket.endpoint

需要用uploadId来区别其他的DELETE操作,比如区别删除对象操作

Ceph Admin API 管理接口

  • 创建用户

    PUT /admin/user?format=json&uid=&display-name=

S3常见接口使用

Posted on 2019-07-08

S3常见接口使用

分段上传

分段上传允许上传单个对象作为一组分段。每个分段都是对象数据的连续部分。您可以独立上传以及按任意顺序上传这些对象分段。如果任意分段传输失败,可以重新传输该分段且不会影响其他分段。当对象的所有段都上传后,Amazon S3 将这些段汇聚起来,然后创建对象。
分段上传可提供以下优势:

  • 文件小于5MB不适用分块上传
  • 并行上传分段以提高吞吐量。
  • 较小的分段大小可以将由于网络错误而需重启失败的上传所产生的影响降至最低。
  • 可以随时上传对象分段。启动分段上传后,不存在过期期限;您必须显式地完成或中止分段上传。
  • 可以在创建对象的同时上传对象。

分段上传分三个步骤:初始化准备、并行上传,完成上传。同时在并行阶段,还可以进行终止上传和查询已上传列表的操作。

上传初始化阶段

发送HTTP POST请求,成功则返回对应的upload ID(后续的上传操作都必须使用相同的upload ID),完成Metadata设置和ACL设置。

上传分段阶段

client端完成文件切片,每个片有一个1~10000之间的任意分段编号(相同的编号会出现覆盖),无论何时上传分段,Amazon S3 都将在其响应中返回ETag 标头。对于每个分段上传,必须记录分段编号和ETag 值。除最后一个分块以为,其余分块大于 5 MB。

完成上传阶段

完成分段上传时,Amazon S3 通过按升序的分段编号规范化分段来创建数据元。成功完成请求后,分段将不再存在。完成分段上传请求必须包括上传 ID 以及分段编号和相应的 ETag 值的列表。这一阶段在完成所有upload Part以后必须执行(否则占用的临时资源仍然纳入计费范围)

分段上传列表

对于每个列出分段请求,Amazon S3 将返回有关特定分段上传的分段信息,最多为 1 000 个分段。如果分段上传中的分段超过 1 000 个,您必须发送一系列列出分段请求以检索所有分段。返回的段列表不包括未完成上传的段。

分块上传规范

名称 规范
最大对象大小 5 TB
每次上传的分段的最大数量 10000
分段编号 1 到 10000(含)
分段大小 5 MB 到 5 GB,最后一个分段可以 <5 MB
列出分段请求返回的分段的最大数量 1000
在列出分段上传请求中返回的分段的最大数量 1000

【代码示例】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# -*- coding: utf-8 -*-
import boto
import boto.s3.connection
import os
import boto.utils

# os.environ['S3_USE_SIGV4'] = 'True'

endpoint = 's3dev.nie.netease.com'
access_key = 'ELWZK6*****05YTC25'
secret_key = 'quDVDt*******eVvOQsP'

key_name = 'TCP-IP.pdf'
part_num = 2 # 文件切分数量
bucket_name = 'mybucket'
metadata={'Content-Type':'application/json','x-amz-meta-abc':'data'} #metadata定义
policy = 'public-read' # ACL配置
file_path = '/home/lihongbo01/workspace/s3_workspace/TCP-IP.pdf'

conn = boto.connect_s3(
aws_access_key_id = access_key,
aws_secret_access_key = secret_key,
host = endpoint,
is_secure=False,
calling_format = boto.s3.connection.SubdomainCallingFormat(),
)

# 定义一个函数完成本地文件的分块切片操作
def split_file(filename):
filelist=[]
statinfo = os.stat(filename)
chunksize = statinfo.st_size/part_num
print "file size: %d(mb)" % (statinfo.st_size/(1024*1024))
with open(filename, "rb") as f:
index = 1
while True:
chunk = f.read(chunksize)
if(chunk):
fn = "%s.part.%d" % (filename, index)
index = index + 1
filelist.append(fn)
print "creating", fn
with open(fn, "wb") as fw:
fw.write(chunk)
else:
break
return filelist

def up_with_multi_part(filename,bucketname,key_name,metadata=None,policy='private'):
bucket = conn.get_bucket(bucketname)
print bucket.get_location()
mpu = bucket.initiate_multipart_upload(key_name,metadata=metadata,policy=policy) # 初始化分块上传
print mpu.get_all_parts()
print mpu.id
filelist = split_file(filename)
f_num = 1
for f in filelist:
sfp = open(f,'rb')
hd, cm, cl = boto.utils.compute_md5(sfp)
md5 = (hd, cm)
print md5
mpu.upload_part_from_file(sfp, part_num=f_num,md5=md5) # 上传分块,每个分块都做md5校验
sfp.close()
f_num = f_num+1
print "%s is done" % f
mpu.complete_upload() # 完成上传
print "%s is done" % filename

up_with_multi_part(file_path, bucket_name, key_name,metadata,policy)

【效果】

1
2
3
4
5
lihongbo01@cld-unknown212867:~/workspace/s3_workspace$ ls
s3sdk.py split_upload.py TCP-IP.pdf TCP-IP.pdf.part.1 TCP-IP.pdf.part.2
lihongbo01@cld-unknown212867:~/workspace/s3_workspace$ s3cmd ls s3://mybucket
2019-06-17 06:29 19132008 s3://mybucket/TCP-IP.pdf
2019-06-14 09:38 1094 s3://mybucket/s3sdk.py

【核心函数】

boto.connect_s3:连接S3
conn.get_bucket:根据name获取bucket
bucket.initiate_multipart_upload:初始化分段上传
boto.utils.compute_md5:计算文件md5值
mpu.upload_part_from_file:上传某一块
mpu.complete_upload():完成上传

【注意】

  1. 除最后一块外每块要大于5MB
  2. bucket要存在
  3. Debug可以根据接口返回的错误信息然后查阅API文档

对象批量删除

将多个对象的删除请求合成一个,降低请求的负载;批量删除之前需要获得这些待删除对象的key(最多一次1000个)。响应:verbose/quiet模式。

批量删除Object(Python版本)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# -*- coding: utf-8 -*-
from boto.s3.connection import S3Connection
import boto
import os

endpoint = 's3.ceph.work' #S3服务的endpoint地址
bucket_name = '' #bucket名称
access_key = '' #access-key
secret_key = '' #secret key

conn = boto.connect_s3(
aws_access_key_id=access_key,
aws_secret_access_key=secret_key,
host=endpoint,
is_secure=False,
calling_format=boto.s3.connection.SubdomainCallingFormat(),
validate_certs=True,
)

bucket = conn.get_bucket(bucket_name) #获取bucket实例
file_list = bucket.get_all_keys(prefix='user1_23695/') #按指定prefix查询bucket中对应的Object列表,注意默认最多返回1000条记录
bucket.delete_keys(file_list) #批量删除Object

【代码示例】

1
2
3
bucket = conn.get_bucket(bucket_name) # 获取bucket实例
file_list = bucket.get_all_keys(prefix='TCP') # 按指定prefix查询bucket中对应的Object列表,注意默认最多返回1000条记录
bucket.delete_keys(file_list) # 批量删除Object

【效果】

1
2
3
4
5
6
7
8
lihongbo01@cld-unknown212867:~/workspace/s3_workspace$ s3cmd ls s3://mybucket
2019-06-17 06:29 19132008 s3://mybucket/TCP-IP.pdf
2019-06-17 06:42 9566004 s3://mybucket/TCP-IP.pdf.part.1
2019-06-17 06:43 9566004 s3://mybucket/TCP-IP.pdf.part.2
2019-06-14 09:38 1094 s3://mybucket/s3sdk.py
lihongbo01@cld-unknown212867:~/workspace/s3_workspace$ python batch_delete.py
lihongbo01@cld-unknown212867:~/workspace/s3_workspace$ s3cmd ls s3://mybucket
2019-06-14 09:38 1094 s3://mybucket/s3sdk.py

【核心函数】

bucket.delete_keys(file_list):批量删除Object

删除Buekct时先批量删除Object
1
2
3
4
5
6
7
lihongbo01@cld-unknown212867:~/workspace/s3_workspace$ s3cmd rb s3://mybucket --force --recursive
WARNING: Bucket is not empty. Removing all the objects from it first. This may take some time...
delete: 's3://mybucket/in/mybucket/s3sdk.py'
delete: 's3://mybucket/s3sdk-in-mybucket.py'
Bucket 's3://mybucket/' removed
lihongbo01@cld-unknown212867:~/workspace/s3_workspace$ s3cmd ls s3://
lihongbo01@cld-unknown212867:~/workspace/s3_workspace$

s3cmd rm s3://mybucket –recursive:清空桶(批量删除,支持前缀匹配)

获取对象列表

支持使用前缀

1
file_list = bucket.get_all_keys(prefix='user1_23695/')

【代码示例】

1
2
bucket = conn.get_bucket(bucket_name) #获取bucket实例
file_list = bucket.get_all_keys(prefix='TCP') #按指定prefix查询bucket中对应的Object列表,注意默认最多返回1000条记录

【效果】

1
2
3
4
5
6
7
lihongbo01@cld-unknown212867:~/workspace/s3_workspace$ python list_key.py 
[<Key: mybucket,TCP-IP.pdf>, <Key: mybucket,TCP-IP.pdf.part.1>, <Key: mybucket,TCP-IP.pdf.part.2>]

## 带有目录包含着前缀(in)
lihongbo01@cld-unknown212867:~/workspace/s3_workspace$ python list_key.py
[<Key: mybucket,in.py>, <Key: mybucket,in/s3sdk.py>]
lihongbo01@cld-unknown212867:~/workspace/s3_workspace$

返回的是一个ResultSet,接口可以参考:http://boto.cloudhackers.com/en/latest/ref/s3.html

【核心函数】

bucket.get_all_keys:获取所有键值

S3版本控制与生命周期

Posted on 2019-07-08

S3版本控制与生命周期

版本控制

存储桶可以处于三种状态之一:非(无)版本化(默认),启用版本控制或暂停版本控制。通过启用了版本控制的存储桶可以恢复因意外删除或覆盖操作而失去的对象。例如:

  • 如果删除对象(而不是永久移除它),则 Amazon S3 会插入删除标记,该标记将成为当前对象版本。通过回滚可以恢复到以前的版本。
  • 如果覆盖对象,则会导致存储桶中出现新的对象版本。通过回滚可以恢复到以前的版本。

一旦您对存储桶启用了版本控制,它将无法返回到无版本控制状态。但是,您可以在该存储桶上暂停版本控制。

版本控制状态将应用到该存储桶中的所有(不是某些)对象。您第一次对存储桶启用版本控制后,该存储桶中的对象将在之后一直受版本控制,并具有唯一的版本 ID。在您设置版本控制状态之前存储在存储桶中的对象具有版本 ID null。启用版本控制时,存储桶中的现有对象不会更改。更改的是 Amazon S3 在以后的请求中处理这些对象的方式。 存储桶拥有者(或任何具有适当权限的用户)可以暂停版本控制以停止累积对象版本。暂停版本控制时,存储桶中的现有对象不会更改。更改的是 Amazon S3 在以后的请求中处理对象的方式。

改变不了之前,只能影响后面的处理

在启用版本控制后,简单的DELETE无法永久删除对象,只是标记一下而已,要永久删除必须制定版本。

生命周期

S3支持通过以配置的形式实现对象的生命周期管理,主要应用在以下两种场景:

  • 如果你需要定期清理S3中的对象数据,可以设置相应的对象生命周期策略,实现对象的定期有计划删除。
  • 如果一些对象数据在一段限定的时间内需要频繁访问,之后这些不再需要访问,可以通过指定对象的生命周期策略,实现后台存储数据从热存储向冷存储(存储成本更低)的自动迁移,从而降低存储成本。

S3(Simple Storage Service)对象存储简介及使用

Posted on 2019-07-08

S3(Simple Storage Service)对象存储简介及使用

什么是S3服务

S3是一套基于HTTP协议并采用RESTful风格构建起来的Web存储管理服务

S3的一些特点

  • 存储桶是S3用于数据存储的基础容器
  • 存储桶中可以存储无限量的数据,每个对象最多5TB数据,使用开发人员分配的唯一密钥存储和检索每个对象
  • 身份验证机制
  • 访问接口使用基于标准的REST和SOAP接口,可以与任何Internet开发工具搭配使用

S3基本存储模型

两种存储单元:Bucket和Object,扁平化存储结构,可以横向增加Bucket和Object,理论上可以存储无数个Object。

  • 对象(Object)

S3存储的最小单位,数据不透明,元数据透明,数据和元数据一起存,还可以指定自定义元数据。在存储桶中,对象将由密钥(名称)和版本 ID 进行唯一地标识。

  • 存储桶(Bucket)

存储对象的容器,名称要全局唯一,并且命名需要符合英文国际域名的命名规则。对象名为mybucket组成的URL为http://mybucket.s3.cephbook.com。

传统文件系统向S3的转变

  • 文件路径和数据存储
  • 文件元数据存储
解决文件路径和数据存储

  • 所有数据都存放在Bucket中,文件都是Object。

个人理解文件夹不需要管,在路径中直接用”/“区分就行了(这个分割符可以指定),因此也没有了文件夹的元数据信息。目录样式演示是模拟出来的对象的层次结构。删除目录可以理解为删除具有该前缀的所有对象。

1
2
3
4
5
6
lihongbo01@cld-unknown212867:~/workspace/s3_workspace$ s3cmd ls s3://mybucket/in
DIR s3://mybucket/in/
lihongbo01@cld-unknown212867:~/workspace/s3_workspace$ s3cmd ls s3://mybucket/in/mybucket
DIR s3://mybucket/in/mybucket/
lihongbo01@cld-unknown212867:~/workspace/s3_workspace$ s3cmd ls s3://mybucket/in/mybucket/s3sdk.py
2019-06-17 07:05 1094 s3://mybucket/in/mybucket/s3sdk.py
  • 在key name中加上”/”来区分“文件夹”。
  • 文件数据内容作为Content存储在Object内。
解决文件元数据存储

两种存储的元数据对应关系:

  • key name -> 文件路径
  • etag -> 文件md5
  • metadata(File size, Last mode, MIME type) -> 文件的size/x-time这些
  • ACL -> 文件的acl/uid/gid这些
  • Content-Type -> MIME

MIME用于设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。

S3的使用

s3cmd 命令行形式访问(连接到其他第三方S3服务为例)

安装
pip install s3cmd

默认s3cmd会读取当前用户的$HOME/.s3cfg,可以使用-c参数手工指定配置文件路径。

配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[default]
access_key = XXXXXXX # 填写access_key
secret_key = XXXXXXX # 填写secret_key
default_mime_type = binary/octet-stream
enable_multipart = True # 启动分块上传
encoding = UTF-8
encrypt = False
host_base = s3dev.nie.netease.com # 接入点
host_bucket = %(bucket)s.s3dev.nie.netease.com
multipart_chunk_size_mb = 15 # 分块上传大小
socket_timeout = 300 # 超时时长
stop_on_error = False
use_https = False # 是否使用HTTPs
use_mime_magic = True
verbosity = WARNING
signature_v2 = True # 强制使用AWS2签名认证
使用实例

s3cmd –help 查看帮助

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
lihongbo01@cld-unknown212867:~/workspace$ s3cmd ls
lihongbo01@cld-unknown212867:~/workspace$ s3cmd mb s3://mybucket
Bucket 's3://mybucket/' created
lihongbo01@cld-unknown212867:~/workspace$ s3cmd rb s3://mybucket
Bucket 's3://mybucket/' removed
lihongbo01@cld-unknown212867:~/workspace$ s3cmd mb s3://mybucket
Bucket 's3://mybucket/' created
lihongbo01@cld-unknown212867:~/workspace$ s3cmd put hello.lua s3://mybucket
upload: 'hello.lua' -> 's3://mybucket/hello.lua' [1 of 1]
15 of 15 100% in 0s 120.37 B/s done
lihongbo01@cld-unknown212867:~/workspace$ s3cmd rb s3://mybucket
ERROR: S3 error: 409 (BucketNotEmpty) # rb是删除空bucket,加--force可以删除(未启用版本控制)
lihongbo01@cld-unknown212867:~/workspace$ s3cmd del s3://mybucket
ERROR: Parameter problem: File name required, not only the bucket name. Alternatively use --recursive
lihongbo01@cld-unknown212867:~/workspace$ s3cmd del s3://mybucket/hello.lua
delete: 's3://mybucket/hello.lua'
lihongbo01@cld-unknown212867:~/workspace$ s3cmd ls s3://mybucket
lihongbo01@cld-unknown212867:~/workspace$

其他常用命令如:

s3cmd get s3://new_bucket/file # 下载file到本地
s3cmd setacl s3://new_bucket/file --acl-public # 开启file的匿名访问权限,注意权限控制
s3cmd info s3://new_bucket/file # 查看object属性信息
s3cmd del s3://new_bucket --recursive --force # 递归删除bucket内的所有内容,慎用!
s3cmd signurl s3://new_bucket/file +30 # 生成临时的url访问链接(30s有效时长)。
s3cmd du s3://new_bucket # 查看bucket的信息
s3cmd cp src dst # 复制
s3cmd mv src dst # 移动

Python SDK使用S3

安装
pip install boto

boto 适用于Python 2.6 and 2.7环境,python 3.x推荐使用boto3

新建、删除bucket实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# -*- coding: utf-8 -*-
from boto.s3.connection import S3Connection
import boto
import os

# 开启下面则启用AWS4认证,默认使用AWS2
# os.environ['S3_USE_SIGV4'] = 'True'

endpoint = 's3dev.nie.netease.com' #S3服务的endpoint地址
bucket_name = 'mk_by_python' #bucket名称
access_key = 'XXXXXXX' #access-key
secret_key = 'XXXXXXX' #secret key

conn = boto.connect_s3(
aws_access_key_id=access_key,
aws_secret_access_key=secret_key,
host=endpoint,
is_secure=False, #不使用HTTPS
calling_format=boto.s3.connection.SubdomainCallingFormat(), #使用virtual-hosted-style,推荐使用
# calling_format=boto.s3.connection.OrdinaryCallingFormat(), #使用path-style
validate_certs=True,
)

buckets = conn.get_all_buckets() #获取当前bucket列表
print buckets
bucket = conn.create_bucket(bucket_name) #新建bucket
buckets = conn.get_all_buckets() #获取当前bucket列表
print buckets
conn.delete_bucket(bucket_name) #删除bucket
buckets = conn.get_all_buckets()
print buckets

输出

1
2
3
4
5
lihongbo01@cld-unknown212867:~/workspace/s3_workspace$ python s3sdk.py 
[<Bucket: mybucket>]
[<Bucket: mk_by_python>, <Bucket: mybucket>]
[<Bucket: mybucket>]
lihongbo01@cld-unknown212867:~/workspace/s3_workspace$
Python接口

bucket相关

1
2
3
4
5
6
7
8
conn.create_bucket(bucket_name)  # 新建bucket
conn.get_all_buckets() # 获取当前bucket列表
conn.delete_bucket(bucket_name) # 删除bucket
bucket.get_acl() # 获取bucket ACL
bucket.get_xml_acl() # 获取bucket ACL的xml格式描述
bucket.set_acl('private') # 设置bucket ACL,可以选:private,public-read,public-read-write,authenticated-read这些
bucket.set_xml_acl(xml_acl) # 以XML格式进行设置
bucket.add_user_grant('WRITE','test1') # 对‘test1’这个用户赋予‘WRITE’权限 # bucket新增用户ACL,可选:READ, WRITE, READ_ACP, WRITE_ACP, FULL_CONTROL

object相关

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
key_ = bucket.new_key(key_name)  # 生成一个key
key_.set_contents_from_filename(local_file) # 上传文件 [与上一条命令一起用]
# 两种删除方式
key_.delete()
bucket.delete_key(key_name)
bucket.get_all_keys(prefix='user1_23695/') # 按指定prefix查询bucket中对应的Object列表,注意默认最多返回1000条记录
bucket.delete_keys(file_list) # 批量删除Object
key_.get_xml_acl() # 获取XML格式的Object的ACL信息
key_.get_acl() # 获取Object的ACL
key_.set_acl('public-read') # 方式1,设置Object的ACL
key_.set_canned_acl('public-read') # 方式2,设置Object的ACL
key_.set_xml_acl(acl_xml) # 方式3,设置Object的ACL
key_.add_user_grant('READ','test1') # 对‘test1’这个用户添加READ权限。 #添加用户授权,可选权限有:READ, WRITE, READ_ACP, WRITE_ACP, FULL_CONTROL
key_.set_metadata('key','value') # 设置Object的metadata,注意必须在上传Object之前做好初始化设置
#获取Object的metadata
key_ = bucket.get_key(key_name)
print key_.get_metadata('key')
key_.get_contents_to_filename(down_file) # 下载Object,保存为本地的‘/tmp/download.file’
123

hb-lee

30 posts
© 2020 hb-lee
Powered by Hexo
|
Theme — NexT.Muse v5.1.4