Nuovi Processi

Il package exec permette l'esecuzione di comandi di sistema operativo da dentro i programmi Go.

La funzione Command() registra il comando in un oggetto comando.

La funzione Output() lo esegue e ritornare lo standard output del comando ed un errore.

Prima dell'esecuzione del comando è possibile la ridirezione dello standard input e output da e in pipes.

Il comando viene poi lanciato con la funzione Start() dell'oggetto comando.

(620spawning-processes.go):

package main

import "fmt"
import "io/ioutil"
import "os/exec"

func main() {

	// Esecuzione di comando senza argomenti
	dateCmd := exec.Command("date")

	// Output ed errore del comando
	dateOut, err := dateCmd.Output()
	if err != nil {
		panic(err)
	}
	fmt.Println("> date")
	fmt.Println(string(dateOut))

	// Comando con argomento
	grepCmd := exec.Command("grep", "hello")

	// Input del comando da stdin
	grepIn, _ := grepCmd.StdinPipe()
	// Output a stdout
	grepOut, _ := grepCmd.StdoutPipe()
	// Lancio del comando
	grepCmd.Start()
	// Fornire l'input
	grepIn.Write([]byte("hello grep\ngoodbye grep"))
	// Chiudere l'input - importante
	grepIn.Close()
	// Lettura dell'output risultante
	grepBytes, _ := ioutil.ReadAll(grepOut)
	// Attesa della terminazione del processo - importante
	grepCmd.Wait()

	// Ognuno dei comandi sopra può ritornare un errore
	// Controllo omesso in questo esempio

	// Stampa del risultato
	fmt.Println("> grep hello")
	fmt.Println(string(grepBytes))

	// Invocazione di shell e passaggio di argomenti
	// alla shell - argomenti: un'unica stringa
	lsCmd := exec.Command("bash", "-c", "ls -a -l -h")
	lsOut, err := lsCmd.Output()
	if err != nil {
		panic(err)
	}
	fmt.Println("(through shell)> ls -a -l -h")
	fmt.Println(string(lsOut))

	// Invocazione diretta: ogni opzione o argomento
	// è una stringa separata
	lsCmd = exec.Command("ls", "-a", "-l", "-h")
	lsOut, err = lsCmd.Output()
	if err != nil {
		panic(err)
	}
	fmt.Println("(standalone)> ls -a -l -h")
	fmt.Println(string(lsOut))
}

Una pipe è composta da un oggetto di input ed un oggetto di output.

Quando l'input è da una pipe è importante chiuderlo esplicitamente con la funzione Close() dell'oggetto di input che invia un End Of File (EOF).

La funzione ReadAll() dell'oggetto di output legge l'output finale di una pipe.

Dato che una pipe è una serie di processi Linux indipendenti e sincronizzati, è importante attendere la terminazione di tutti questi processi con la funzione Wait() dell'oggetto comando.