Je veux écrire du code comme ceci:
command="some command"
safeRunCommand $command
safeRunCommand() {
cmnd=$1
$($cmnd)
if [ $? != 0 ]; then
printf "Error when executing command: '$command'"
exit $ERROR_CODE
fi
}
Mais ce code ne fonctionne pas comme je le souhaite. Où j'ai fait une erreur?
Ci-dessous le code fixe:
#!/bin/ksh
safeRunCommand() {
typeset cmnd="$*"
typeset ret_code
echo cmnd=$cmnd
eval $cmnd
ret_code=$?
if [ $ret_code != 0 ]; then
printf "Error : [%d] when executing command: '$cmnd'" $ret_code
exit $ret_code
fi
}
command="ls -l | grep p"
safeRunCommand "$command"
Maintenant, si vous examinez ce code, voici quelques modifications que j'ai apportées:
typeset
n'est pas nécessaire, mais constitue une bonne pratique. Cela fait cmnd
et ret_code
local à safeRunCommand
ret_code
n'est pas nécessaire, mais c'est une bonne pratique de stocker le code de retour dans une variable (et de le stocker dès que possible) afin que vous puissiez l'utiliser plus tard, comme je l'ai fait dans printf "Error : [%d] when executing command: '$command'" $ret_code
safeRunCommand "$command"
. Si vous ne le faites pas, cmnd
obtiendra uniquement la valeur ls
et non ls -l
. Et c'est encore plus important si votre commande contient des pipes.typeset cmnd="$*"
au lieu de typeset cmnd="$1"
_ si vous voulez conserver les espaces. Vous pouvez essayer les deux en fonction de la complexité de votre argument de commande.NOTE: N'oubliez pas que certaines commandes donnent 1 comme code de retour même s'il n'y a pas d'erreur comme grep
. Si grep
a trouvé quelque chose, il retournera 0 sinon 1.
J'avais testé avec KSH/BASH. Et ça a bien fonctionné. Faites-moi savoir si vous rencontrez des problèmes en cours d'exécution.
Essayer
safeRunCommand() {
"$@"
if [ $? != 0 ]; then
printf "Error when executing command: '$1'"
exit $ERROR_CODE
fi
}
Ce devrait être $cmd
Au lieu de $($cmd)
. Fonctionne bien avec ça sur ma boîte.
Edit: Votre script ne fonctionne que pour les commandes one-Word, comme ls. Cela ne fonctionnera pas pour "ls cpp". Pour que cela fonctionne, remplacez cmd="$1"; $cmd
Par "$@"
. Et, n'exécutez pas votre script en tant que command="some cmd"; safeRun command
, Exécutez-le en tant que safeRun some cmd
.
De plus, lorsque vous devez déboguer vos scripts bash, exécutez-le avec l'indicateur '-x'. [bash -x s.sh].
Il y a plusieurs problèmes avec votre script.
Les fonctions (sous-routines) doivent être déclarées avant de tenter de les appeler. Vous voulez probablement retourner () mais pas exit () de votre sous-routine pour permettre au bloc appelant de tester le succès ou l'échec d'une commande particulière. Cela dit, vous ne capturez pas 'ERROR_CODE', donc il s'agit toujours de zéro (non défini).
Il est également judicieux d'entourer vos références variables d'accolades. Votre code pourrait ressembler à:
#!/bin/sh
command="/bin/date -u" #...Example Only
safeRunCommand() {
cmnd="$@" #...insure whitespace passed and preserved
$cmnd
ERROR_CODE=$? #...so we have it for the command we want
if [ ${ERROR_CODE} != 0 ]; then
printf "Error when executing command: '${command}'\n"
exit ${ERROR_CODE} #...consider 'return()' here
fi
}
safeRunCommand $command
command="cp"
safeRunCommand $command
L'idée normale serait d'exécuter la commande puis d'utiliser $?
pour obtenir le code de sortie. Cependant, il arrive parfois que vous ayez plusieurs cas dans lesquels vous devez obtenir le code de sortie. Par exemple, vous devrez peut-être masquer la sortie tout en renvoyant le code de sortie ou imprimer le code de sortie et la sortie.
ec() { [[ "$1" == "-h" ]] && { shift && eval $* > /dev/null 2>&1; ec=$?; echo $ec; } || eval $*; ec=$?; }
Cela vous donnera la possibilité de supprimer la sortie de la commande pour laquelle vous voulez le code de sortie. Lorsque la sortie est supprimée pour la commande, le code de sortie sera directement renvoyé par la fonction.
Personnellement, j'aime bien mettre cette fonction dans mon .bashrc
fichier
Ci-dessous, je vous présente quelques façons d'utiliser ceci:
# In this example, the output for the command will be
# normally displayed, and the exit code will be stored
# in the variable $ec.
$ ec echo test
test
$ echo $ec
0
# In this example, the exit code is output
# and the output of the command passed
# to the `ec` function is suppressed.
$ echo "Exit Code: $(ec -h echo test)"
Exit Code: 0
# In this example, the output of the command
# passed to the `ec` function is suppressed
# and the exit code is stored in `$ec`
$ ec -h echo test
$ echo $ec
0
Solution à votre code en utilisant cette fonction
#!/bin/bash
if [[ "$(ec -h 'ls -l | grep p')" != "0" ]]; then
echo "Error when executing command: 'grep p' [$ec]"
exit $ec;
fi
Vous devez également noter que le code de sortie que vous verrez s'affichera pour la commande
grep
en cours d'exécution, car il s'agit de la dernière commande en cours d'exécution. Pas lels
.