我如何制作可以自行删除的Go程序?

时间:2019-04-14 14:04:30

标签: go

当我想制作一个可以自我更新的程序时,一切就开始了。我认为我需要该程序下载一个新版本并运行一个功能,该功能可以复制新程序并用下载的版本替换原始程序。

我试图使这个问题尽可能小,如何使一个程序调用另一个程序将其自身删除,这是我的尝试:

m

这就是我通过cli称呼它的方式。

package main

import (
    "flag"
    "fmt"
    "log"
    "os"
    "os/exec"
    "time"
)

func main()  {
    fmt.Println("program started")
    remove := flag.Bool("rm", false, "removes test")
    flag.Parse()

    if *remove {
        // Wait 5 seconds to let other program finish
        time.Sleep(5 * time.Second)
        // Try to remove program that started this program
        fmt.Println("running rm")
        err := os.Remove("./test")
        if err != nil {
            log.Fatalf("os.Remove() failed with %s\n", err)
        }
    } else {
        // Call the second program which will remove ./test which is currently running
        fmt.Println("running remove program")
        cmd := exec.Command("./remove", "-rm")
        err := cmd.Start()
        if err != nil {
            log.Fatalf("cmd.Run() failed with %s\n", err)
        }
    }
}

总而言之:我如何制作一个可以自行删除或通过第二个命令/程序删除自身的程序?

如果可移植到不同的操作系统,则奖励。

2 个答案:

答案 0 :(得分:1)

由于您的目标是使应用程序自行更新,因此我将此功能移至第二个“更新程序”应用程序中。否则可执行文件(取决于OS)可能会被锁定,否则您仍然存在重新启动应用程序的问题。流程如下:

  • 主程序产生更新程序并终止自身
  • 更新程序等待主程序终止
  • 更新程序替换可执行文件并重新启动应用程序(如果需要)

答案 1 :(得分:0)

下面的代码是我如何解决在Mac OS,Linux和Windows上都能运行的示例。

package main

import (
    "flag"
    "fmt"
    "log"
    "os"
    "os/exec"
    "runtime"
    "time"
)

func main()  {
    fmt.Println("program started")
    remove := flag.Bool("rm", false, "removes test")
    flag.Parse()

    if *remove {
        var err error
        // Wait 5 seconds to let other program finish
        time.Sleep(5 * time.Second)
        // Try to remove program that started this program
        fmt.Println("running rm")
        if runtime.GOOS == "windows" {
            err = os.Remove("./test.exe")
        } else {
            err = os.Remove("./test")
        }
        if err != nil {
            log.Fatalf("os.Remove() failed with %s\n", err)
        }
    } else {
        var cmd *exec.Cmd
        // Call the second remove program which will remove ./test which is currently running
        fmt.Println("running remove program")
        if runtime.GOOS == "windows" {
            cmd = exec.Command("./remove.exe", "-rm")
        } else {
            cmd = exec.Command("./remove", "-rm")
        }
        cmd.Stdout = os.Stdout
        cmd.Stderr = os.Stderr
        err := cmd.Start()
        if err != nil {
            log.Fatalf("cmd.Run() failed with %s\n", err)
        }
    }
    fmt.Println("Finished running program")
}

如果您这样运行,该程序将自行删除

uberswe$ go build -o test
uberswe$ go build -o remove
uberswe$ ./test

在Windows上,我必须做一个更改,即添加.exe扩展名,以便Windows cmd将二进制文件识别为可执行文件。我能够在test上调用应用程序remove来删除自身。