web-dev-qa-db-fra.com

Comment faire écho aux commandes du shell lors de leur exécution

Dans un script Shell, comment puis-je faire écho à toutes les commandes Shell appelées et développer des noms de variables?

Par exemple, à partir de la ligne suivante:

ls $DIRNAME

Je voudrais que le script exécute la commande et affiche ce qui suit

ls /full/path/to/some/dir

Le but est de sauvegarder un journal de toutes les commandes du shell appelées et de leurs arguments. Existe-t-il peut-être un meilleur moyen de générer un tel journal?

768
Jack Nock

set -x ou set -o xtrace développe les variables et affiche un petit signe + avant la ligne.

set -v ou set -o verbose ne développe pas les variables avant l'impression.

Utilisez set +x et set +v pour désactiver les paramètres ci-dessus.

Sur la première ligne du script, on peut mettre #!/bin/sh -x (ou -v) pour avoir le même effet que set -x (ou -v) ultérieurement dans le script.

Ce qui précède fonctionne également avec /bin/sh.

Voir le wiki de bash-hackers sur attributs set , et sur débogage .

$ cat shl
#!/bin/bash                                                                     

DIR=/tmp/so
ls $DIR

$ bash -x shl 
+ DIR=/tmp/so
+ ls /tmp/so
$
870
Tom

set -x vous donnera ce que vous voulez.

Voici un exemple de script Shell à illustrer:

#!/bin/bash
set -x #echo on

ls $PWD

Cela développe toutes les variables et affiche les commandes complètes avant la sortie de la commande.

sortie:

+ ls /home/user/
file1.txt file2.txt
281
radman

Vous pouvez également activer cette option pour certaines lignes de votre script en les enveloppant dans set -x et set +x par exemple.

#!/bin/bash
...
if [[ ! -e $OUT_FILE ]];
then
   echo "grabbing $URL"
   set -x
   curl --fail --noproxy $SERV -s -S $URL -o $OUT_FILE
   set +x
fi
82
shuckc

J'utilise une fonction pour echo puis lance la commande

#!/bin/bash
#function to display commands
exe() { echo "\$ $@" ; "$@" ; }

exe echo hello world

Quelles sorties

$ echo hello world
hello world

Modifier:

Pour des commandes plus compliquées, tuyaux, etc., vous pouvez utiliser eval:

#!/bin/bash
#function to display commands
exe() { echo "\$ ${@/eval/}" ; "$@" ; }

exe eval "echo 'Hello World' | cut -d ' ' -f1"

Quelles sorties

$  echo 'Hello World' | cut -d ' ' -f1
Hello
74
Soth

la réponse de shuckc pour l'écho de certaines lignes comporte quelques inconvénients: vous obtenez également la commande set +x suivante en écho, et vous perdez la possibilité de tester le code de sortie avec $? puisqu'il est écrasé par le set +x.

Une autre option consiste à exécuter la commande dans un sous-shell:

echo "getting URL..."
( set -x ; curl -s --fail $URL -o $OUTFILE )

if [ $? -eq 0 ] ; then
    echo "curl failed"
    exit 1
fi

qui vous donnera une sortie comme:

getting URL...
+ curl -s --fail http://example.com/missing -o /tmp/example
curl failed

Cela entraîne toutefois la surcharge de créer un nouveau sous-shell pour la commande.

48
bhassel

Une autre option consiste à mettre "-x" en haut de votre script plutôt que sur la ligne de commande:

$ cat ./server
#!/bin/bash -x
ssh user@server

$ ./server
+ ssh user@server
user@server's password: ^C
$

(Représentant insuffisant pour commenter la réponse choisie.)

33
nooj

Selon TLDP 's Guide Bash pour les débutants: Chapitre 2. Écrire et déboguer des scripts

2.3.1. Débogage sur l'ensemble du script

$ bash -x script1.sh

...

Il existe maintenant un débogueur à part entière pour Bash, disponible sur SourceForge . Ces fonctionnalités de débogage sont disponibles dans la plupart des versions modernes de Bash, à partir de la version 3.x.

2.3.2. Débogage sur une partie du script

set -x            # activate debugging from here
w
set +x            # stop debugging from here

...

Tableau 2-1. Vue d'ensemble des options de débogage définies

Short  | Long notation | Result  
-------+---------------+--------------------------------------------------------------
set -f | set -o noglob | Disable file name generation using metacharacters (globbing).  
set -v | set -o verbose| Prints Shell input lines as they are read.  
set -x | set -o xtrace | Print command traces before executing command.  

...

Sinon, ces modes peuvent être spécifiés dans le script lui-même, en ajoutant les options souhaitées à la première ligne de la déclaration Shell. Les options peuvent être combinées, comme c'est habituellement le cas avec les commandes UNIX:

#!/bin/bash -xv
19
Afriza N. Arief

