使用重定向到文件启动分离命令
Start detached command with redirect to file
我正在尝试在分离进程中启动一个命令,以便它可以在 go 程序退出后继续。我需要将命令的输出重定向到一个文件。
我需要的是这样的:
func main() {
command := exec.Command("/tmp/test.sh", ">", "/tmp/out")
if err := command.Start(); err != nil {
fmt.Fprintln(os.Stderr, "Command failed.", err)
os.Exit(1)
}
fmt.Println("Process ID:", command.Process.Pid)
}
显然这样的重定向不起作用。因为我在启动 long 运行 命令后立即退出程序,所以我无法打开文件并将其绑定到 Stdout。
有什么方法可以实现这样的重定向吗?
也许你可以尝试使用这个:
打开文件(os.File
实现 io.Writer
),然后将其作为 command.Stdout
传递:
func main() {
command := exec.Command("./tmp/test.sh")
f, err := os.OpenFile("/tmp/out", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
fmt.Printf("error opening file: %v", err)
}
defer f.Close()
// On this line you're going to redirect the output to a file
command.Stdout = f
if err := command.Start(); err != nil {
fmt.Fprintln(os.Stderr, "Command failed.", err)
os.Exit(1)
}
fmt.Println("Process ID:", command.Process.Pid)
}
不确定这是否是适合您的情况的可行解决方案。我已经在本地试过了,它似乎有效...请记住,您的用户应该能够 create/update 文件。
您可以启动一个 shell 来执行您的命令/应用程序,并且您可以将其输出重定向到一个文件。 shell 将继续 运行 并执行您的脚本/应用程序,即使您的 Go 应用程序退出也是如此。
示例:
cmd := exec.Command("sh", "-c", "/tmp/test.sh > /tmp/out")
if err := cmd.Start(); err != nil {
panic(err)
}
fmt.Println("Process ID:", cmd.Process.Pid)
使用这个简单的 Go 应用程序对其进行测试(将 /tmp/test.sh
替换为您将其编译成的可执行二进制文件的名称):
package main
import ("fmt"; "time")
func main() {
for i := 0; i < 10; i++ {
fmt.Printf("%d.: %v\n", i, time.Now())
time.Sleep(time.Second)
}
}
这个应用只是每秒向标准输出打印一行。您可以看到输出文件是如何写入的,例如tail -f /tmp/out
.
请注意,您可以根据自己的喜好(以及 test.sh
脚本的指示)使用其他 shell 来执行脚本。
例如使用bash
:
cmd := exec.Command("/bin/bash", "-c", "/tmp/test.sh > /tmp/out")
// rest is unchanged
请注意,shell 执行的命令作为单个 string
参数传递,并且不会像执行它时那样分解为多个直接在命令提示符中。
我正在尝试在分离进程中启动一个命令,以便它可以在 go 程序退出后继续。我需要将命令的输出重定向到一个文件。
我需要的是这样的:
func main() {
command := exec.Command("/tmp/test.sh", ">", "/tmp/out")
if err := command.Start(); err != nil {
fmt.Fprintln(os.Stderr, "Command failed.", err)
os.Exit(1)
}
fmt.Println("Process ID:", command.Process.Pid)
}
显然这样的重定向不起作用。因为我在启动 long 运行 命令后立即退出程序,所以我无法打开文件并将其绑定到 Stdout。
有什么方法可以实现这样的重定向吗?
也许你可以尝试使用这个:
打开文件(os.File
实现 io.Writer
),然后将其作为 command.Stdout
传递:
func main() {
command := exec.Command("./tmp/test.sh")
f, err := os.OpenFile("/tmp/out", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
fmt.Printf("error opening file: %v", err)
}
defer f.Close()
// On this line you're going to redirect the output to a file
command.Stdout = f
if err := command.Start(); err != nil {
fmt.Fprintln(os.Stderr, "Command failed.", err)
os.Exit(1)
}
fmt.Println("Process ID:", command.Process.Pid)
}
不确定这是否是适合您的情况的可行解决方案。我已经在本地试过了,它似乎有效...请记住,您的用户应该能够 create/update 文件。
您可以启动一个 shell 来执行您的命令/应用程序,并且您可以将其输出重定向到一个文件。 shell 将继续 运行 并执行您的脚本/应用程序,即使您的 Go 应用程序退出也是如此。
示例:
cmd := exec.Command("sh", "-c", "/tmp/test.sh > /tmp/out")
if err := cmd.Start(); err != nil {
panic(err)
}
fmt.Println("Process ID:", cmd.Process.Pid)
使用这个简单的 Go 应用程序对其进行测试(将 /tmp/test.sh
替换为您将其编译成的可执行二进制文件的名称):
package main
import ("fmt"; "time")
func main() {
for i := 0; i < 10; i++ {
fmt.Printf("%d.: %v\n", i, time.Now())
time.Sleep(time.Second)
}
}
这个应用只是每秒向标准输出打印一行。您可以看到输出文件是如何写入的,例如tail -f /tmp/out
.
请注意,您可以根据自己的喜好(以及 test.sh
脚本的指示)使用其他 shell 来执行脚本。
例如使用bash
:
cmd := exec.Command("/bin/bash", "-c", "/tmp/test.sh > /tmp/out")
// rest is unchanged
请注意,shell 执行的命令作为单个 string
参数传递,并且不会像执行它时那样分解为多个直接在命令提示符中。