Maison >développement back-end >Golang >Exécuter des scripts bash dynamiques à l'aide de Go, y compris une déclaration de fonction sur une ligne

Exécuter des scripts bash dynamiques à l'aide de Go, y compris une déclaration de fonction sur une ligne

WBOY
WBOYavant
2024-02-05 23:09:11856parcourir

"使用

Contenu de la question

J'écris un exécuteur de tâches bash en go et il a un concept simple :

  1. Il lit taskfile , qui est un script bash contenant une définition de tâche (une simple déclaration de fonction bash)
  2. Il ajoute du contenu supplémentaire de manière dynamique
  3. Exécutez la commande selon les paramètres passés

Voici un exemple simplifié :

package main

import (
    "fmt"
    "os/exec"
)

func main() {
    //simplified for a dynamically built script
    taskfilecontent := "#!/bin/bash\n\ntask:foo (){\n  echo \"test\"\n}\n"
    // simplified for passed arguments
    task := "\ntask:foo"
    bash, _ := exec.lookpath("bash")
    cmd := exec.command(bash, "-c", "\"$(cat << eof\n"+taskfilecontent+task+"\neof\n)\"")
    fmt.println(cmd.string())
    out, _ := cmd.combinedoutput()
    fmt.println(string(out))
}

Mon problème maintenant est que si exécuté via go, cela ne fonctionne pas et j'obtiens cette erreur

task:foo: no such file or directory

Mais si j'exécute le script généré directement dans le shell, ça marche :

$ /opt/opt/homebrew/bin/bash -c "$(cat << EOF
#!/bin/bash

task:foo (){
  echo "test"
}

task:foo
EOF
)"

test   <-- printed out from the `task:foo` above

Qu'est-ce que je fais de mal ici ?


Bonne réponse


Tout d’abord : rien n’a de sens ici.

Vous n’obtiendrez rien que vous n’obtiendrez pas :

cmd := exec.command(bash, "-c", taskfilecontent+"\n"+task)

Si vous l'omettez, votre code sera plus simple.

Deuxième : Expliquez la raison

Lorsque vous exécutez en shell :

65be85239 lit 5

... les éléments entourant les $()" ne sont pas la syntaxe de la copie de bash qui est lancée, mais la syntaxe de la copie de bash qui analyse la commande. /em>. Ils indiquent à la copie de bash que le résultat de la substitution de commande sera transmis sous forme de chaîne, non affecté par le fractionnement de chaîne ou les caractères génériques.

De même, un seul argument pour $(cat <<eofeof 和最终的 )" 也是交互式 shell 的指令,而不是它调用的非交互式 shell。它是运行的交互式 shell cat (包含连接到其标准输入的heredoc内容的临时文件),读取 cat 副本的标准输出,然后将该数据替换为传递给 bash -c.

Dans votre programme go, vous n'avez pas de shell interactif, vous devez donc utiliser la syntaxe go (et non la syntaxe shell) pour effectuer toutes ces étapes. En ce qui concerne ces étapes, il n'y a aucune raison d'aller au premier emplacement (pas besoin d'écrire le fichier de données dans un fichier temporaire, pas besoin de /bin/cat lire le contenu de ce fichier, pas besoin d'utiliser un sous-processus pour exécuter substitution de commande pour générer une chaîne (qui est ensuite placée dans la ligne de commande du shell final), il serait donc plus sage d'ignorer toutes ces étapes.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer