英文:
How to run a CLI command from Go?
问题
如何在Go程序中运行Gulp任务?
这是我在典型终端中运行的命令:
gulp serv.dev
我该如何从Golang运行这行简单的代码:
package main
import (
"net/http"
"github.com/julienschmidt/httprouter"
"fmt"
)
func main() {
// 我应该在这里放什么来在后台打开终端并运行 `gulp serv.dev`?
}
英文:
How do I run a Gulp task from a Go program?
This is the command I run from a typical terminal:
gulp serv.dev
How could I run this simple line of code from golang:
package main
import (
"net/http"
"github.com/julienschmidt/httprouter"
"fmt"
)
func main() {
// What do I put here to open terminal in background and run `gulp serv.dev`?
}
答案1
得分: 34
你要找的是exec.Command。
你需要生成一个运行gulp
任务的进程。
可以按照以下方式实现:
package main
import (
"os/exec"
)
func main() {
cmd := exec.Command("gulp", "serv.dev")
if err := cmd.Run(); err != nil {
log.Fatal(err)
}
}
英文:
What you're looking for is exec.Command
You'll pretty much want to spawn off a process that will run your gulp
task.
This can be done like so:
package main
import (
"os/exec"
)
func main() {
cmd := exec.Command("gulp", "serv.dev")
if err := cmd.Run(); err != nil {
log.Fatal(err)
}
}
答案2
得分: 12
请看一下exec。针对你的用例:
package main
import (
"net/http"
"github.com/julienschmidt/httprouter"
"fmt"
"os/exec"
"log"
)
func main() {
out, err := exec.Command("gulp", "serv.dev").Output()
if err != nil {
log.Fatal(err)
}
fmt.Printf("The date is %s\n", out)
}
英文:
Take a look at exec. For your use case:
package main
import (
"net/http"
"github.com/julienschmidt/httprouter"
"fmt"
"os/exec"
"log"
)
func main() {
out, err := exec.Command("gulp", "serv.dev").Output()
if err != nil {
log.Fatal(err)
}
fmt.Printf("The date is %s\n", out)
}
答案3
得分: 1
最可能你需要exec包
cmd := exec.Command("gulp", "serv.dev")
err := cmd.Run()
在exec.Command的示例中可以看到。他们解释了如何传递参数和读取输出。
英文:
Most probably you need exec package
cmd := exec.Command("gulp", "serv.dev")
err := cmd.Run()
Take a look at example at exec.Command. They explained how to pass parameters and read the output.
答案4
得分: 1
更通用,输出更好。
使用exec.Command和缓冲区来记录输出,并且只在有用时显示输出。
甚至可以通过使用可变参数(即任意数量的参数)使函数适用于任何命令。
适当标记未处理的错误,这样如果命令失败,你就会知道是哪个命令以及原因。
最后请注意,尽管Go语言很表达力,但它是一种相当原始的语言。它不会为你做任何事情。你将不得不自己编写大量代码。
示例代码:
package main
import (
"bytes"
"fmt"
"os"
"os/exec"
"runtime"
"strings"
)
func main() {
runCommand(currentFunction(), "ping", "-c1", "google.commm")
}
func commandErrorMessage(stderr bytes.Buffer, program string) string {
message := string(stderr.Bytes())
if len(message) == 0 {
message = "the command doesn't exist: " + program + "\n"
}
return message
}
func currentFunction() string {
counter, _, _, success := runtime.Caller(1)
if !success {
println("functionName: runtime.Caller: failed")
os.Exit(1)
}
return runtime.FuncForPC(counter).Name()
}
func printCommandError(stderr bytes.Buffer, callerFunc string, program string, args ...string) {
printCommandErrorUbication(callerFunc, program, args...)
fmt.Fprintf(os.Stderr, "%s", commandErrorMessage(stderr, program))
}
func printCommandErrorUbication(callerFunc string, program string, args ...string) {
format := "error at: %s: %s %s\n"
argsJoined := strings.Join(args, " ")
fmt.Fprintf(os.Stderr, format, callerFunc, program, argsJoined)
}
func runCommand(callerFunc string, program string, args ...string) {
command := exec.Command(program, args...)
var stderr bytes.Buffer
command.Stderr = &stderr
fail := command.Run()
if fail != nil {
printCommandError(stderr, callerFunc, program, args...)
os.Exit(1)
}
}
示例运行:
$ go run test.go
error at: main.main: ping -c1 google.commm
ping: google.commm: Name or service not known
exit status 1
英文:
More generic, better output.
Use the exec.Command, along with buffers to record output and display it only when useful.
You can even make the function work with any command by using variadic arguments, aka arguments of an arbitrary quantity of elements.
Label unhanded errors appropriately, so if a command fails you are told which one and why.
Lastly note that Go, although expressive, is a quite raw language. It holds your hand for nothing. You will have to program plenty by yourself.
Example code:
package main
import (
"bytes"
"fmt"
"os"
"os/exec"
"runtime"
"strings"
)
func main() {
runCommand(currentFunction(), "ping", "-c1", "google.commm")
}
func commandErrorMessage(stderr bytes.Buffer, program string) string {
message := string(stderr.Bytes())
if len(message) == 0 {
message = "the command doesn't exist: " + program + "\n"
}
return message
}
func currentFunction() string {
counter, _, _, success := runtime.Caller(1)
if !success {
println("functionName: runtime.Caller: failed")
os.Exit(1)
}
return runtime.FuncForPC(counter).Name()
}
func printCommandError(stderr bytes.Buffer, callerFunc string, program string, args ...string) {
printCommandErrorUbication(callerFunc, program, args...)
fmt.Fprintf(os.Stderr, "%s", commandErrorMessage(stderr, program))
}
func printCommandErrorUbication(callerFunc string, program string, args ...string) {
format := "error at: %s: %s %s\n"
argsJoined := strings.Join(args, " ")
fmt.Fprintf(os.Stderr, format, callerFunc, program, argsJoined)
}
func runCommand(callerFunc string, program string, args ...string) {
command := exec.Command(program, args...)
var stderr bytes.Buffer
command.Stderr = &stderr
fail := command.Run()
if fail != nil {
printCommandError(stderr, callerFunc, program, args...)
os.Exit(1)
}
}
Example run:
$ go run test.go
error at: main.main: ping -c1 google.commm
ping: google.commm: Name or service not known
exit status 1
答案5
得分: 0
我将为那些要运行二进制文件的人留下一个小例子:
package main
import (
"fmt"
"log"
"os"
"os/exec"
"path"
"path/filepath"
"runtime"
)
func main() {
ex, err := os.Executable()
if err != nil {
panic(err)
}
exPath := filepath.Dir(ex)
var command = path.Join(exPath, "libexec")
os := runtime.GOOS
switch os {
case "windows":
command += ".exe"
case "darwin":
command += ""
case "linux":
command = "." + command
default:
fmt.Printf("%s.\n", os)
}
// 这里缺少一个检查可执行文件是否存在或是否在路径变量中的实现
out, err := exec.Command(command).Output()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Out: %s", out)
}
英文:
I'll leave a small example for those who are going to run a binary:
package main
import (
"fmt"
"log"
"os"
"os/exec"
"path"
"path/filepath"
"runtime"
)
func main() {
ex, err := os.Executable()
if err != nil {
panic(err)
}
exPath := filepath.Dir(ex)
var command = path.Join(exPath, "libexec")
os := runtime.GOOS
switch os {
case "windows":
command += ".exe"
case "darwin":
command += ""
case "linux":
command = "." + command
default:
fmt.Printf("%s.\n", os)
}
// it lacks to implement a check if the executable exists or
// is in one of the path variables
out, err := exec.Command(command).Output()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Out: %s", out)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论