A veces nuestros programas en Go necesitan generar otros procesos que no son de Go.
|
|
|
package main
|
|
import (
"fmt"
"io"
"os/exec"
)
|
|
func main() {
|
Comenzaremos con un comando simple que no toma
argumentos ni entrada y simplemente imprime algo en
stdout. El ayudante exec.Command crea un objeto
para representar este proceso externo.
|
dateCmd := exec.Command("date")
|
El método Output ejecuta el comando, espera a que
termine y recoge su salida estándar.
Si no hubo errores, dateOut contendrá bytes
con la información de la fecha.
|
dateOut, err := dateCmd.Output()
if err != nil {
panic(err)
}
fmt.Println("> date")
fmt.Println(string(dateOut))
|
Output y otros métodos de Command devolverán
*exec.Error si hubo un problema al ejecutar el
comando (por ejemplo, ruta incorrecta), y *exec.ExitError
si el comando se ejecutó pero terminó con un código de retorno
distinto de cero.
|
_, err = exec.Command("date", "-x").Output()
if err != nil {
switch e := err.(type) {
case *exec.Error:
fmt.Println("failed executing:", err)
case *exec.ExitError:
fmt.Println("command exit rc =", e.ExitCode())
default:
panic(err)
}
}
|
A continuación, veremos un caso un poco más complicado
donde canalizamos datos al proceso externo en su
stdin y recogemos los resultados de su stdout .
|
grepCmd := exec.Command("grep", "hello")
|
Aquí tomamos explícitamente tuberías de entrada/salida, iniciamos
el proceso, escribimos algo de entrada en él, leemos la
salida resultante y finalmente esperamos a que el proceso
termine.
|
grepIn, _ := grepCmd.StdinPipe()
grepOut, _ := grepCmd.StdoutPipe()
grepCmd.Start()
grepIn.Write([]byte("hello grep\ngoodbye grep"))
grepIn.Close()
grepBytes, _ := io.ReadAll(grepOut)
grepCmd.Wait()
|
Omitimos las comprobaciones de errores en el ejemplo anterior, pero
podrías usar el patrón habitual if err != nil para
todas ellas. También solo recogemos los resultados de StdoutPipe ,
pero podrías recoger los de StderrPipe de la misma manera.
|
fmt.Println("> grep hello")
fmt.Println(string(grepBytes))
|
Ten en cuenta que al generar comandos necesitamos
proporcionar un comando y un arreglo de argumentos explícitamente delimitados,
en vez de poder pasar solo una cadena de línea de comandos. Si quieres generar un comando completo
con una cadena, puedes usar la opción -c de bash :
|
lsCmd := exec.Command("bash", "-c", "ls -a -l -h")
lsOut, err := lsCmd.Output()
if err != nil {
panic(err)
}
fmt.Println("> ls -a -l -h")
fmt.Println(string(lsOut))
}
|