J'ai un script bash avec diverses instructions if basées sur des arguments de ligne de commande que je transmets lors de l'appel. Avoir une sorte de sortie sur les commandes en cours d'exécution est utile pour confirmer le flux à travers toutes ces instructions if, mais ma solution actuelle me donne trop d' informations.
L'utilisation set -v
dans le script était quelque peu utile pour voir les commandes imprimées à l'écran lorsqu'elles étaient exécutées dans le script, mais j'obtiens trop de commandes. C'est presque comme une copie entière du script.
Je veux une sortie qui montre quelles commandes sont exécutées, mais je ne veux pas voir les commentaires, les nouvelles lignes, les expressions dans les instructions if, etc.
Existe-t-il un moyen de passer toutes les sorties possibles générées par l'option -v via une expression régulière avant d'être imprimées? Ou une autre solution pour que bash ne produise que des commandes d'un certain "type" (par exemple, qui utilisent des exécutables et pas seulement des instructions, commentaires, etc.?)
[1] /programming/257616/sudo-changes-path-why m'a été très utile à ce sujet et c'est là que j'ai obtenu la suggestion d' set -v
utilisation.
Modifier :
Un script similaire (mais pas identique) à celui que j'utilise:
#!/bin/bash
#get verbose command output
set -v
env=$1
if [ "$env" == "dev" ]; then
python ascript.py
fi
if [ "$env" == "prod" ]; then
#launching in prod will most likely fail if not run as root. Warn user if not running as root.
if [ $EUID -ne 0 ]; then
echo "It doesn't look like you're running me as root. This probably won't work. Press any key to continue." > /dev/stderr
read input
fi
#"stop" any existing nginx processes
pkill -f nginx
nginx -c `pwd`/conf/artfndr_nginx.conf
fi
Je veux seulement 2 ensembles possibles de lignes de sortie de ce script. La première:
python ascript.py
La deuxième:
pkill -f nginx
nginx -c /some/current/directory/conf/artfndr_nginx.conf
la source
set -v
sortie vous souhaitez et lesquelles vous ne le souhaitez pas.Réponses:
Lorsque j'écris des scripts bash plus complexes, j'utilise une petite fonction pour exécuter des commandes qui imprimeront également les commandes exécutées dans un fichier journal:
Ensuite, dans mon script, j'exécute des commandes comme celle-ci:
Si vous ne voulez pas qu'une commande soit imprimée, exécutez-la normalement.
Vous pouvez soit définir le
$LOG
sur un nom de fichier, soit le supprimer et imprimer sur stdout ou stderr.la source
v python ascript.py
sans avoir à les mettre entre guillemets et à perdre mon code vim en surbrillanceeval ..... || ok=1
: définira ok sur "1" uniquement lorsque "eval ..." échoue ?? Peut-être que vous vouliez dire "&&"? Et si vous vouliez dire cela, ajoutez un "ok = 0" avant la ligne d'évaluation, afin qu'il soit "réinitialisé" à chaque fois. Ou simplement renommer "ok" en "erreur"? il semble que c'est ce que l'on voulait dire ici. Donc au final:eval "$@" 2>> "$LOG" && error=0 || error=1
ok
variable qui arrêtera le script si une commande échoue. Comme cela n'était pas pertinent ici, je l'ai supprimé mais j'ai oublié de le supprimer|| ok=1
. Merci, réparé maintenant."
entourage de l'instruction eval, car la commande est déjà entourée de"
sUtilisez un sous-shell, c'est-à-dire:
Par exemple:
impressions
la source
set -x; cmd; set +x
à plusieurs raisons. Tout d'abord, il ne se réinitialise passet -x
s'il était déjà allumé. Deuxièmement, la fin du script à l'intérieur ne provoque pas l'exécution d'interruptions avec des paramètres détaillés.J'ai vu des méthodes similaires à celles de @ terdon. Ce sont les débuts de ce que les langages de programmation de niveau supérieur appellent les enregistreurs, et proposent des bibliothèques complètes, telles que log4J (Java), log4Perl (Perl), etc.
Vous pouvez obtenir quelque chose de similaire en utilisant
set -x
Bash comme vous l'avez mentionné, mais vous pouvez l'utiliser pour augmenter le débogage juste un sous-ensemble de commandes en enveloppant des blocs de code avec eux comme ça.Exemples
Voici un motif à doublure que vous pouvez utiliser.
Vous pouvez les envelopper comme ceci pour plusieurs commandes dans un script.
Log4Bash
La plupart des gens sont inconscients, mais Bash a également un log4 *, Log4Bash . Si vous avez des besoins plus modestes, cela peut valoir la peine de le configurer.
Exemples
Voici quelques exemples d'utilisation de log4bash.
Log4sh
Si vous voulez ce que je qualifierais de plus de la pleine puissance d'un framework log4 *, j'essaierais Log4sh .
extrait
Log4sh prend en charge plusieurs shells, pas seulement Bash.
Il a également été testé sur plusieurs systèmes d'exploitation, pas seulement Linux.
L'utilisation d'un framework log4 * prendra un certain temps à apprendre, mais cela en vaut la peine si vous avez des besoins plus exigeants de votre journalisation. Log4sh utilise un fichier de configuration dans lequel vous pouvez définir des annexes et contrôler la mise en forme de la sortie qui apparaîtra.
Exemple
Maintenant, quand je l'exécute:
REMARQUE: ce qui précède configure l'appender dans le cadre du code. Si vous le souhaitez, cela peut être extrait dans son propre fichier,
log4sh.properties
etc.Consultez l' excellente documentation de Log4sh si vous avez besoin de plus de détails.
la source
set
commandes que j'aurais besoin d'introduire, en alternant autour des commentaires, etc., donc avoir juste une fonction en haut de mon script, avec un seul appel de fonction de caractère ajouté à toutes les lignes "importantes" du script me semblaient plus propres pour l'instant. (caractère unique car la fonction a un nom de caractère unique)echo
dans ma propre fonction,mecho
puis à passer un commutateur dans le programme appelé-v
verbose lorsque je veux désactiver les choses. Je peux également le contrôler avec un commutateur de 2ème argument qui spécifie le nom de la fonction, j'ai donc 2 axes sur lesquels contrôler la journalisation. C'est souvent la passerelle pour vouloir log4bash.set -x
imprime les commandes lorsqu'elles sont exécutées. Il n'imprime pas de commentaires.set -x
est pratique pour le débogage (contrairement àset -v
ce qui n'est pas très utile). Zsh a une meilleure sortieset -x
que bash, par exemple, il montre quelle fonction est en cours d'exécution et le numéro de ligne source.Vous pouvez
trap
DEBUG
ensuite tester laBASH_COMMAND
variable . Ajoutez ceci en haut du script:Le code est lisible; il teste simplement si le premier argument commence par
python
oupkill
, et l'imprime si c'est le cas. Et le piège utiliseBASH_COMMAND
(qui contient la commande qui sera exécutée) comme premier argument.Notez que si
case
vous utilisez des globes, vous pouvez tout aussi facilement faire:Et utilisez des expressions régulières.
la source
Ceci est une version révisée de la fonction soignée de Steven Penny. Il imprime ses arguments en couleur et les cite au besoin. Utilisez-le pour faire écho de manière sélective aux commandes que vous souhaitez tracer. Étant donné que les guillemets sont générés, vous pouvez copier des lignes imprimées et les coller sur le terminal pour une réexécution immédiate pendant que vous déboguez un script. Lisez le premier commentaire pour savoir ce que j'ai changé et pourquoi.
Exemple d'utilisation avec sortie:
# xc echo "a b" "c'd" "'" '"' "fg" '' " " "" \# this line prints in green
echo 'a b' c\'d \' '"' fg '' ' ' '' '#' this line prints in green
a b c'd ' " fg # this line prints in green
La deuxième ligne au-dessus s'imprime en vert et peut être copiée-collée pour reproduire la troisième ligne.
Remarques supplémentaires
@ Xc original de Steven-Penny est intelligent et il mérite tous les crédits pour cela. Cependant, j'ai remarqué quelques problèmes, mais je n'ai pas pu commenter son message directement car je n'ai pas assez de réputation. J'ai donc proposé une modification à son article, mais les critiques ont rejeté ma modification. Par conséquent, j'ai eu recours à la publication de mes commentaires en tant que réponse, bien que j'aurais préféré pouvoir modifier la propre réponse de Steve Penny.
Ce que j'ai changé par rapport à la réponse de Steven-Penny
Correction: impression de chaînes nulles - elles n'étaient pas imprimées. Résolu: l'impression de chaînes incluant
%
- elles provoquaient des erreurs de syntaxe awk. Remplacéfor (j in ...)
parfor (j = 0, ...)
car le premier ne garantit pas l'ordre de traversée du tableau (il dépend de l'implémentation de awk). Ajout de 0 aux nombres octaux pour la portabilité.Mise à jour
Steven Penny a depuis corrigé ces problèmes dans sa réponse, donc ces remarques ne restent que pour l'historique de ma réponse. Voir la section Commentaires pour plus de détails.
la source
Vous pouvez utiliser la fonction shell "sh_trace" de la bibliothèque POSIX stdlib pour imprimer la commande en couleur avant de l'exécuter. Exemple:
Fonction Awk sous-jacente:
la source