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?
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
$
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
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
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
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.
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.)
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
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
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
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!
Pour zsh echo
setopt VERBOSE
et pour le débogage
setopt XTRACE
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.
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