好久没上来这里写专栏了,发现上一篇有关tar打包解包还留着一个坑。这里补上。
本文介绍下通过os/exec调用shell命令,直接调用系统的tar命令进行打包。
基本思路是先拼接tar打包和解包的命令,然后调用os/exec包的CommandContext方法执行shell命令。这里要求操作系统中需要有tar命令。
这里定义一个结构体,对日志的读取、shell脚本的执行做了封装。当然如果需要执行其他shell命令,直接给exec方法传入具体命令也是可以的。
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命令的方法后,我们要进行打包的工作,那就相当简单了,直接拼接命令行即可
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)
}
同压缩打包,值需要拼接解压命令即可
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 删除。