J'ai un tas de commandes systèmes qui ressemblent un peu à l'ajout de nouveau contenu à un fichier. J'ai écrit un script simple pour exécuter des commandes système, qui fonctionne bien s'il y a des mots simples tels que 'ls', 'date' etc. Mais si la commande est supérieure à cette valeur, le programme meurt.
Ce qui suit est le code
package main
import (
"fmt"
"os/exec"
"sync"
)
func exe_cmd(cmd string, wg *sync.WaitGroup) {
fmt.Println(cmd)
c = cmd.Str
out, err := exec.Command(cmd).Output()
if err != nil {
fmt.Println("error occured")
fmt.Printf("%s", err)
}
fmt.Printf("%s", out)
wg.Done()
}
func main() {
wg := new(sync.WaitGroup)
wg.Add(3)
x := []string{"echo newline >> foo.o", "echo newline >> f1.o", "echo newline >> f2.o"}
go exe_cmd(x[0], wg)
go exe_cmd(x[1], wg)
go exe_cmd(x[2], wg)
wg.Wait()
}
Ce qui suit est l'erreur que je vois
exec: "echo newline >> foo.o": executable file not found in $PATHexec:
"echo newline >> f2.o": executable file not found in $PATHexec:
"echo newline >> f1.o": executable file not found in $PATH
Je suppose que cela peut être dû au fait que nous n’avons pas envoyé les commandes et les arguments séparément ( http://golang.org/pkg/os/exec/#Command ). Je me demande comment subvertir cela, puisque je ne sais pas combien d'arguments seront présents dans ma commande et doivent être exécutés.
J'ai trouvé un moyen relativement décent d'atteindre le même objectif.
out, err := exec.Command("sh","-c",cmd).Output()
Travaille pour moi jusqu'à maintenant. Nous trouvons toujours de meilleurs moyens d’atteindre le même objectif.
Edit1:
Enfin, un moyen plus facile et efficace (du moins jusqu'à présent) serait comme ceci
func exe_cmd(cmd string, wg *sync.WaitGroup) {
fmt.Println("command is ",cmd)
// splitting head => g++ parts => rest of the command
parts := strings.Fields(cmd)
head := parts[0]
parts = parts[1:len(parts)]
out, err := exec.Command(head,parts...).Output()
if err != nil {
fmt.Printf("%s", err)
}
fmt.Printf("%s", out)
wg.Done() // Need to signal to waitgroup that this goroutine is done
}
Merci aux arguments variadiques et aux gens qui me l'ont signalé :)
Pour exec.Command()
, le premier argument doit être le chemin d'accès à l'exécutable. Ensuite, les arguments restants seront fournis en tant qu’arguments à l’exécutable. Utilisez strings.Fields()
pour diviser le mot en une chaîne [].
package main
import (
"fmt"
"os/exec"
"sync"
"strings"
)
func exe_cmd(cmd string, wg *sync.WaitGroup) {
fmt.Println(cmd)
parts := strings.Fields(cmd)
out, err := exec.Command(parts[0],parts[1]).Output()
if err != nil {
fmt.Println("error occured")
fmt.Printf("%s", err)
}
fmt.Printf("%s", out)
wg.Done()
}
func main() {
wg := new(sync.WaitGroup)
commands := []string{"echo newline >> foo.o", "echo newline >> f1.o", "echo newline >> f2.o"}
for _, str := range commands {
wg.Add(1)
go exe_cmd(str, wg)
}
wg.Wait()
}
Voici une approche alternative qui écrit simplement toutes les commandes dans un fichier puis exécute ce fichier dans le contexte du nouveau répertoire de sortie créé.
package main
import (
"os"
"os/exec"
"fmt"
"strings"
"path/filepath"
)
var (
output_path = filepath.Join("./output")
bash_script = filepath.Join( "_script.sh" )
)
func checkError( e error){
if e != nil {
panic(e)
}
}
func exe_cmd(cmds []string) {
os.RemoveAll(output_path)
err := os.MkdirAll( output_path, os.ModePerm|os.ModeDir )
checkError(err)
file, err := os.Create( filepath.Join(output_path, bash_script))
checkError(err)
defer file.Close()
file.WriteString("#!/bin/sh\n")
file.WriteString( strings.Join(cmds, "\n"))
err = os.Chdir(output_path)
checkError(err)
out, err := exec.Command("sh", bash_script).Output()
checkError(err)
fmt.Println(string(out))
}
func main() {
commands := []string{
"echo newline >> foo.o",
"echo newline >> f1.o",
"echo newline >> f2.o",
}
exe_cmd(commands)
}
out, _ := exec.Command("sh", "-c", "date +\"%Y-%m-%d %H:%M:%S %Z\"").Output()
exec.Command("sh","-c","ls -al -t | grep go >>test.txt").Output()
fmt.Printf("%s\n\n",out)
Cas de couple testés et tout fonctionne bien. Cela vous sauvera la vie si vous utilisez des commandes Shell rapides dans votre programme. Non testé avec des cas complexes.
echo
n'est pas une commande système. C'est un shell intégré, et donc pas directement accessible depuis exec
out, _: = exec.Command ("sh", "-c", "echo test1232 | grep 12"). Sortie ()
fmt.Printf ("% s", out)
^^ ça marche