Tapez "bash -x" sur la ligne de commande avant le nom du script bash. Par exemple, pour exécuter foo.sh, tapez:

bash -x foo.sh
17
Alan

Vous pouvez exécuter un script bash en mode débogage avec l'option - x.
Ceci fera écho à toutes les commandes.

bash -x example_script.sh

# Console output
+ cd /home/user
+ mv text.txt mytext.txt


Vous pouvez aussi enregistrer l’option -x dans le script. Spécifiez simplement l'option -x dans le Shebang.

######## example_script.sh ###################
#!/bin/bash -x

cd /home/user
mv text.txt mytext.txt

##############################################

./example_script.sh

# Console output
+ cd /home/user
+ mv text.txt mytext.txt



8
RenRen

Quelqu'un ci-dessus posté:

#!/bin/bash
#function to display commands
exe() { echo "\$ $@" ; "$@" ; }

et cela semble prometteur, mais je ne peux pas pour la vie de comprendre ce que ça fait. J'ai googlé et cherché dans la page man bash pour "\ $" et "$ @", et j'ai trouvé absolument rien.

Je comprends qu'une fonction est en train d'être créée, nommée "exec ()". Je comprends que les accolades marquent le début et la fin de la fonction. Je pense comprendre que le point-virgule marque un "retour difficile" entre une commande multiligne, de sorte que '{echo "\ $ $ @"; "$ @"; } 'devient, en substance:

{
echo "\$ $@"
"$@"

}

Quelqu'un peut-il me donner une brève explication ou un endroit où trouver cette information, étant donné que mon google-fu me manque?

(Sans vouloir commencer une nouvelle question sur un ancien fil, mon objectif est de rediriger la sortie vers un fichier. La méthode "set -x; [commandes]; set + x" fonctionnerait correctement pour moi, mais je peux " Je ne savais pas comment faire écho aux résultats dans un fichier au lieu de l’écran. J’essayais donc de comprendre cette autre méthode dans l’espoir de pouvoir utiliser très mal ma compréhension de la redirection/pipes/tee/etc pour faire la même chose.)

Merci!

PLUS TARD:

Avec un peu de bricolage, je crois que j'ai compris. Voici mon code équivalent pour ce dont j'ai besoin:

SCRIPT_LOG="\home\buddy\logfile.txt"
exe () {
  params="$@"                       # Put all of the command-line into "params"
  printf "%s\t$params" "$(date)" >> "$SCRIPT_LOG"   # Print the command to the log file
  $params                           # Execute the command
}

exe rm -rf /Library/LaunchAgents/offendingfile
exe rm -rf /Library/LaunchAgents/secondoffendingfile

Les résultats dans le fichier logfile.txt ressemblent à:

Tue Jun  7 16:59:57 CDT 2016  rm -rf /Library/LaunchAgents/offendingfile
Tue Jun  7 16:59:57 CDT 2016  rm -rf /Library/LaunchAgents/secondoffendingfile

Juste ce dont j'avais besoin. Merci!

5
DebianFanatic

Pour zsh echo

 setopt VERBOSE

et pour le débogage

 setopt XTRACE
3
zzapper

Pour csh et tcsh, vous pouvez set verbose ou set echo (ou vous pouvez également définir les deux, mais la plupart du temps, cela peut entraîner des duplications).

L'option verbose imprime à peu près l'expression exacte du shell que vous tapez.

L'option echo indique plus clairement ce qui sera exécuté lors du frai.


http://www.tcsh.org/tcsh.html/Special_Shell_variables.html#verbose

http://www.tcsh.org/tcsh.html/Special_Shell_variables.html#echo


Special Shell variables

verbose If set, causes the words of each command to be printed, after history substitution (if any). Set by the -v command line option.

echo If set, each command with its arguments is echoed just before it is executed. For non-builtin commands all expansions occur before echoing. Builtin commands are echoed before command and filename substitution, because these substitutions are then done selectively. Set by the -x command line option.

2
cnst
$ cat exampleScript.sh
#!/bin/bash
name="karthik";
echo $name;

bash -x exampleScript.sh

La sortie est la suivante:

enter image description here

1
Karthik Arun

Pour permettre l’écho des commandes composées, j’utilise la fonction eval ainsi que exe de Soth pour exécuter un écho, puis exécuter la commande. Ceci est utile pour les commandes piped qui ne montreraient sinon rien ou seulement la partie initiale de la commande piped.

Sans eval:

exe() { echo "\$ $@" ; "$@" ; }
exe ls -F | grep *.txt

Les sorties:

$
file.txt

Avec eval:

exe() { echo "\$ $@" ; "$@" ; }
exe eval 'ls -F | grep *.txt'

Quelles sorties

$ exe eval 'ls -F | grep *.txt'
file.txt
1
Paul Havens