From cd2b7412a8d8cafd6b285ab0e6cd94ac77c5f09f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E5=8A=A0=E5=BC=BA?= Date: Fri, 16 Nov 2018 12:02:14 +0800 Subject: [PATCH 01/20] change version and download link --- README.md | 2 +- cmd/version.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f6ab6bc8..1cdc2b4d 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ qshell是利用[七牛文档上公开的API](http://developer.qiniu.com)实现 |版本 |支持平台|链接| |--------|---------|----| -|qshell-v2.3.2-bugfix |Mac OSX, Linux, Windows|[下载](http://devtools.qiniu.com/qshell-bugfix.zip)| +|qshell-v2.3.2-develop |Mac OSX, Linux, Windows|[下载](http://devtools.qiniu.com/qshell-develop.zip)| ## 安装 diff --git a/cmd/version.go b/cmd/version.go index 26754fe0..aeb9c5c0 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -6,7 +6,7 @@ import ( "runtime" ) -var version = "v2.3.2-bugfix" +var version = "v2.3.2-develop" var versionCmd = &cobra.Command{ Use: "version", From dbcaf88b4d27bd72e6e5d01e22e8343a24e16823 Mon Sep 17 00:00:00 2001 From: Tony Cai Date: Mon, 19 Nov 2018 16:18:22 +0800 Subject: [PATCH 02/20] =?UTF-8?q?=E4=BF=AE=E6=94=B9docs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/cdnrefresh.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/cdnrefresh.md b/docs/cdnrefresh.md index 92055ab5..5461fdd3 100644 --- a/docs/cdnrefresh.md +++ b/docs/cdnrefresh.md @@ -13,7 +13,7 @@ qshell cdnrefresh [-i ] 刷新目录的命令格式: ``` -qshell cdnrefresh --dirs +qshell cdnrefresh --dirs -i ``` 注意需要刷新的目录,必须以`/`结尾。如果没有制定输入文件默认从终端读取输入内容 From 000977dd65e122dc8618a68cceb838a9ad4a076e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E5=8A=A0=E5=BC=BA?= Date: Tue, 27 Nov 2018 09:27:33 +0800 Subject: [PATCH 03/20] capture CTRL-C in listbucket2 to printout marker if not empty --- iqshell/list_bucket.go | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/iqshell/list_bucket.go b/iqshell/list_bucket.go index 7f863160..b291bef5 100644 --- a/iqshell/list_bucket.go +++ b/iqshell/list_bucket.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/astaxie/beego/logs" "os" + "os/signal" "strings" "time" ) @@ -60,6 +61,20 @@ func (m *BucketManager) ListFiles(bucket, prefix, marker, listResultFile string) } func (m *BucketManager) ListBucket2(bucket, prefix, marker, listResultFile, delimiter string, startDate, endDate time.Time, suffixes []string, maxRetry int) (retErr error) { + lastMarker := marker + + sigChan := make(chan os.Signal, 1) + + signal.Notify(sigChan, os.Interrupt) + + go func() { + for sig := range sigChan { + if lastMarker != "" { + fmt.Println("Marker: ", lastMarker) + } + } + }() + if maxRetry <= 0 { retErr = fmt.Errorf("maxRetry must be greater than 0") return @@ -82,7 +97,6 @@ func (m *BucketManager) ListBucket2(bucket, prefix, marker, listResultFile, deli bWriter := bufio.NewWriter(listResultFh) - lastMarker := marker notfilterTime := startDate.IsZero() && endDate.IsZero() notfilterSuffix := len(suffixes) == 0 @@ -152,6 +166,7 @@ func (m *BucketManager) ListBucket2(bucket, prefix, marker, listResultFile, deli marker = lastMarker } } + if lastMarker != "" { fmt.Println("Marker: ", lastMarker) } From 137fc85ba4f9f24e62657537325f11bd86189f4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E5=8A=A0=E5=BC=BA?= Date: Tue, 27 Nov 2018 10:00:25 +0800 Subject: [PATCH 04/20] caputre CTR-C in listbucket(2) --- CHANGELOG.md | 3 +++ iqshell/list_bucket.go | 13 ++++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6929920f..f7afe195 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +# 2.3.4 +1. listbucket, listbucket2增加捕捉interrupt信号(CTR-C), 打印marker + # 2.3.3 1. 修复qdownload配置cdn_domain使用了测试域名作为HOST 引起超过10G流量限制的问题 2. listbucket2 max-retry选项只限制出错下载次数,不限制接口返回空的次数 diff --git a/iqshell/list_bucket.go b/iqshell/list_bucket.go index b291bef5..d2e4827f 100644 --- a/iqshell/list_bucket.go +++ b/iqshell/list_bucket.go @@ -2,6 +2,7 @@ package iqshell import ( "bufio" + "context" "fmt" "github.com/astaxie/beego/logs" "os" @@ -64,14 +65,16 @@ func (m *BucketManager) ListBucket2(bucket, prefix, marker, listResultFile, deli lastMarker := marker sigChan := make(chan os.Signal, 1) + ctx, cancel := context.WithCancel(context.Background()) signal.Notify(sigChan, os.Interrupt) go func() { - for sig := range sigChan { - if lastMarker != "" { - fmt.Println("Marker: ", lastMarker) - } + <-sigChan + cancel() + maxRetry = 0 + if lastMarker != "" { + fmt.Println("Marker: ", lastMarker) } }() @@ -101,7 +104,7 @@ func (m *BucketManager) ListBucket2(bucket, prefix, marker, listResultFile, deli notfilterSuffix := len(suffixes) == 0 for c := 0; c < maxRetry; { - entries, lErr := m.ListBucket(bucket, prefix, delimiter, marker) + entries, lErr := m.ListBucketContext(ctx, bucket, prefix, delimiter, marker) if entries == nil && lErr == nil { // no data From 2035978424388d32ef1fe969d57ab329c7c88435 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E5=8A=A0=E5=BC=BA?= Date: Tue, 27 Nov 2018 10:11:54 +0800 Subject: [PATCH 05/20] =?UTF-8?q?=E9=81=BF=E5=85=8D=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E6=89=93=E5=8D=B0marker?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iqshell/list_bucket.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/iqshell/list_bucket.go b/iqshell/list_bucket.go index d2e4827f..0d1e9ffd 100644 --- a/iqshell/list_bucket.go +++ b/iqshell/list_bucket.go @@ -70,12 +70,10 @@ func (m *BucketManager) ListBucket2(bucket, prefix, marker, listResultFile, deli signal.Notify(sigChan, os.Interrupt) go func() { + // 捕捉Ctrl-C, 退出下面列举的循环 <-sigChan cancel() maxRetry = 0 - if lastMarker != "" { - fmt.Println("Marker: ", lastMarker) - } }() if maxRetry <= 0 { From e8911f7cb8269971fd6d2d2e19ce6b02e5868fe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E5=8A=A0=E5=BC=BA?= Date: Tue, 27 Nov 2018 11:53:30 +0800 Subject: [PATCH 06/20] imporove docs --- README.md | 5 +++-- cmd/version.go | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 56c1ca9c..3336a581 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ qshell是利用[七牛文档上公开的API](http://developer.qiniu.com)实现 |版本 |支持平台|链接| |--------|---------|----| -|qshell-v2.3.3-develop |Mac OSX, Linux, Windows|[下载](http://devtools.qiniu.com/qshell-develop.zip)| +|qshell-v2.3.4 |Mac OSX, Linux, Windows|[下载](http://devtools.qiniu.com/qshell-develop.zip)| ## 安装 @@ -69,7 +69,8 @@ $ qshell account $ qshell account -- ``` -可以连续使用qshell account 添加账号ak, sk, name信息,qshell会保存这些账号的信息, 可以使用qshell user命令列举账号信息,在各个账号之间切换, 删除账号等 +可以连续使用qshell account 添加账号ak, sk, name信息,qshell会保存这些账号的信息, 可以使用qshell user命令列举账号信息,在各个账号之间切换, 删除账号等。 +如果使用的2.3.0之前的版本account命令记录的账户信息,需要先使用qshell user clean清楚保存的账户信息,然后使用qshell account命令重新记录账户信息。 2. 添加完账户后,就可以使用qshell上传,下载文件了 diff --git a/cmd/version.go b/cmd/version.go index a9cd61b7..cb8d7667 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -6,7 +6,7 @@ import ( "runtime" ) -var version = "v2.3.3-develop" +var version = "v2.3.4" var versionCmd = &cobra.Command{ Use: "version", From 3504b1dec7ed3bf727879fee95419d3ede9bdf7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E5=8A=A0=E5=BC=BA?= Date: Wed, 28 Nov 2018 18:09:46 +0800 Subject: [PATCH 07/20] =?UTF-8?q?=E5=AE=8C=E5=96=84listbucket2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/rs.go | 6 +----- go.mod | 2 +- go.sum | 4 ++-- iqshell/list_bucket.go | 23 +++++++++++++++-------- 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/cmd/rs.go b/cmd/rs.go index 2ffe5058..64a602fe 100644 --- a/cmd/rs.go +++ b/cmd/rs.go @@ -144,7 +144,7 @@ func init() { lsBucketCmd2.Flags().StringVarP(&listMarker, "marker", "m", "", "list marker") lsBucketCmd2.Flags().StringVarP(&prefix, "prefix", "p", "", "list by prefix") lsBucketCmd2.Flags().StringVarP(&suffixes, "suffixes", "q", "", "list by key suffixes, separated by comma") - lsBucketCmd2.Flags().IntVarP(&maxRetry, "max-retry", "x", 20, "max retries when error occurred") + lsBucketCmd2.Flags().IntVarP(&maxRetry, "max-retry", "x", -1, "max retries when error occurred") lsBucketCmd2.Flags().StringVarP(&outFile, "out", "o", "", "output file") lsBucketCmd2.Flags().StringVarP(&startDate, "start", "s", "", "start date with format yyyy-mm-dd-hh-MM-ss") lsBucketCmd2.Flags().StringVarP(&endDate, "end", "e", "", "end date with format yyyy-mm-dd-hh-MM-ss") @@ -176,10 +176,6 @@ func DirCache(cmd *cobra.Command, params []string) { } func ListBucket2(cmd *cobra.Command, params []string) { - if maxRetry <= 0 { - fmt.Fprintf(os.Stderr, "maxRetry must be greater than 0\n") - os.Exit(1) - } bucket := params[0] var dateParser = func(datestr string) (time.Time, error) { diff --git a/go.mod b/go.mod index 2b503292..769cb295 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/onsi/gomega v1.4.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/qiniu/api.v7 v7.2.5-0.20181112070011-bc6998c1186a+incompatible + github.com/qiniu/api.v7 v7.2.6-0.20181128092015-8c3e1ca2eb33+incompatible github.com/qiniu/x v7.0.8+incompatible // indirect github.com/satori/go.uuid v1.2.0 // indirect github.com/spf13/cobra v0.0.3 diff --git a/go.sum b/go.sum index a669b048..2f8b1c92 100644 --- a/go.sum +++ b/go.sum @@ -32,8 +32,8 @@ github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/qiniu/api.v7 v7.2.5-0.20181112070011-bc6998c1186a+incompatible h1:FnBHGjkt7JJ2ebnQU0cRWrjk14ShzTSfvnLqjin2AWI= -github.com/qiniu/api.v7 v7.2.5-0.20181112070011-bc6998c1186a+incompatible/go.mod h1:V8/EzlTgLN6q0s0CJmg/I81ytsvldSF22F7h6MI02+c= +github.com/qiniu/api.v7 v7.2.6-0.20181128092015-8c3e1ca2eb33+incompatible h1:L3WEV1XhimkIAI0u1b2KlUIJyURecprw0EW42gsvYTA= +github.com/qiniu/api.v7 v7.2.6-0.20181128092015-8c3e1ca2eb33+incompatible/go.mod h1:V8/EzlTgLN6q0s0CJmg/I81ytsvldSF22F7h6MI02+c= github.com/qiniu/x v7.0.8+incompatible h1:P4LASsfwJY7SoZ13dwqBwGhZh7HKU8cdFVCUkmz0gZ8= github.com/qiniu/x v7.0.8+incompatible/go.mod h1:KpRKWYG/GaidPQVpoQ2Cvuvtts3gYnoo2PftgdmAiU4= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= diff --git a/iqshell/list_bucket.go b/iqshell/list_bucket.go index 0d1e9ffd..9406431c 100644 --- a/iqshell/list_bucket.go +++ b/iqshell/list_bucket.go @@ -76,11 +76,6 @@ func (m *BucketManager) ListBucket2(bucket, prefix, marker, listResultFile, deli maxRetry = 0 }() - if maxRetry <= 0 { - retErr = fmt.Errorf("maxRetry must be greater than 0") - return - } - var listResultFh *os.File if listResultFile == "" { @@ -101,16 +96,26 @@ func (m *BucketManager) ListBucket2(bucket, prefix, marker, listResultFile, deli notfilterTime := startDate.IsZero() && endDate.IsZero() notfilterSuffix := len(suffixes) == 0 - for c := 0; c < maxRetry; { + var c int + for { + if maxRetry >= 0 && c >= maxRetry { + break + } entries, lErr := m.ListBucketContext(ctx, bucket, prefix, delimiter, marker) if entries == nil && lErr == nil { // no data + fmt.Fprintf(os.Stderr, "Warning: empty data\n") return } if lErr != nil { + retErr = lErr errorWarning(lastMarker, retErr) - c++ + if maxRetry > 0 { + c++ + } + time.Sleep(1) + continue } for listItem := range entries { @@ -159,7 +164,9 @@ func (m *BucketManager) ListBucket2(bucket, prefix, marker, listResultFile, deli if fErr != nil { retErr = fErr errorWarning(lastMarker, retErr) - c++ + if maxRetry > 0 { + c++ + } } if lastMarker == "" { break From b5d232258c3a4212db8b8598ef4f06e1597fbc65 Mon Sep 17 00:00:00 2001 From: Tony Cai Date: Wed, 28 Nov 2018 22:02:57 +0800 Subject: [PATCH 08/20] add append mode to listbucket2 --- cmd/rs.go | 4 +++- iqshell/list_bucket.go | 13 ++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/cmd/rs.go b/cmd/rs.go index 64a602fe..34031fd9 100644 --- a/cmd/rs.go +++ b/cmd/rs.go @@ -131,6 +131,7 @@ var ( endDate string maxRetry int finalKey string + appendMode bool ) func init() { @@ -148,6 +149,7 @@ func init() { lsBucketCmd2.Flags().StringVarP(&outFile, "out", "o", "", "output file") lsBucketCmd2.Flags().StringVarP(&startDate, "start", "s", "", "start date with format yyyy-mm-dd-hh-MM-ss") lsBucketCmd2.Flags().StringVarP(&endDate, "end", "e", "", "end date with format yyyy-mm-dd-hh-MM-ss") + lsBucketCmd2.Flags().BoolVarP(&appendMode, "append", "a", false, "append to file") moveCmd.Flags().BoolVarP(&mOverwrite, "overwrite", "w", false, "overwrite mode") moveCmd.Flags().StringVarP(&finalKey, "key", "k", "", "filename saved in bucket") @@ -217,7 +219,7 @@ func ListBucket2(cmd *cobra.Command, params []string) { } } bm := iqshell.GetBucketManager() - retErr := bm.ListBucket2(bucket, prefix, listMarker, outFile, "", start, end, sf, maxRetry) + retErr := bm.ListBucket2(bucket, prefix, listMarker, outFile, "", start, end, sf, maxRetry, appendMode) if retErr != nil { os.Exit(iqshell.STATUS_ERROR) } diff --git a/iqshell/list_bucket.go b/iqshell/list_bucket.go index 9406431c..e6693c43 100644 --- a/iqshell/list_bucket.go +++ b/iqshell/list_bucket.go @@ -58,10 +58,10 @@ func errorWarning(marker string, err error) { *@return listError */ func (m *BucketManager) ListFiles(bucket, prefix, marker, listResultFile string) (retErr error) { - return m.ListBucket2(bucket, prefix, marker, listResultFile, "", time.Time{}, time.Time{}, nil, 20) + return m.ListBucket2(bucket, prefix, marker, listResultFile, "", time.Time{}, time.Time{}, nil, 20, false) } -func (m *BucketManager) ListBucket2(bucket, prefix, marker, listResultFile, delimiter string, startDate, endDate time.Time, suffixes []string, maxRetry int) (retErr error) { +func (m *BucketManager) ListBucket2(bucket, prefix, marker, listResultFile, delimiter string, startDate, endDate time.Time, suffixes []string, maxRetry int, appendMode bool) (retErr error) { lastMarker := marker sigChan := make(chan os.Signal, 1) @@ -82,7 +82,14 @@ func (m *BucketManager) ListBucket2(bucket, prefix, marker, listResultFile, deli listResultFh = os.Stdout } else { var openErr error - listResultFh, openErr = os.Create(listResultFile) + var mode int + + if appendMode { + mode = os.O_APPEND | os.O_RDWR + } else { + mode = os.O_CREATE | os.O_RDWR | os.O_TRUNC + } + listResultFh, openErr = os.OpenFile(listResultFile, mode, 0666) if openErr != nil { retErr = openErr logs.Error("Failed to open list result file `%s`", listResultFile) From 940b41326f98658b368c7171b1b5575ecdf585a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E5=8A=A0=E5=BC=BA?= Date: Thu, 29 Nov 2018 09:23:30 +0800 Subject: [PATCH 09/20] does not allow overwrite of account --- iqshell/account.go | 10 ++++++++++ iqshell/list_bucket.go | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/iqshell/account.go b/iqshell/account.go index 5d13dac7..cf1b7368 100644 --- a/iqshell/account.go +++ b/iqshell/account.go @@ -111,6 +111,16 @@ func setdb(acc Account) (err error) { } defer ldb.Close() + exists, hErr := ldb.Has([]byte(acc.Name), nil) + if hErr != nil { + err = hErr + return + } + if exists { + err = fmt.Errorf("Account Name: %s already exist in local db", acc.Name) + return + } + ldbWOpt := opt.WriteOptions{ Sync: true, } diff --git a/iqshell/list_bucket.go b/iqshell/list_bucket.go index e6693c43..9ce61747 100644 --- a/iqshell/list_bucket.go +++ b/iqshell/list_bucket.go @@ -113,7 +113,7 @@ func (m *BucketManager) ListBucket2(bucket, prefix, marker, listResultFile, deli if entries == nil && lErr == nil { // no data fmt.Fprintf(os.Stderr, "Warning: empty data\n") - return + break } if lErr != nil { retErr = lErr From a82cf99d0c548839028b453a19cd59feb7f53094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E5=8A=A0=E5=BC=BA?= Date: Thu, 29 Nov 2018 09:45:31 +0800 Subject: [PATCH 10/20] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=96=B0=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E7=9A=84=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + cmd/account.go | 7 ++++++- docs/account.md | 12 +++++++++--- docs/listbucket2.md | 23 +++++++++++++++-------- iqshell/account.go | 25 ++++++++++++++----------- 5 files changed, 45 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7afe195..478c2633 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # 2.3.4 1. listbucket, listbucket2增加捕捉interrupt信号(CTR-C), 打印marker +2. account在本地记录账号,默认不覆盖 # 2.3.3 1. 修复qdownload配置cdn_domain使用了测试域名作为HOST 引起超过10G流量限制的问题 diff --git a/cmd/account.go b/cmd/account.go index b79e7336..0d0772c6 100644 --- a/cmd/account.go +++ b/cmd/account.go @@ -7,7 +7,12 @@ import ( "os" ) +var ( + accountOver bool +) + func init() { + cmdAccount.Flags().BoolVarP(&accountOver, "overwrite", "w", false, "overwrite account or not when account exists in local db, by default not overwrite") RootCmd.AddCommand(cmdAccount) } @@ -37,7 +42,7 @@ func Account(cmd *cobra.Command, params []string) { name := params[2] pt, oldPath := iqshell.AccPath(), iqshell.OldAccPath() - sErr := iqshell.SetAccount2(accessKey, secretKey, name, pt, oldPath) + sErr := iqshell.SetAccount2(accessKey, secretKey, name, pt, oldPath, accountOver) if sErr != nil { fmt.Println(sErr) os.Exit(iqshell.STATUS_ERROR) diff --git a/docs/account.md b/docs/account.md index a5dbcf76..6dd2eb7e 100644 --- a/docs/account.md +++ b/docs/account.md @@ -3,6 +3,9 @@ `account`命令用来设置当前用户的`AccessKey`和`SecretKey`,这对Key主要用在其他的需要授权的命令中,比如`stat`,`delete`,`listbucket`命令中。 该命令设置的信息,经过加密保存在命令执行的目录下的`.qshell/account.json`文件中。 +本地数据库会记录`account`注册的所有, 的信息, 所以当用`account`注册账户信息时,如果qshell发现本地数据库有同样的名字为 +的账户, 那么默认qshell会返回错误信息报告该名字的账户已经存在,如果要覆盖注册,需要使用强制覆盖选项--overwrite 或者 -w + # 格式 ``` @@ -12,10 +15,13 @@ qshell account 打印当前设置的`AccessKey`, `SecretKey`和`Name` ``` -qshell account +qshell account [--overwrite | -w] ``` -设置当前用户的`AccessKey`, `SecretKey`和`Name` +设置当前用户的`AccessKey`, `SecretKey`和`Name`, Name是用户可以任意取的名字,表示当前在本地记录的账户的名称,和在七牛注册的邮箱信息没有关系 + +# 选项 +-w --overwrite 强制覆盖已经存在的账户 # 参数 @@ -23,7 +29,7 @@ qshell account |--------|--------| |AccessKey|七牛账号对应的AccessKey [获取](https://portal.qiniu.com/user/key)| |SecretKey|七牛账号对应的SecretKey [获取](https://portal.qiniu.com/user/key)| -|Name|账户的名字| +|Name|账户的名字, 可以任意取,和在七牛注册的邮箱信息没有关系, 只是qshell本地用来标示对 | # 示例 diff --git a/docs/listbucket2.md b/docs/listbucket2.md index 94748444..042ed551 100644 --- a/docs/listbucket2.md +++ b/docs/listbucket2.md @@ -15,7 +15,7 @@ Key\tSize\tHash\tPutTime\tMimeType\tFileType\tEndUser # 格式 ``` -qshell listbucket2 [--prefix | --suffixes ] [--start ] [--max-retry ][--end ] [-o ] +qshell listbucket2 [--prefix | --suffixes ] [--start ] [--max-retry ][--end ] [ [-a] -o ] ``` # 鉴权 @@ -32,8 +32,9 @@ qshell listbucket2 [--prefix | --suffixes ] [--sta | ListBucketResultFile | 获取的文件列表保存在本地的文件名,如果不指定该参数,则会把结果输出到终端,一般可用于获取小规模文件列表测试使用 | Y | | StartDate | 列举整个空间,然后从中筛选出文件上传日期在之后的文件 | Y | | EndDate | 列举整个空间, 然后从中筛选出文件上传日期在之前的文件 | Y | -| RetryCount | 列举整个空间文件出错以后,最大的尝试次数;超过最大尝试次数以后,程序退出,打印出marker | Y | -| suffixes | 列举整个空间文件, 然后从中筛选出文件后缀为在[suffixes1, suffixes2, ...]中的文件 |Y| +| RetryCount | 列举整个空间文件出错以后,最大的尝试次数;超过最大尝试次数以后,程序退出,打印出marker | Y | +| suffixes | 列举整个空间文件, 然后从中筛选出文件后缀为在[suffixes1, suffixes2, ...]中的文件 | Y | +| a | 开启选项o 的append模式, 如果本地保存文件列表的文件已经存在,如果希望像该文件添加内容,使用该选项, 必须和-o选项一起使用 | Y | # 常用使用场景介绍 @@ -43,31 +44,37 @@ qshell listbucket2 [--prefix | --suffixes ] [--sta ``` qshell listbucket2 -o ``` + + (2) 如果本地文件`ListBucketResultFile`已经存在,有上一次列举的内容,如果希望把新的列表添加到该文件中,需要使用选项-a开启-o选项的append 模式 + + ``` + qshell listbucket2 -a -o + ``` - (2) 获取空间所有文件,输出到屏幕上(标准输出) + (3) 获取空间所有文件,输出到屏幕上(标准输出) ``` qshell listbucket2 ``` -(3)获取空间中指定前缀的文件列表 +(4)获取空间中指定前缀的文件列表 ``` qshell listbucket2 [--prefix ] -o ``` - (4) 获取空间中指定前缀的文件列表, 输出到屏幕上 + (5) 获取空间中指定前缀的文件列表, 输出到屏幕上 ``` qshell listbucket2 [--prefix ] ``` - (5) 获取2018-10-30到2018-11-02上传的文件 + (6) 获取2018-10-30到2018-11-02上传的文件 ``` qshell listbucket2 --start 2018-10-30 --end 2018-11-02 ``` - (6) 获取后缀为mp4, html的文件 + (7) 获取后缀为mp4, html的文件 ``` qshell listbucket2 --suffixes mp4,html diff --git a/iqshell/account.go b/iqshell/account.go index cf1b7368..a1d993ee 100644 --- a/iqshell/account.go +++ b/iqshell/account.go @@ -99,7 +99,7 @@ func DecryptSecretKey(accessKey, encryptedKey string) (string, error) { return secretKey, nil } -func setdb(acc Account) (err error) { +func setdb(acc Account, accountOver bool) (err error) { accDbPath := AccDBPath() if accDbPath == "" { return fmt.Errorf("empty account db path") @@ -111,14 +111,17 @@ func setdb(acc Account) (err error) { } defer ldb.Close() - exists, hErr := ldb.Has([]byte(acc.Name), nil) - if hErr != nil { - err = hErr - return - } - if exists { - err = fmt.Errorf("Account Name: %s already exist in local db", acc.Name) - return + if !accountOver { + + exists, hErr := ldb.Has([]byte(acc.Name), nil) + if hErr != nil { + err = hErr + return + } + if exists { + err = fmt.Errorf("Account Name: %s already exist in local db", acc.Name) + return + } } ldbWOpt := opt.WriteOptions{ @@ -137,7 +140,7 @@ func setdb(acc Account) (err error) { return } -func SetAccount2(accessKey, secretKey, name, accPath, oldPath string) (err error) { +func SetAccount2(accessKey, secretKey, name, accPath, oldPath string, accountOver bool) (err error) { acc := Account{ Name: name, AccessKey: accessKey, @@ -149,7 +152,7 @@ func SetAccount2(accessKey, secretKey, name, accPath, oldPath string) (err error return } - err = setdb(acc) + err = setdb(acc, accountOver) return } From 70b3e986f1d33de100ce1030608284ed767b72a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E5=8A=A0=E5=BC=BA?= Date: Thu, 29 Nov 2018 09:47:29 +0800 Subject: [PATCH 11/20] =?UTF-8?q?=E5=AE=8C=E5=96=84CHANGLOG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 478c2633..f1eb6020 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # 2.3.4 1. listbucket, listbucket2增加捕捉interrupt信号(CTR-C), 打印marker -2. account在本地记录账号,默认不覆盖 +2. account在本地记录账号,默认不覆盖, 加了-w强制覆盖选项 +3. listbucket2 增加append 模式(-a)开启 # 2.3.3 1. 修复qdownload配置cdn_domain使用了测试域名作为HOST 引起超过10G流量限制的问题 From 19dfa8138f0147451f6c8a9ed4b4a11ed4cc5877 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E5=8A=A0=E5=BC=BA?= Date: Thu, 29 Nov 2018 09:56:10 +0800 Subject: [PATCH 12/20] =?UTF-8?q?=E5=AE=8C=E5=96=84=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 +- iqshell/account.go | 27 +-------------------------- 2 files changed, 2 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f1eb6020..cd666474 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # 2.3.4 1. listbucket, listbucket2增加捕捉interrupt信号(CTR-C), 打印marker 2. account在本地记录账号,默认不覆盖, 加了-w强制覆盖选项 -3. listbucket2 增加append 模式(-a)开启 +3. listbucket2 增加append 模式(-a)开启, 修复列举几亿空间的时候,列举一半左右程序中断问题 # 2.3.3 1. 修复qdownload配置cdn_domain使用了测试域名作为HOST 引起超过10G流量限制的问题 diff --git a/iqshell/account.go b/iqshell/account.go index a1d993ee..6a496c09 100644 --- a/iqshell/account.go +++ b/iqshell/account.go @@ -375,32 +375,7 @@ func ListUser(userLsName bool) (err error) { } defer db.Close() - iter := db.NewIterator(nil, nil) - var ( - name string - value string - ) - for iter.Next() { - name = string(iter.Key()) - value = string(iter.Value()) - acc, dErr := Decrypt(value) - if dErr != nil { - err = fmt.Errorf("Decrypt account bytes: %v", dErr) - return - } - if userLsName { - fmt.Println(name) - } else { - fmt.Printf("Name: %s\n", name) - fmt.Printf("AccessKey: %s\n", acc.AccessKey) - fmt.Printf("SecretKey: %s\n", acc.SecretKey) - fmt.Println("") - } - } - iter.Release() - return -} - + func CleanUser() (err error) { QShellRootPath := RootPath() if QShellRootPath == "" { From 9b328272f9a1b53560a7e55749f9789e4369b3d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E5=8A=A0=E5=BC=BA?= Date: Thu, 29 Nov 2018 10:10:16 +0800 Subject: [PATCH 13/20] debug --- iqshell/account.go | 27 ++++++++++++++++++++++++++- iqshell/list_bucket.go | 3 +-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/iqshell/account.go b/iqshell/account.go index 6a496c09..a1d993ee 100644 --- a/iqshell/account.go +++ b/iqshell/account.go @@ -375,7 +375,32 @@ func ListUser(userLsName bool) (err error) { } defer db.Close() - + iter := db.NewIterator(nil, nil) + var ( + name string + value string + ) + for iter.Next() { + name = string(iter.Key()) + value = string(iter.Value()) + acc, dErr := Decrypt(value) + if dErr != nil { + err = fmt.Errorf("Decrypt account bytes: %v", dErr) + return + } + if userLsName { + fmt.Println(name) + } else { + fmt.Printf("Name: %s\n", name) + fmt.Printf("AccessKey: %s\n", acc.AccessKey) + fmt.Printf("SecretKey: %s\n", acc.SecretKey) + fmt.Println("") + } + } + iter.Release() + return +} + func CleanUser() (err error) { QShellRootPath := RootPath() if QShellRootPath == "" { diff --git a/iqshell/list_bucket.go b/iqshell/list_bucket.go index 9ce61747..20b1881e 100644 --- a/iqshell/list_bucket.go +++ b/iqshell/list_bucket.go @@ -112,8 +112,7 @@ func (m *BucketManager) ListBucket2(bucket, prefix, marker, listResultFile, deli if entries == nil && lErr == nil { // no data - fmt.Fprintf(os.Stderr, "Warning: empty data\n") - break + return } if lErr != nil { retErr = lErr From 8e30f26f45f1fa9317cf4f758a8b43fc31d20476 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E5=8A=A0=E5=BC=BA?= Date: Thu, 29 Nov 2018 12:01:42 +0800 Subject: [PATCH 14/20] debug --- iqshell/list_bucket.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iqshell/list_bucket.go b/iqshell/list_bucket.go index 20b1881e..cdaa9652 100644 --- a/iqshell/list_bucket.go +++ b/iqshell/list_bucket.go @@ -112,7 +112,7 @@ func (m *BucketManager) ListBucket2(bucket, prefix, marker, listResultFile, deli if entries == nil && lErr == nil { // no data - return + break } if lErr != nil { retErr = lErr From 507ea4f522c791a1d8d39ea386f2576dda94a81e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E5=8A=A0=E5=BC=BA?= Date: Thu, 29 Nov 2018 14:06:18 +0800 Subject: [PATCH 15/20] debug --- iqshell/list_bucket.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/iqshell/list_bucket.go b/iqshell/list_bucket.go index cdaa9652..f9c89ccf 100644 --- a/iqshell/list_bucket.go +++ b/iqshell/list_bucket.go @@ -112,7 +112,11 @@ func (m *BucketManager) ListBucket2(bucket, prefix, marker, listResultFile, deli if entries == nil && lErr == nil { // no data - break + if lastMarker == "" { + break + } else { + continue + } } if lErr != nil { retErr = lErr From 0083a31c7e81f84b3898713bc143b50afd3d3e6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E5=8A=A0=E5=BC=BA?= Date: Thu, 29 Nov 2018 14:08:17 +0800 Subject: [PATCH 16/20] debug --- iqshell/list_bucket.go | 1 + 1 file changed, 1 insertion(+) diff --git a/iqshell/list_bucket.go b/iqshell/list_bucket.go index f9c89ccf..fdf33070 100644 --- a/iqshell/list_bucket.go +++ b/iqshell/list_bucket.go @@ -115,6 +115,7 @@ func (m *BucketManager) ListBucket2(bucket, prefix, marker, listResultFile, deli if lastMarker == "" { break } else { + fmt.Fprintf(os.Stderr, "meet empty body when list not completed\n") continue } } From 77f4981bac80b71e78cf9e3538aa689e8091befe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E5=8A=A0=E5=BC=BA?= Date: Fri, 30 Nov 2018 16:37:46 +0800 Subject: [PATCH 17/20] =?UTF-8?q?=E4=BF=AE=E5=A4=8Ddirache=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + cmd/rs.go | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cd666474..2e0832a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ 1. listbucket, listbucket2增加捕捉interrupt信号(CTR-C), 打印marker 2. account在本地记录账号,默认不覆盖, 加了-w强制覆盖选项 3. listbucket2 增加append 模式(-a)开启, 修复列举几亿空间的时候,列举一半左右程序中断问题 +4. 修复dircache 列表没有输出到文件使用-o选项的时候 # 2.3.3 1. 修复qdownload配置cdn_domain使用了测试域名作为HOST 引起超过10G流量限制的问题 diff --git a/cmd/rs.go b/cmd/rs.go index 34031fd9..8e82b5a4 100644 --- a/cmd/rs.go +++ b/cmd/rs.go @@ -165,9 +165,8 @@ func init() { func DirCache(cmd *cobra.Command, params []string) { var cacheResultFile string cacheRootPath := params[0] - if len(params) == 2 { - cacheResultFile = params[1] - } + + cacheResultFile = outFile if cacheResultFile == "" { cacheResultFile = "stdout" } From a72e94b12327dd1659daf9cbd59b884ffc03b97c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E5=8A=A0=E5=BC=BA?= Date: Tue, 4 Dec 2018 16:15:28 +0800 Subject: [PATCH 18/20] v2.3.4 --- CHANGELOG.md | 2 ++ README.md | 1 + cmd/root.go | 30 ++++++++++++++++++++++++++++++ iqshell/account.go | 6 +++--- iqshell/config.go | 18 ------------------ iqshell/qupload.go | 5 ++++- 6 files changed, 40 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e0832a3..0cbfbfc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ 2. account在本地记录账号,默认不覆盖, 加了-w强制覆盖选项 3. listbucket2 增加append 模式(-a)开启, 修复列举几亿空间的时候,列举一半左右程序中断问题 4. 修复dircache 列表没有输出到文件使用-o选项的时候 +5. 修复qupload, qupload2使用多线程上传导致的部分文件上传失败问题 +6. 加了-L 选项到qshell, 使用当前工作路径作为qshell的配置目录 # 2.3.3 1. 修复qdownload配置cdn_domain使用了测试域名作为HOST 引起超过10G流量限制的问题 diff --git a/README.md b/README.md index 3336a581..cafd0dd1 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,7 @@ fi |-h|打印命令列表帮助信息,遇到参数忘记的情况下,可以使用该命令| |-v|打印工具版本,反馈问题的时候,请提前告知工具对应版本号| |-C|qshell配置文件, 其配置格式请看下一节| +|-L|使用当前工作路径作为qshell的配置目录| ## 配置文件 diff --git a/cmd/root.go b/cmd/root.go index 0996ca0a..bbf9f68d 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -8,6 +8,7 @@ import ( "github.com/spf13/viper" "os" "os/user" + "path/filepath" "runtime" ) @@ -15,6 +16,7 @@ var ( DebugFlag bool VersionFlag bool cfgFile string + local bool ) const ( @@ -61,8 +63,10 @@ func init() { RootCmd.PersistentFlags().BoolVarP(&DebugFlag, "debug", "d", false, "debug mode") RootCmd.PersistentFlags().BoolVarP(&VersionFlag, "version", "v", false, "show version") RootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "C", "", "config file (default is $HOME/.qshell.json)") + RootCmd.PersistentFlags().BoolVarP(&local, "local", "L", false, "use current directory as config file path") viper.BindPFlag("config", RootCmd.PersistentFlags().Lookup("config")) + viper.BindPFlag("local", RootCmd.PersistentFlags().Lookup("local")) } func initConfig() { @@ -86,6 +90,32 @@ func initConfig() { viper.AddConfigPath(curUser.HomeDir) viper.SetConfigName(".qshell") } + + if local { + dir, gErr := os.Getwd() + if gErr != nil { + fmt.Fprintf(os.Stderr, "get current directory: %v\n", gErr) + os.Exit(1) + } + viper.Set("path.root_path", dir+"/.qshell") + } else { + curUser, gErr := user.Current() + if gErr != nil { + fmt.Fprintf(os.Stderr, "Error: get current user error: %v\n", gErr) + os.Exit(1) + } + viper.Set("path.root_path", curUser.HomeDir+"/.qshell") + } + rootPath := viper.GetString("path.root_path") + + viper.SetDefault("path.acc_db_path", filepath.Join(rootPath, "account.db")) + viper.SetDefault("path.acc_path", filepath.Join(rootPath, "account.json")) + viper.SetDefault("hosts.up_host", "upload.qiniup.com") + viper.SetDefault("hosts.rs_host", storage.DefaultRsHost) + viper.SetDefault("hosts.rsf_host", storage.DefaultRsfHost) + viper.SetDefault("hosts.io_host", "iovip.qbox.me") + viper.SetDefault("hosts.api_host", storage.DefaultAPIHost) + if rErr := viper.ReadInConfig(); rErr != nil { if _, ok := rErr.(viper.ConfigFileNotFoundError); !ok { fmt.Fprintf(os.Stderr, "read config file: %v\n", rErr) diff --git a/iqshell/account.go b/iqshell/account.go index a1d993ee..50926143 100644 --- a/iqshell/account.go +++ b/iqshell/account.go @@ -164,21 +164,21 @@ func SetAccount(acc Account, accPath, oldPath string) (err error) { } if _, sErr := os.Stat(QShellRootPath); sErr != nil { if mErr := os.MkdirAll(QShellRootPath, 0755); mErr != nil { - err = fmt.Errorf("Mkdir `%s` error, %s", QShellRootPath, mErr) + err = fmt.Errorf("Mkdir `%s` error: %s", QShellRootPath, mErr) return } } accountFh, openErr := os.OpenFile(accPath, os.O_CREATE|os.O_RDWR, 0600) if openErr != nil { - err = fmt.Errorf("Open account file error, %s", openErr) + err = fmt.Errorf("Open account file error: %s", openErr) return } defer accountFh.Close() oldAccountFh, openErr := os.OpenFile(oldPath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600) if openErr != nil { - err = fmt.Errorf("Open account file error, %s", openErr) + err = fmt.Errorf("Open account file error: %s", openErr) return } defer oldAccountFh.Close() diff --git a/iqshell/config.go b/iqshell/config.go index 0d250e34..e5b1e322 100644 --- a/iqshell/config.go +++ b/iqshell/config.go @@ -9,24 +9,6 @@ import ( "path/filepath" ) -func init() { - curUser, gErr := user.Current() - if gErr != nil { - fmt.Println("Error: get current user error,", gErr) - os.Exit(STATUS_HALT) - } - rootPath := filepath.Join(curUser.HomeDir, ".qshell") - - viper.SetDefault("path.root_path", filepath.Join(curUser.HomeDir, ".qshell")) - viper.SetDefault("path.acc_db_path", filepath.Join(rootPath, "account.db")) - viper.SetDefault("path.acc_path", filepath.Join(rootPath, "account.json")) - viper.SetDefault("hosts.up_host", "upload.qiniup.com") - viper.SetDefault("hosts.rs_host", storage.DefaultRsHost) - viper.SetDefault("hosts.rsf_host", storage.DefaultRsfHost) - viper.SetDefault("hosts.io_host", "iovip.qbox.me") - viper.SetDefault("hosts.api_host", storage.DefaultAPIHost) -} - func RootPath() string { return viper.GetString("path.root_path") } diff --git a/iqshell/qupload.go b/iqshell/qupload.go index a9bf4634..06799fb1 100644 --- a/iqshell/qupload.go +++ b/iqshell/qupload.go @@ -105,6 +105,7 @@ type UploadConfig struct { CallbackUrls string `json:"callback_urls,omitempty"` CallbackHost string `json:"callback_host,omitempty"` PutPolicy storage.PutPolicy + Plock sync.Mutex } func (cfg *UploadConfig) JobId() string { @@ -282,6 +283,9 @@ func (cfg *UploadConfig) PrepareLogger(storePath, jobId string) { func (cfg *UploadConfig) UploadToken(mac *qbox.Mac, uploadFileKey string) string { + cfg.Plock.Lock() + defer cfg.Plock.Unlock() + cfg.PutPolicy.Scope = cfg.Bucket if cfg.Overwrite { cfg.PutPolicy.Scope = fmt.Sprintf("%s:%s", cfg.Bucket, uploadFileKey) @@ -578,7 +582,6 @@ func QiniuUpload(threadCount int, uploadConfig *UploadConfig, exporter *FileExpo defer upWaitGroup.Done() upToken := uploadConfig.UploadToken(bm.GetMac(), uploadFileKey) - if localFileSize > putThreshold { resumableUploadFile(uploadConfig, ldb, &ldbWOpt, ldbKey, upToken, storePath, localFilePath, uploadFileKey, localFileLastModified, exporter) From 7af32ecb587408d980f308ec41263b0d76461502 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E5=8A=A0=E5=BC=BA?= Date: Tue, 4 Dec 2018 16:17:19 +0800 Subject: [PATCH 19/20] v2.3.4 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cafd0dd1..beb895b3 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ qshell是利用[七牛文档上公开的API](http://developer.qiniu.com)实现 |版本 |支持平台|链接| |--------|---------|----| -|qshell-v2.3.4 |Mac OSX, Linux, Windows|[下载](http://devtools.qiniu.com/qshell-develop.zip)| +|qshell-v2.3.4 |Mac OSX, Linux, Windows|[下载](http://devtools.qiniu.com/qshell-v2.3.4.zip)| ## 安装 From b684fec09d918114eaf54df463a27f2f7505173a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E5=8A=A0=E5=BC=BA?= Date: Tue, 4 Dec 2018 16:19:12 +0800 Subject: [PATCH 20/20] v2.3.4 --- iqshell/config.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/iqshell/config.go b/iqshell/config.go index e5b1e322..50555330 100644 --- a/iqshell/config.go +++ b/iqshell/config.go @@ -1,11 +1,7 @@ package iqshell import ( - "fmt" - "github.com/qiniu/api.v7/storage" "github.com/spf13/viper" - "os" - "os/user" "path/filepath" )