J'ai un script d'installation pour une boîte Vagrant où j'ai utilisé pour mesurer des étapes simples avec time
. Maintenant, je voudrais activer ou désactiver conditionnellement les mesures de temps.
Par exemple, auparavant, une ligne ressemblerait à:
time (apt-get update > /tmp/last.log 2>&1)
Maintenant, je pensais que je pouvais simplement faire quelque chose comme ça:
MEASURE_TIME=true
[[ $MEASURE_TIME = true ]] && TIME="time --format=%e" || TIME=""
$TIME (apt-get update > /tmp/last.log 2>&1)
Mais cela ne fonctionnera pas:
syntax error near unexpected token `apt-get'
`$TIME (apt-get update > /tmp/last.log 2>&1)'
Quel est le problème ici?
Réponses:
Pour pouvoir chronométrer un sous-shell, vous avez besoin du
time
mot - clé , pas de la commande.Le
time
mot-clé, qui fait partie du langage, n'est reconnu comme tel que lorsqu'il est entré littéralement et comme le premier mot d'une commande (et dans le cas deksh93
, alors le jeton suivant ne commence pas par a-
). Même entrer"time"
ne fonctionnera pas encore moins$TIME
(et serait plutôt considéré comme un appel à latime
commande).Vous pouvez utiliser ici des alias qui sont développés avant qu'un autre cycle d'analyse ne soit effectué (donc laissez le shell reconnaître ce
time
mot - clé):Le
time
mot - clé ne prend pas d'options (sauf pour-p
inbash
), mais le format peut être défini avec laTIMEFORMAT
variable inbash
. (lashopt
pièce est égalementbash
spécifique, les autres coques n'ont généralement pas besoin de cela).la source
info -f bash --index-search=time
Bien que an
alias
soit une façon de le faire, cela peut être faiteval
aussi - c'est juste que vous ne voulez pas tanteval
l'exécution deeval
la commande que la déclaration de commande .J'aime
alias
es - je les utilise tout le temps, mais j'aime mieux les fonctions - en particulier leur capacité à gérer les paramètres et qu'elles ne doivent pas nécessairement être étendues en position de commande comme cela est requis pouralias
es.J'ai donc pensé que vous voudriez peut-être essayer aussi:
Le
$IFS
bit concerne principalement$*
. Il est important que le( subshell bit )
soit également le résultat d'une expansion du shell et donc afin d'étendre les arguments dans une chaîne analysable que j'utilise"$*"
(ne le faites paseval
"$@"
, d'ailleurs, sauf si vous êtes certain que tous les arguments peuvent être joints sur des espaces) . Le délimiteur divisé entre les arguments dans"$*"
est le premier octet$IFS
, et il peut donc être dangereux de continuer sans s'assurer de sa valeur. Ainsi , la fonction permet d' enregistrer$IFS
, il met un\n
ewline assez longtemps pourset ... "$*"
en"$3"
,unset
s, puis remet à zéro sa valeur si elle avait déjà un.Voici une petite démo:
Vous voyez, j'ai mis deux commandes dans la valeur de
$TIME
there - n'importe quel nombre est correct - même aucun - mais assurez-vous qu'il est échappé et cité correctement - et il en va de même pour les arguments_time()
. Ils seront tous concaténés en une seule chaîne de commande lors de leur exécution - mais chaque argument obtient sa propre ligne\n
électronique et peut donc être étalé relativement facilement. Ou bien, vous pouvez les\n
regrouper en un seul, si vous le souhaitez, et les séparer sur des lignes électroniques ou des points-virgules ou ce que vous avez. Assurez-vous simplement qu'un seul argument représente une commande que vous seriez à l'aise de mettre sur sa propre ligne dans un script lorsque vous l'appelez.\(
, par exemple est très bien, tant qu'il est finalement suivi de\)
. Fondamentalement, le truc normal.Lorsque
eval
l'extrait ci-dessus est alimenté, il ressemble à ceci:Et ses résultats ressemblent à ...
PRODUCTION
L'
hash
erreur indique que je n'ai pas/usr/bin/time
installé (parce que je n'ai pas) etcommand
laissez-nous savoir quelle heure est en cours d'exécution. Le suiviset +x
est une autre commande exécutée aprèstime
(ce qui est possible) - il est important d'être prudent avec les commandes d'entrée lors deeval
n'importe quoi.la source
_time() { eval "$TIME $@"; }
? L'utilisation d'une fonction a l'inconvénient d'introduire un champ d'application différent pour les variables (pas un problème pour les sous-coquilles)"$@"
extension. J'aime un seul argument poureval
- ça devient effrayant sinon. Ummm .... comment voulez-vous dire sur la portée différente cependant? Je pensais que c'était juste desfunction
fonctions ...eval
rejoint ses arguments avant d'exécuter, ce que vous essayez de faire de manière très compliquée. Je voulais dire que_time 'local var=1; blah'
ferait cevar
local que_time
, ou qui_time 'echo "$#"'
imprimerait la$#
de cette_time
fonction, et non celui de l'appelant.eval
concède ses arguments sur les espaces - ce qui est, comme vous le dites, exactement ce que je fais ici - même si ce n'était pas une intention initiale. Je vais arranger ça.eval
ing"$*"
par opposition à"$@"
est une habitude que j'ai prise après de nombreuxcommand not found
rodages avec quand les arguments ont été joints au mauvais endroit. Dans tous les cas, bien que les arguments soient finalement exécutés dans la fonction, il est assez simple de les développer lors de l'invocation, je pense. C'est ce que je ferais de"$#"
toute façon.