前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >golang封装tar打包解包之二

golang封装tar打包解包之二

原创
作者头像
willsiom
发布2023-11-07 20:23:12
2240
发布2023-11-07 20:23:12
举报
文章被收录于专栏:沈钦华的专栏沈钦华的专栏

好久没上来这里写专栏了,发现上一篇有关tar打包解包还留着一个坑。这里补上。

本文介绍下通过os/exec调用shell命令,直接调用系统的tar命令进行打包。

方案二、通过调用系统的tar命令

基本思路是先拼接tar打包和解包的命令,然后调用os/exec包的CommandContext方法执行shell命令。这里要求操作系统中需要有tar命令。

公共方法的定义

这里定义一个结构体,对日志的读取、shell脚本的执行做了封装。当然如果需要执行其他shell命令,直接给exec方法传入具体命令也是可以的。

代码语言:javascript
复制
type TgzLinuxPacker struct {
   ctx        context.Context    // context上下文,监听上层的退出信号
   cancel     context.CancelFunc // context的取消函数
   wg         sync.WaitGroup
   outputList []string // 命令的输出
}

func NewTgzLinuxPacker(ctx context.Context) *TgzLinuxPacker {
   subCtx, cancel := context.WithCancel(ctx)
   return &TgzLinuxPacker{
      ctx:        subCtx,
      cancel:     cancel,
      wg:         sync.WaitGroup{},
      outputList: make([]string, 0),
   }
}

// 从标准输出、错误输出读取内容
func (tlp *TgzLinuxPacker) readLog(stdReader io.Reader) {
   defer tlp.wg.Done()
   reader := bufio.NewReader(stdReader)
   for {
      select {
      case <-tlp.ctx.Done():
         return
      default:
         readString, err := reader.ReadString('\n')
         if err != nil || err == io.EOF {
            return
         }
         line := strings.Trim(readString, "\n")
         tlp.outputList = append(tlp.outputList, line)
      }
   }
}

// 命令执行的封装
func (tlp *TgzLinuxPacker) exec(cmdStr string) error {
   // 方法退出时触发cancel方法的调用,通知readLog和shell子进程退出
   defer tlp.cancel()
   c := exec.CommandContext(tlp.ctx, "/bin/bash", "-c", cmdStr)
   // get stdout stderr pipe
   stdout, err := c.StdoutPipe()
   if err != nil {
      return err
   }
   stderr, err := c.StderrPipe()
   if err != nil {
      return err
   }
   // read stdout stderr
   tlp.wg.Add(2)
   go tlp.readLog(stdout)
   go tlp.readLog(stderr)
   // 开始执行
   err = c.Start()
   if err != nil {
      return err
   }
   // 等待readLog退出
   tlp.wg.Wait()
   // 这里调用一次wait,获取shell进程的退出码
   err = c.Wait()
   if err != nil {
      return errors.New(strings.Join(tlp.outputList, "\n") + err.Error())
   }
   if !c.ProcessState.Success() {
      return errors.New("返回码:" + strconv.Itoa(c.ProcessState.ExitCode()) + "\n" + strings.Join(tlp.outputList, "\n"))
   }
   return nil
}

压缩打包

有了执行shell命令的方法后,我们要进行打包的工作,那就相当简单了,直接拼接命令行即可

代码语言:javascript
复制
func (tlp *TgzLinuxPacker) Pack(sourceFullPath string, tarFileName string) error {
   // e.g: tar -zcf test.tar.gz -C /tmp/ test
   cmdStr := "tar -zcf " + tarFileName + " -C " + filepath.Dir(sourceFullPath) + " " + filepath.Base(sourceFullPath)
   return tlp.exec(cmdStr)
}

解压

同压缩打包,值需要拼接解压命令即可

代码语言:javascript
复制
func (tlp *TgzLinuxPacker) Unpack(tarFileName string, dstDir string) error {
   // e.g: tar -zxf /tmp/test.tar.gz -C /tmp/
   cmdStr := "tar -zxf " + tarFileName + " -C " + dstDir
   return tlp.exec(cmdStr)
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 方案二、通过调用系统的tar命令
    • 公共方法的定义
      • 压缩打包
        • 解压
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档