Esegui una stringa come comando all'interno di uno script Bash


152

Ho uno script Bash che crea una stringa da eseguire come comando

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

che non sembra fornire correttamente gli argomenti a $serverbin.

Output dello 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

Copyright (C) 1995, 1996, 1997, 1998, 1999 Electrotechnical Laboratory.
2000 - 2009 RoboCup Soccer Simulator Maintenance Group.


Usage: /usr/local/bin/rcssserver [[-[-]]namespace::option=value]
                                 [[-[-]][namespace::]help]
                                 [[-[-]]include=file]
Options:
    help
        display generic help

    include=file
        parse the specified configuration file.  Configuration files
        have the same format as the command line options. The
        configuration file specified will be parsed before all
        subsequent options.

    server::help
        display detailed help for the "server" module

    player::help
        display detailed help for the "player" module

    CSVSaver::help
        display detailed help for the "CSVSaver" module

CSVSaver Options:
    CSVSaver::save=<on|off|true|false|1|0|>
        If save is on/true, then the saver will attempt to save the
        results to the database.  Otherwise it will do nothing.

        current value: false

    CSVSaver::filename='<STRING>'
        The file to save the results to.  If this file does not
        exist it will be created.  If the file does exist, the results
        will be appended to the end.

        current value: 'out.csv'

se ho appena incollato il comando /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'(nell'output dopo "runnning:") funziona benissimo.



Si noti che in alcuni casi, è necessario fare: echo | whateverCommandsinvece di whateverCommands(per esempio, ho dovuto fare in questo modo: | tail -`echo | whateverCommands`)
Andrew

Risposte:


279

Puoi usare evalper eseguire una stringa:

eval $illcommando

2
Eval inoltra il valore restituito dal comando ( valore restituito , non output stringa)?
Tomáš Zato - Ripristina Monica il

3
evalè un comando malvagio in tutti i linguaggi di programmazione quindi usalo con cautela.
Krishnadas PC

1
eval "$illcommando", tra virgolette , per non modificare il comando prima che venga eseguito. Prova evalcon un valore di illcommando='printf "%s\n" " * "'con e senza virgolette per vedere la differenza.
Charles Duffy,

@ TomášZato-ReinstateMonica Sì, inoltra il valore restituito dal comando. Tuttavia, NON imposta "${PIPESTATUS[@]}"correttamente la variabile in bash. Tuttavia, set -o pipefailprovoca correttamente la evalrestituzione di un codice di uscita non riuscito se il comando contiene un comando non riuscito reindirizzato a un comando riuscito.
Cameron Hudson,

Stavo cercando di fare qualcosa del genere grep -E '$filter' unfiltered.txt > filtered.txt, non avevo idea del perché funzionasse dalla riga di comando e perché con i valori calcolati non funzionasse nello script bash. La tua risposta ha salvato la mia sceneggiatura. Aggiungerò qui anche alcuni esempi documentati che ho usato per capire meglio come funziona eval. linuxhint.com/bash_eval_command
student0495

28

Di solito inserisco i comandi tra parentesi $(commandStr), se ciò non aiuta a trovare la modalità debug bash eccezionale, eseguo lo script comebash -x script


4
Non sono sicuro a cosa si riferisca commandStr, ma almeno questo non ha funzionato per me. È meglio se usi esempi di lavoro completi.
Robin Manoli,

@RobinManoli Migliorata la chiarezza per te.
Andrew,

18
your_command_string="..."
output=$(eval "$your_command_string")
echo "$output"

10

non mettere i tuoi comandi in variabili, basta eseguirlo

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
fatto proprio quello. ma dove avevo variabili che dovrebbero andare proprio come un singolo argomento che ho fatto "${arg}". esempio: server :: team_l_start = "$ {teamAComm}"
João Portela

1

./me cast raise_dead ()

Stavo cercando qualcosa del genere, ma avevo anche bisogno di riutilizzare la stessa stringa meno due parametri, quindi ho finito con qualcosa del tipo:

my_exe ()
{
    mysql -sN -e "select $1 from heat.stack where heat.stack.name=\"$2\";"
}

Questo è qualcosa che uso per monitorare la creazione di stack di calore openstack. In questo caso mi aspetto due condizioni, un'azione 'CREA' e uno stato 'COMPLETO' su uno stack chiamato "Somestack"

Per ottenere quelle variabili posso fare qualcosa del tipo:

ACTION=$(my_exe action Somestack)
STATUS=$(my_exe status Somestack)
if [[ "$ACTION" == "CREATE" ]] && [[ "$STATUS" == "COMPLETE" ]]
...

0

Ecco il mio script build buildle che esegue le stringhe memorizzate negli heredocs :

current_directory=$( realpath "." )
GENERATED=${current_directory}/"GENERATED"
build_gradle=$( realpath build.gradle )

## touch because .gitignore ignores this folder:
touch $GENERATED

COPY_BUILD_FILE=$( cat <<COPY_BUILD_FILE_HEREDOC

    cp 
        $build_gradle 
        $GENERATED/build.gradle

COPY_BUILD_FILE_HEREDOC
)
$COPY_BUILD_FILE

GRADLE_COMMAND=$( cat <<GRADLE_COMMAND_HEREDOC

    gradle run

        --build-file       
            $GENERATED/build.gradle

        --gradle-user-home 
            $GENERATED  

        --no-daemon

GRADLE_COMMAND_HEREDOC
)
$GRADLE_COMMAND

I ")" solitari sono piuttosto brutti. Ma non ho idea di come riparare quell'aspetto asetico.


0

Per vedere tutti i comandi che vengono eseguiti dallo script, aggiungi il -xflag alla tua linea shabang ed esegui normalmente il comando:

#! /bin/bash -x

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
$serverbin include="$include" server::team_l_start="${teamAComm}" server::team_r_start="${teamBComm}" CSVSaver::save='true' CSVSaver::filename='out.csv'

Quindi se a volte vuoi ignorare l'output di debug, reindirizza stderrda qualche parte.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.