exec.Cmd în Go

Structura care descrie o comandă externă: programul, argumentele, directorul, mediul și intrarea/ieșirile ei.

Sintaxă
type Cmd struct {
    Path   string
    Args   []string
    Env    []string
    Dir    string
    Stdin  io.Reader
    Stdout io.Writer
    Stderr io.Writer
    // ...
}

Ce face exec.Cmd

exec.Cmd se creează cu exec.Command și se configurează prin câmpuri, înainte de pornire. Cele mai folosite: Dir (directorul în care rulează; gol = directorul curent), Env (mediul; nil = mediul procesului curent), Stdin (de unde citește), Stdout și Stderr (unde scrie; nil = ieșirea este aruncată).

După rulare, cmd.ProcessState conține informații despre proces (codul de ieșire), iar cmd.Process permite oprirea lui (cmd.Process.Kill()). Un Cmd poate fi folosit o singură dată.

Ce returnează

Nu se aplică (este un tip).

Exemple

Exemplul 1: Director, mediu, intrare și ieșire

package main

import (
    "bytes"
    "fmt"
    "os"
    "os/exec"
    "strings"
)

func main() {
    os.Mkdir("lucru", 0o755)

    cmd := exec.Command("sh", "-c", "pwd | xargs basename; echo \"client: $CLIENT\"; tr a-z A-Z")
    cmd.Dir = "lucru"
    cmd.Env = append(os.Environ(), "CLIENT=Ana")
    cmd.Stdin = strings.NewReader("comanda 1042 confirmata\n")
    var out bytes.Buffer
    cmd.Stdout = &out

    if err := cmd.Run(); err != nil {
        fmt.Println("eroare:", err)
        return
    }
    fmt.Print(out.String())
    fmt.Println("cod de ieșire:", cmd.ProcessState.ExitCode())
}

Rezultat

lucru
client: Ana
COMANDA 1042 CONFIRMATA
cod de ieșire: 0

Exemplul 2: Ieșirea direct pe ecran

Legăm ieșirea comenzii de os.Stdout, ca utilizatorul să o vadă imediat.

package main

import (
    "fmt"
    "os"
    "os/exec"
)

func main() {
    cmd := exec.Command("printf", "%s\\n", "Iași", "Cluj", "Brașov")
    cmd.Stdout = os.Stdout
    fmt.Println("rulez:", cmd.String())
    if err := cmd.Run(); err != nil {
        fmt.Println("eroare:", err)
    }
}

Rezultat

rulez: /usr/bin/printf %s\n Iași Cluj Brașov
Iași
Cluj
Brașov

Greșeli frecvente

  • Setezi cmd.Env doar cu variabilele tale ([]string{"MOD=test"}). Comanda pierde PATH, HOME etc.; pornește de la os.Environ().
  • Modifici câmpurile după Start. Configurarea trebuie făcută înainte de pornire.

Comenzi înrudite

  • exec.Command: Pregătește rularea unui program extern cu argumentele date; programul pornește abia la Run, Output sau Start.
  • exec.Cmd.Run: Pornește comanda și așteaptă să se termine; returnează eroare dacă nu a pornit sau a ieșit cu cod diferit de 0.
  • exec.Cmd.Start: Start pornește comanda fără să aștepte; Wait așteaptă terminarea ei și eliberează resursele.
  • exec.Cmd.StdoutPipe: Returnează un Reader legat de ieșirea comenzii, ca să citești rezultatul pe măsură ce apare.
  • os.Environ: Returnează toate variabilele de mediu, ca o listă de texte de forma NUME=valoare.