188 votes

Exécuter une chaîne en tant que commande dans un script Bash

J'ai un script Bash qui construit une chaîne pour l'exécuter en tant que commande

Script:

#! /bin/bash

matchdir="/home/joao/robocup/runner_workdir/matches/testmatch/"

teamAComm="`pwd`/a.sh"
teamBComm="`pwd`/b.sh"
include="`pwd`/server_official.conf"
serverbin='/usr/local/bin/rcssserver'

cd $matchdir
illcommando="$serverbin include='$include' server::team_l_start = '${teamAComm}' server::team_r_start = '${teamBComm}' CSVSaver::save='true' CSVSaver::filename = 'out.csv'"

echo "running: $illcommando"
# $illcommando > server-output.log 2> server-error.log
$illcommando

qui semble ne pas fournir correctement les arguments à $serverbin.

Sortie du script :

running: /usr/local/bin/rcssserver include='/home/joao/robocup/runner_workdir/server_official.conf' server::team_l_start = '/home/joao/robocup/runner_workdir/a.sh' server::team_r_start = '/home/joao/robocup/runner_workdir/b.sh' CSVSaver::save='true' CSVSaver::filename = 'out.csv'
rcssserver-14.0.1

Droits d'auteur (C) 1995, 1996, 1997, 1998, 1999 Laboratoire électrotechnique.
2000 - 2009 Groupe de maintenance du simulateur de soccer RoboCup.

Utilisation: /usr/local/bin/rcssserver [[-[-]]namespace::option=value]
                                 [[-[-]][namespace::]help]
                                 [[-[-]]include=file]
Options:
    help
        afficher l'aide générique

    include=file
        analyser le fichier de configuration spécifié. Les fichiers de configuration
        ont le même format que les options de ligne de commande. Le
        fichier de configuration spécifié sera analysé avant toutes les
        options suivantes.

    serveur::help
        afficher l'aide détaillée pour le module "serveur"

    joueur::help
        afficher l'aide détaillée pour le module "joueur"

    CSVSaver::help
        afficher l'aide détaillée pour le module "CSVSaver"

Options de CSVSaver:
    CSVSaver::save=
        Si save est on/vrai, alors le sauvegardant tentera de sauvegarder les
        résultats dans la base de données. Sinon, il ne fera rien.

        valeur actuelle: false

    CSVSaver::filename=''
        Le fichier où sauvegarder les résultats. Si ce fichier n'existe pas
        il sera créé. Si le fichier existe déjà, les résultats
        seront ajoutés à la fin.

        valeur actuelle: 'out.csv'

si je colle simplement la commande /usr/local/bin/rcssserver include='/home/joao/robocup/runner_workdir/server_official.conf' server::team_l_start = '/home/joao/robocup/runner_workdir/a.sh' server::team_r_start = '/home/joao/robocup/runner_workdir/b.sh' CSVSaver::save='true' CSVSaver::filename = 'out.csv' (dans la sortie après "running: ") ça fonctionne bien.

0 votes

0 votes

Notez que dans certains cas, vous devez faire : echo | whateverCommands au lieu de simplement whateverCommands (par exemple, j'ai dû le faire comme ceci : | tail -`echo | whateverCommands`)

332voto

Arne Burmeister Points 8423

Vous pouvez utiliser eval pour exécuter une chaîne :

eval $illcommando

Si votre chaîne de commande doit être évaluée elle-même avant d'être exécutée - l'envelopper de guillemets :

eval "$votrecommande"
# par exemple eval "commande argument  --votre-option='$(date -d "$date" +%Y-%m-%d)'"

2 votes

Est-ce que eval renvoie la valeur de retour de la commande (valeur de retour, pas de la sortie de chaîne) ?

5 votes

eval est une commande malveillante dans tous les langages de programmation, alors utilisez-la avec prudence.

2 votes

eval "$illcommando", avec les guillemets, pour éviter que votre commande ne soit altérée avant son exécution. Essayez d'evaluer avec une valeur de illcommando='printf "%s\n" " * "' avec et sans les guillemets pour voir la différence.

31voto

Takman Points 371
your_command_string="..."
output=$(eval "$your_command_string")
echo "$output"

0 votes

Cela semble intéressant, mais cela ne fonctionne pas pour moi. $your_command_string ne s'exécute pas. Quel est le problème?

1 votes

A fonctionné pour moi. Je ne sais pas où le mettre, mais faites attention à ne pas mettre d'espace avant le = comme votre_chaîne_de_commande ="..."

28voto

Ola Points 109

Je place généralement les commandes entre parenthèses $(commandStr), si cela ne fonctionne pas, j'utilise le mode de débogage bash, exécuter le script comme bash -x script

6 votes

Je ne suis pas sûr à quoi commandStr fait référence, mais au moins cela n'a pas fonctionné pour moi. Il est préférable d'utiliser des exemples complets et fonctionnels.

0 votes

@RobinManoli Amélioré la clarté pour toi.

0 votes

CommandStr="ls -l" $(echo commandStr) #devrait fonctionner

12voto

ghostdog74 Points 86060

Ne mettez pas vos commandes dans des variables, exécutez-les simplement

matchdir="/home/joao/robocup/runner_workdir/matches/testmatch/"
PWD=$(pwd)
teamAComm="$PWD/a.sh"
teamBComm="$PWD/b.sh"
include="$PWD/server_official.conf"
serverbin='/usr/local/bin/rcssserver'    
cd $matchdir
$serverbin include=$include server::team_l_start = ${teamAComm} server::team_r_start=${teamBComm} CSVSaver::save='true' CSVSaver::filename = 'out.csv'

1 votes

A fait exactement cela. mais là où j'avais des variables qui devraient simplement être envoyées en tant qu'argument unique, j'ai utilisé "${arg}". exemple : server::team_l_start = "${teamAComm}"

0 votes

Pour de nombreuses tâches de débogage, il est judicieux d'avoir la commande dans une chaîne. Cela me fait gagner beaucoup de temps.

4voto

Si vous souhaitez mettre votre commande dans une variable, vous devriez lire FAQ #50.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X