Permalink
cbb7432 Aug 4, 2017
3 contributors

Users who have contributed to this file

@jemygraw @TianZong48 @loyachen
326 lines (222 sloc) 21.7 KB

简介

qupload是用来将本地目录中的文件同步到七牛空间中的命令。

格式

qshell qupload [<ThreadCount>] <LocalUploadConfig>

鉴权

需要在使用了account设置了AccessKeySecretKey的情况下使用。

参数

参数名 描述 可选参数
ThreadCount 并发上传的协程数量,默认为1,即文件一个个上传,对于大量小文件来说,可以通过提高该参数值来提升同步速度 Y
LocalUploadConfig 数据同步的配置文件,该配置文件里面包含了一些诸如本地同步目录,目标空间名称等信息,详情参考配置文件的讲解 N

关于 ThreadCount 的值,并不是越大越好,所以工具里面限制了范围 [1, 2000],在实际情况下最好根据所拥有的上传带宽和文件的平均大小来计算下这个并发数,最简单的算法就是带宽除以平均文件大小即可得到并发数。

假设上传带宽有10Mbps,文件平均大小500KB,那么利用 10*1024/8/500 = 2.56,那么并发数差不多就是 3-6 左右。

配置

qupload 功能需要配置文件的支持,配置文件支持的全部参数如下:

{
   "src_dir"            :   "<LocalPath>",
   "bucket"             :   "<Bucket>",
   "file_list"          :   "<FileList>",
   "key_prefix"         :   "<Key Prefix>",
   "up_host"            :   "<Upload Host>",
   "ignore_dir"         :   false,
   "overwrite"          :   false,
   "check_exists"       :   false,
   "check_hash"         :   false,
   "check_size"         :   false,
   "rescan_local"       :   true,
   "skip_file_prefixes" :   "test,demo,",
   "skip_path_prefixes" :   "hello/,temp/",
   "skip_fixed_strings" :   ".svn,.git",
   "skip_suffixes"      :   ".DS_Store,.exe",
   "log_file"           :   "upload.log",
   "log_level"          :   "info",
   "log_rotate"         :   1,
   "log_stdout"         :   false,
   "file_type"          :   0
}
参数名 描述 可选参数
src_dir 本地同步路径,为全路径格式,工具将同步该目录下面所有的文件;在Windows系统下面使用的时候,注意src_dir的设置遵循D:\\jemy\\backup这种方式。也就是路径里面的\要有两个(\\ N
bucket 同步数据的目标空间名称,可以为公开空间或私有空间 N
file_list 待同步文件列表,该文件列表内容必须是相对于src_dir的文件相对路径列表,可以不指定,工具将自动获取src_dir下面的文件列表。请使用 dircache 命令生成这个文件列表,生成之后可以手动删除不需要的行 Y
up_host 上传域名,可选设置,一般情况下不需要指定 Y
ignore_dir 保存文件在七牛空间时,使用的文件名是否忽略本地路径,默认为false Y
key_prefix 在保存文件在七牛空间时,使用的文件名的前缀,默认为空字符串 Y
overwrite 是否覆盖空间中已有的同名文件,默认不覆盖。 Y
check_exists 每个文件上传之前是否检查空间中是否存在同名文件,默认为false,不检查 Y
check_hash check_exists设置为true的情况下生效,是否检查本地文件hash和空间文件hash一致,默认不检查,节约同步时间 Y
check_size check_exists设置为true的情况下,如果check_hashfalse,那么你可以设置check_sizetrue做简单的大小检查,以查看本地文件和空间文件大小是否一致,默认不检查 Y
skip_file_prefixes 跳过所有文件名(不带相对路径)以该前缀列表里面字符串为前缀的文件 Y
skip_path_prefixes 跳过所有文件路径(相对路径)以该前缀列表里面字符串为前缀的文件 Y
skip_fixed_strings 跳过所有文件路径(相对路径)中包含该字符串列表中字符串的文件 Y
skip_suffixes 跳过所有以该后缀列表里面字符串为后缀的文件或者目录 Y
rescan_local 默认情况下,本地新增的文件不会被同步,需要手动设置为true才会去检测新增文件。 Y
log_level 上传日志输出级别,可选值为debug,info,warn,error,默认info Y
log_file 上传日志的输出文件,如果不指定会输出到qshell工作目录下默认的文件中,文件名可以在终端输出看到 Y
log_rotate 上传日志文件的切换周期,单位为天,默认为1天即切换到新的上传日志文件 Y
log_stdout 上传日志是否同时输出一份到标准终端,默认为false,主要在调试上传功能时可以指定为true Y
file_type 文件存储类型,默认为0(标准存储) 1为低频存储 Y
delete_on_success 上传成功的文件,同时删除本地文件,以达到节约磁盘的目的,比如日志归档的场景,默认为false,如果需要开启功能,设置为true即可。 Y

对于那么多的参数,我们可以分为几类来解释:

讲解

最基本的上传功能和必须要指定的参数

{
  "src_dir" : "xxx",
  "bucket" : "xxx"
}

最基本的参数就是上面的这几个,分别为本地待上传的目录,上传的目标空间,指定这两个参数就可以将一个本地目录中的文件全部同步到空间中去。其余的一些参数,只是同步任务的其他场景下的可选参数。

假设有目录 /Users/jemy/Temp/uptest ,下面的文件结构为:

.
├── 2017
│   ├── 01
│   │   └── 03
│   │       ├── cut1.png
│   │       ├── cut2.png
│   │       ├── demo1.png
│   │       └── demo2.gif
│   ├── cut1.png
│   ├── cut2.png
│   ├── demo1.png
│   └── demo2.gif
├── cut1.png
├── cut2.png
├── demo1.png
└── demo2.gif

文件命名

在上面的目录结构中,我们模拟了一些拥有子目录的情况,这种情况下,如果指定 src_dir/Users/jemy/Temp/uptest ,那么默认上传到七牛空间的文件名都会带上从 src_dir 开始的文件的相对路径作为前缀,即上传的结果为:

2017/01/03/cut1.png
2017/01/03/cut2.png
2017/01/03/demo1.png
2017/01/03/demo2.gif
2017/cut1.png
2017/cut2.png
2017/demo1.png
2017/demo2.gif
cut1.png
cut2.png
demo1.png
demo2.gif

默认上传日志

在上传的过程中,我们把上传的进度信息输出到标准输出,所以你可以看到它们,当然还有就是其他的上传日志信息,如果在不指定 log_file 参数的情况下,会默认写入到上传任务所在的目录中,这个日志文件的路径在上传的终端第一行输出和最后一行输出都可以看到。

Writing upload log to file /Users/jemy/.qshell/qupload/290438bcd0bcc7121bb22a56b1c95926/290438bcd0bcc7121bb22a56b1c95926.log
...
...
See upload log at path /Users/jemy/.qshell/qupload/290438bcd0bcc7121bb22a56b1c95926/290438bcd0bcc7121bb22a56b1c95926.log

处理中断

上面的演示,我们的图片比较少,所以很容易成功,那么在大量文件要上传的情况下,怎么样保证上传完成的文件不再继续上传呢?我们在本地使用了一个 leveldb 数据库用来记录这个已上传成功的文件信息。 这个纪录的格式为 (k, v) => ((localFilePath, uploadFileKey), lastModifyTime),也就是说记录的key为本地文件的路径加上上传到空间中的文件名构成的,而value则是本地文件的最后修改时间,这个用来在下次上传的时候检查文件是否已发生过变化。这个 leveldb 的数据库保存在上传任务的目录之下,每个上传的任务相关的文件都保存在以任务ID命名的目录之下。任务 ID 的生成算法为 MD5(SrcDir+":"+Bucket)。

通过上面的方法,我们在每次上传之前,都会去检查是否已有文件上传成功,如果存在本地文件上传成功的记录,而且本地文件的最后修改时间没有变化的话,我们就认为该文件已上传过了,可以不用再传。

强制覆盖

上面说过我们可以处理中断的上传过程,从中断的地方继续上传,但是这里存在的问题是,在这个中断后的时间里面,本地文件内容是否发生过改变,如果发生过改变该怎么处理的问题?这种情况下,我们会比对文件当前的最后修改时间和 leveldb 数据库中记录的最后修改时间,如果时间不一致,我们认为该文件已被修改。这个时候,你可以指定一个参数 overwrite 来强制覆盖这个文件,否则的话,工具会给一个警告级别的日志信息,并记录为没有覆盖的文件。

{
  "overwrite" : true
}

警告信息:

Skip upload of changed file `xxx` but no overwrite set

overwrite 这个参数设置为 true 的时候,覆盖操作会在两种情况下发生:

(1)本地文件的最后修改时间发生了改变(认为该文件内容已变化),并且在设置了 rescal_localtrue 的情况下;

(2)当开启了 check_exists 选项,发现空间已存在同名文件,而且在 check_hash 或者 check_size 发现文件内容hash或者大小不同的情况下;

总之,当本地文件发生改动的时候,如果你希望将改动后的文件覆盖空间已有的文件,那么请设置 overwritetrue,否则默认情况下,不会去覆盖,因为这个操作很危险。

忽略相对路径

在上面的例子中,我们把相同的文件名都放在了不同的路径之下来演示默认的命名方式,有些情况下,你可能不需要文件名之前带上相对路径,这种情况下,你可以使用 ignore_dir 参数。

{
  "src_dir" : "xxx",
  "bucket" : "xxx",
  "ignore_dir" : true
}

上传的结果为:

cut1.png
cut2.png
demo1.png
demo2.gif

在这个例子中,其实会存在一种情况,A目录下的文件和B目录下的文件同名,但是内容不同,如果设置了 ignore_dirtrue 的话,在A下面的文件先上传成功,B下面的文件后上传的情况下,会演变为是否覆盖空间中同名文件的问题,这种情况下,如果你设置了 overwritetrue 那么就会去覆盖,否则就不去覆盖,参考上面的解释。

指定文件上传前缀

某些情况下,你可能需要为批量上传的文件指定统一的前缀,本工具为这种需求提供了支持,可以通过指定参数 key_prefix 来为上传的文件指定统一的前缀。前缀的添加规则如下:

(1)在没有指定 ignore_dirtrue 的情况下,该前缀附加在文件相对路径的前面,假设待上传到空间的文件名是 2017/01/03/demo1.png ,指定的 key_prefixdemo/,那么最终落在空间中的文件名是 demo/2017/01/03/demo1.png

(2)在指定了 ignore_dirtrue 的情况下,该前缀附加在文件名的前面,假设待上传到空间的文件名是 demo1.png,指定的 key_prefixdemo/,那么最终落在空间中的文件名是 demo/demo1.png

默认的上传入口

很多情况下,该工具的使用者的网络和七牛的网络都不是在一个内网,或者是机房或者是普通的办公网络和家庭网络。这种情况下,为了保证上传的速度和效率,必须走加速上传通道。目前本工具中使用的空间所在机房和对应的上传加速域名如下表:

机房 上传加速域名
华东 http://upload.qiniu.com
华北 http://upload-z1.qiniu.com
华南 http://upload-z2.qiniu.com
北美 http://upload-na0.qiniu.com

本工具会根据配置文件中指定的空间参数,自动获取所应该使用的默认加速域名,所以不需要担心是否需要额外设置上传域名。

指定上传入口

有些情况下,你可能想自己指定上传的入口域名,工具也为这种需求提供了参数 up_host,你可以自行指定上传的域名来从这个入口上传文件。当然你需要根据空间所在的机房选择正确的上传入口域名,可选的域名列表如下:

机房 上传加速域名 源站上传域名 https上传加速域名 https上传源站域名
华东 http://upload.qiniu.com http://up.qiniu.com https://upload.qbox.me https://up.qbox.me
华北 http://upload-z1.qiniu.com http://up-z1.qiniu.com https://upload-z1.qbox.me https://up-z1.qbox.me
华南 http://upload-z2.qiniu.com http://up-z2.qiniu.com https://upload-z2.qbox.me https://up-z2.qbox.me
北美 http://upload-na0.qiniu.com http://up-na0.qiniu.com https://upload-na0.qbox.me https://up-na0.qbox.me

一般来说,如果你的网络是机房网络,而且带宽比较大,那么可以选择七牛的源站上传域名来上传,否则都选择上传加速域名即可。

跳过特定字符匹配的文件不上传

某些情况下,我们可能需要跳过某些文件或者目录不上传,比如 .git 或者 .svn 目录或者 Mac 下的 .DS_Store 文件等。本工具提供了4种根据文件名中字符串匹配的方式来跳过这些文件或者目录。

这4种参数,每种都可以指定多个值,每个值之间通过英文逗号( , )来分隔。特别提示,由于 qupload 中待上传的文件列表,都是相对于 src_dir 的相对路径,所以我们下面所说的文件名或者路径都默认不带 src_dir 前缀。

(1)参数 skip_file_prefixes 可以忽略所有文件名(不带相对路径的文件名)以该参数中指定的字符串为前缀的文件。比如对于文件路径 2017/01/03/demo1.png ,我们取出 demo1.png 来进行检查,如果 skip_file_prefixes 里面指定忽略前缀 demo ,那么这个文件就会跳过不上传;

(2)参数 skip_path_prefixes 可以忽略所有文件路径(带相对路径的文件名)以该参数中指定的字符串为前缀的文件。比如对于文件路径 2017/01/03/demo1.png ,我们检查这个文件路径是否有以 skip_path_prefixes 中指定的字符串为前缀,如果是的话,那么这个文件就会跳过不上传;

(3)参数 skip_fixed_strings 可以忽略所有文件路径中存在该参数中指定的字符串的文件。比如对于文件路径 2017/01/03/demo1.png,在 skip_fixed_strings 设置了 2017,2018的情况下,因为该文件路径出现了字符串 2017,所以会被跳过不上传;

(4)参数 skip_suffixes 可以忽略所有文件路径以该参数中指定的字符串为结尾的文件。比如如果我们想忽略图片文件不上传,我们可以设置 skip_suffixes.png,.jpg,.gif,那么上面的文件 2017/01/03/demo1.png 就会被跳过不上传。

检查空间是否已有同名文件

在某些情况下,我们在上传文件之前,可能需要先去检查下空间是否已存在同名的文件。如果存在的话,可能不再上传;也有可能再判断下是否内容相同或者文件大小相同,如果不同再上传。

我们提供了 check_existscheck_hashcheck_size 三个额外的参数来支持该功能。其中 check_hashcheck_size 在设置了 check_existstrue 的情况下,才生效。

(1)当设置了 check_existstrue 的情况下,工具不再检查本地的 leveldb 数据库该文件是否已上传成功,而是去查询空间中是否存在同名文件。

(2)如果发现空间中已存在同名文件,并且 check_hashcheck_size 都设置为 false 的情况下,那么工具认为该文件已上传成功,无需再传。

(3)如果上面指定了 check_hash 或者 check_sizetrue 的话,会进行进一步的检查,其中优先使用 check_hash 选项,该选项会将从空间获取的文件hash和本地计算得到的文件hash进行比较,如果相同,则认为该文件已上传成功,无需再传。

(4)当 check_hash 没有设置或者设置为 false 的情况下,才去检查 check_size 是否设置为 true,如果设置为 true,则比较空间中获取的文件大小和本地文件的大小,如果大小相同,则认为该文件已上传成功,无需再传。

上面的这些检查,当认为该文件已上传成功,无需再传的时候,都会去同时更新 leveldb 数据库,记录下这个状态。

当我们思考如何设置上面的选项的时候,我们只需要根据几个场景来进行选择即可:

(1)待同步的文件是否存在从多个地方进行同步的情况,并且这种情况下之后,是否会存在同名文件?如果存在,那么可以设置 check_existstrue

(2)在第(1)步确认之后,我们再想一下,多个地方存在的这些同名文件,是否内容是相同的,如果相同,那么我们就可以不再考虑设置 check_hashcheck_size

(3)如果进行到了第(3)步,那么肯定存在文件名相同,但是内容不同的情况,这个时候为了提升上传的检查效率,我们区分一下检查方式只是简单地比对下文件大小还是去根据内容进行比较,即计算文件的hash值进行比较。很显然,计算文件的hash值进行比较,是需要将文件内容加载到内存进行计算,对于大文件例如视频文件,这种方式的效率肯定不如检查文件大小。所以第(3)步里面选择 check_hash 还是 check_size 设置为 true,根据实际需要进行吧。当同时设置了 check_hashcheck_sizetrue 的情况下,优先检查文件的hash而不是文件大小。

上传日志文件

上面我们讲解过默认日志文件的内容,默认日志文件的日志级别是INFO,保存在以上传任务ID命名的目录之下,通过终端输出的方式告诉你日志文件的所在位置。这个主要是避免有些用户着急上传,然后遇到问题难以调查,所以工具默认写入一个日志文件,方便后面协查问题。

当然,你也可以自行指定日志文件的级别和保存的文件路径。工具提供了 log_levellog_file 两个参数选项来支持这种设置。

log_level 的可选值依次为 debuginfowarnerror,不指定的情况下,默认为 info 级别的日志。

log_file 的值为日志保存的文件路径,可以指定任意一个使用者拥有写入权限的文件。

过滤上传文件列表

有些情况下,我们希望能上传指定的文件列表,比如遇到上面的跳过规则无法覆盖的场合或者是其他的情况,这种情况下,我们可以指定 file_list 参数来上传指定的文件列表。这个 file_list 参数所指定的文件列表必须使用 dir_cache 命令来生成,你可以对这个生成的列表进行删除操作,删除掉不需要上传的文件。

增量上传的支持

增量上传主要解决两个问题,第一就是文件的新增,第二就是文件的内容已改动。这两种情况下,需要设置参数 rescan_localtrue 去重新获取本地目录下的文件列表信息,然后再同步。默认情况下这个参数设置为 false,也就是说如果本地目录不存在文件的更新操作,那么如果上传中断的话,会使用上一次完整获取的文件列表。之所以这样做,是因为对于海量的数据同步,获取一次完整的文件列表也是十分耗费时间的。

目前该工具支持增量上传的方式,仍然是重新运行上传命令,尚不支持后台常驻,自动检测更新进行同步的功能。

本地删除操作同步

目前尚不支持本地文件删除,同步删除空间中的文件的操作。因为很多情况下,这个操作十分危险,如果需要批量删除空间中的文件的话,可以使用本工具的 batchdelete

文件归档的同步

对于某些场景下,比如日志的归档,可能需要在文件上传成功之后,需要删除本地磁盘上面的文件以达到节约空间的目的。默认情况下,该功能是禁用状态,可以开启delete_on_success选项来支持该功能。

高级用法

导出上传的文件列表

对于上传的文件,我们可以导出各个结果的列表,所以qupload额外支持三个命令行选项参数,分别是:success-listfailure-listoverwrite-list

其中 success-list 表示所有上传成功的文件列表,而failure-list则表示所有上传失败的文件列表。另外overwrite-list表示所有上传是覆盖了空间已有文件的列表,这个列表的意义在于可以用来拼接CDN的域名,进行CDN资源的刷新操作,以及时更新节点文件。

命令格式:

$ qshell qupload -success-list success.txt upload.conf 

特别提示:由于这些选项所指定的文件在每次运行命令时,如果文件已存在,则已有内容会被清空然后写入新的内容,所以注意每次命令运行指定不同的文件。

绑定网卡IP上传

如果本地机器有多个网卡,比如一般的服务器可能同时安装了两块网卡,我们希望所有的上传流量都走其中的一块网卡。那么这种情况下,我们可以使用ipconfig或者ifconfig来查看本地网卡的IP地址。其中 ipconfig 是 Windows 系统下的命令,而 ifconfig 是 Linux 或者 Mac 系统下的命令,都可以用来查看本地网卡的IP地址。

在获取到本地网卡的IP地址后,可以设置配置文件中的选项 bind_nic_ip 来将网卡IP写入到配置中,这样所有的文件上传流量都会走这个网卡。

绑定域名对应IP

我们支持上传域名和资源管理域名指定IP上传。分别由选项 bind_up_ipbind_rs_ip 来支持,这种情况一般用于私有云部署或者是其他特殊场景下使用,比如内网或者专线上传。