简易文件中转站脚本

164 阅读4分钟

简易版文件中转站

大家可能会遇到这种场景:

  • 容器里面的日志帮忙拉下来下,我要定位下问题
  • 我有一个安装包下载不下来,我需要上传到服务器
  • 我有一些比较重要的日志, 需要定期归档到云端, 避免占用本地空间

那么如何解决这些问题呢?

解决方案

由于可能面临复杂网络下(多层跳板机)的上传和下载问题, 通过点对点传(比如SCP之类)的很难行得通,所以选择用中转站的方式,比如 OSS

OSS在产品开发过程中也经常用到比如:

  • 用户上传了一个视频,我需要找个地方存储
  • 用户上传了一些图片, 我需要找个地方存储

寻找现成工具

我们寻找有没有现有的客户端:

  • 阿里有 OSS browser, 但不能通过 CLI 调用
  • 多个云商客户端不能通用

自己做一个简单的工具

1. 准备好你的阿里云bucket资源

image.png

2. 查看阿里云 oss sdk使用样例

我们通过编写一些测试用例来熟悉基本操作(获取Bucket、上传文件)

操作目录 image.png

  • oss_test.go

    • 声明一个全局 OSS 客户端变量
        var (
            client *oss.Client
        )
    
    • 声明出所需变量,并从环境变量中获取
       var (
           AccessKey    = os.Getenv("ALI_AK")
           AccessSecret = os.Getenv("ALI_SK")
           OssEndpoint  = os.Getenv("ALI_OSS_ENDPOINT")
           BucketName   = os.Getenv("ALI_BUCKET_NAME")
       )
    
    • init函数在程序执行前 初始化全局客户端变量
        func init() {
            c, err := oss.New(OssEndpoint, AccessKey, AccessSecret)
            if err != nil{
                    panic(err)
            }
    
            client = c
        }
    
    • 获取Bucket列表函数
       func TestBucketList(t *testing.T) {
            lsRes, err := client.ListBuckets()
            if err != nil{
                    t.Log(err)
            }
    
            for _, bucket := range lsRes.Buckets{
                    fmt.Println("Buckets:", bucket.Name)
                }
        }
    
    • 上传文件函数
      • 获取bucket对象
      • 上传文件到该 Bucket
      • 获取下载地址并设置时间限制
        func TestUploadFile(t *testing.T) {
            bucket, err := client.Bucket(BucketName)
            if err != nil{
                    t.Log(err)
            }
            // 第一个参数是上传到Bucket后的位置, 第二个为该文件夹下的文件(此处为自己)
            err = bucket.PutObjectFromFile("mydir/test.go", "oss_test.go")
            if err != nil{
                    t.Log(err)
                 }
                 
          downloadURL, err := bucket.SignURL(file_path, oss.HTTPGet, 60*60*24)
          if err != nil {
                   return err
              }
          fmt.Printf("文件下载URL: %s \n", downloadURL)
          fmt.Println("请在1天之内下载.")
         }
    
  • settings.json 文件

    • 若该文件或目录前缀路径没有需自己建立
    • 为了使我们的测试用例获取环境变量
    • 我们可以加入以下代码让测试用例在本文件夹下的 /etc/unit_test.env文件内加载环境变量
{
    "go.testEnvFile": "${workspaceFolder}/etc/unit_test.env",
    "commentTranslate.source": "Baidu"
}
  • unit_test.env
    • 填写你自己的相关配置,例子如下
    • AccessKey和AccessSecret从右上角账号栏 image.png获取
ALI_AK=X56ZAMDE23
ALI_SK=WONM1235AA
ALI_OSS_ENDPOINT=oss-cn-beijing.aliyuncs.com
ALI_BUCKET_NAME=my-bucket
  • 测试用例显示Print打印

默认情况下 我们在测试用例中使用print的时候 控制台是不打印 这些中间环节信息的, 如果我们需要打印 就需要进行配置, 如何配置?

vscodego 插件在 执行测试用例的时候 是调用 go test 来执行的, 但是他没有加上 -v 参数, 因此我们通过 vscode 配置上该参数就可以了

注意这里配置的是 vscode 全局参数, 因此只需要配置一次,后面所有项目都可以生效

然后添加如下参数即可

去试一试吧!

3. 开始工具的编写

  • 所需变量与 upload 函数和测试用例相同,不重复论述
  • 设置用户所需传递的参数
    • -h:打印帮助信息
    • -f:输入上传文件的名称
func loadParams() {
	flag.StringVar(&uploadFile, "f", "", "上传文件的名称")
	flag.BoolVar(&help, "h", false, "打印帮助信息")
	flag.Parse()

	if help{
		usage()
		os.Exit(0)
	}
}
  • 帮助信息 usage()
func usage(){
	// 1. 打印一些描述信息
	fmt.Fprintf(os.Stderr, `cloud-station version: 0.0.1
Usage: cloud-station [-h] -f <uplaod_file_path>
Options:
`)

	// 2. 打印有哪些参数可以使用, 就像-f
	flag.PrintDefaults()
}
  • 参数合法性检测
    • 我们可以在 创建 OSS 客户端实例前对 创建所需参数 进行校验
func validate() error {
	if endpoint == "" || acessKey == "" || acessSecret == "" {
		return fmt.Errorf("endpoint, access_key access_secret has one empty")
	}

	if uploadFile == "" {
		return fmt.Errorf("upload file path required")
	}

	return nil
}
  • 串联逻辑,编写入口函数
func main() {
	// 参数加载
	loadParams()

	// 参数验证
	if err := validate(); err != nil {
		fmt.Printf("参数校验异常: %s\n", err)
		usage()
		os.Exit(1)
	}

	if err := upload(uploadFile); err != nil {
		fmt.Printf("上传文件异常: %s\n", err)
		os.Exit(1)
	}

	fmt.Printf("文件: %s 上传完成\n", uploadFile)
}

实现结果,快去试试吧!

image.png

image.png

客户如何使用你提供的工具

  • 提供多个平台的版本(Linux, Windows, MacOS)
  • 用户如何获取到你的工具, 上传到一个工具仓库,提供下载链接
  • 为你的工具添加一个使用文档

来自用户的抱怨

  • 我上传大文件 没进度条, 不知道啥时候能传输完成
  • 没有传输速率, 不知道上传快慢

总结

我们以写脚本的一个模式写了一个工具, 他能最快的解决我们问题, 但是其中还是有一些简单的技巧

  • 面向过程开发的思维模式
  • 合理抽象函数
  • 合理使用变量
  • 注意校验用户输入

请看下节 系统方式开发文件中转站