2017-04-04 6 views
3

Il semble qu'en exécutant du code dans les variables PS0 et PS1 (qui sont évaluées avant et après l'exécution d'une commande d'invite, si je comprends bien) il devrait être possible de enregistrer l'heure de chaque commande en cours et l'afficher dans l'invite. Quelque chose comme ça:Utiliser PS0 et PS1 pour afficher l'heure d'exécution de chaque commande bash

[email protected] ~/tmp 
$ sleep 1 

[email protected] ~/tmp 1.01s 
$ 

Cependant, je me suis vite coincé avec le temps d'enregistrement dans PS0, depuis quelque chose comme cela ne fonctionne pas:

PS0='$(START=$(date +%s.%N))' 

Si je comprends bien, la cession START arrive dans un sous- shell, de sorte qu'il n'est pas visible dans la coque extérieure. Comment aborderiez-vous cela?

Répondre

1

Je pris cela comme casse-tête et que vous voulez montrer le résultat de mon déroutante:

D'abord, je bidouillé avec la mesure du temps. Le date +%s.%N (que je n'avais pas réalisé avant) était d'où je suis parti. Malheureusement, il semble que l'évaluation arithmétique de bash ne semble pas prendre en charge les points flottants. Ainsi, j'ai choisi quelque chose d'autre:

$ START=$(date +%s.%N) 

$ awk 'BEGIN { printf("%fs", '$(date +%s.%N)' - '$START') }' /dev/null 
8.059526s 

$ 

Ceci est suffisant pour calculer la différence de temps.

Ensuite, j'ai confirmé ce que vous avez déjà décrit: l'invocation de sous-shell empêche l'utilisation de variables shell. Ainsi, j'ai pensé à l'endroit où je pourrais stocker l'heure de début qui est globale pour les sous-shells mais assez locale pour être utilisée simultanément dans plusieurs shells interactifs. Ma solution est temp. fichiers (au /tmp). Pour fournir un nom unique je suis venu avec ce modèle: /tmp/$USER.START.$BASHPID.

$ date +%s.%N >/tmp/$USER.START.$BASHPID ; \ 
> awk 'BEGIN { printf("%fs", '$(date +%s.%N)' - '$(cat /tmp/$USER.START.$BASHPID)') }' /dev/null 
cat: /tmp/ds32737.START.11756: No such file or directory 
awk: cmd. line:1: BEGIN { printf("%fs", 1491297723.111219300 -) } 
awk: cmd. line:1:           ^syntax error 

$ 

Damn! Encore une fois je suis coincé dans le problème de sous-shell. Pour venir autour, je défini une autre variable:

$ INTERACTIVE_BASHPID=$BASHPID 

$ date +%s.%N >/tmp/$USER.START.$INTERACTIVE_BASHPID ; \ 
> awk 'BEGIN { printf("%fs", '$(date +%s.%N)' - '$(cat /tmp/$USER.START.$INTERACTIVE_BASHPID)') }' /dev/null 
0.075319s 

$ 

Prochaine étape: violon cela avec PS0 et PS1. Dans un puzzle similaire (SO: How to change bash prompt color based on exit code of last command?), j'ai déjà maîtrisé le "citant l'enfer". Ainsi, je devrais être capable de le faire à nouveau:

$ PS0='$(date +%s.%N >"/tmp/${USER}.START.${INTERACTIVE_BASHPID}")' 

$ PS1='$(awk "BEGIN { printf(\"%fs\", "$(date +%s.%N)" - "$(cat /tmp/$USER.START.$INTERACTIVE_BASHPID)") }" /dev/null)'"$PS1" 
0.118550s 
$ 

Ahh. Ça commence à marcher. Ainsi, il n'y a qu'un seul problème - pour trouver le bon script de démarrage pour l'initialisation de INTERACTIVE_BASHPID. J'ai trouvé ~/.bashrc qui semble être le bon pour cela, et que j'ai déjà utilisé dans le passé pour d'autres personnalisations personnelles.

Donc, mettre tous ensemble - ce sont les lignes que j'ai ajouté à mon ~/.bashrc:

# command duration puzzle 
INTERACTIVE_BASHPID=$BASHPID 
date +%s.%N >"/tmp/${USER}.START.${INTERACTIVE_BASHPID}" 
PS0='$(date +%s.%N >"/tmp/${USER}.START.${INTERACTIVE_BASHPID}")' 
PS1='$(awk "BEGIN { printf(\"%fs\", "$(date +%s.%N)" - "$(cat /tmp/$USER.START.$INTERACTIVE_BASHPID)") }" /dev/null)'"$PS1" 

La 3ème ligne (la commande date) a été ajouté pour résoudre un autre problème. Commentez-le et commencez un nouveau bash interactif pour découvrir pourquoi.

Un aperçu de mon xterm Cygwin bash où j'ai ajouté les lignes ci-dessus pour ./~bashrc: Snapshot of my cygwin xterm with the "tuned" bash prompt

Notes:

  1. Je considère que ce plutôt comme solution à un casse-tête d'un « grave productif " Solution. Je suis sûr que ce genre de mesure du temps prend beaucoup de temps. La commande time peut fournir une meilleure solution: SE: How to get execution time of a script effectively?. Cependant, c'était une bonne leçon pour pratiquer le bash ...

  2. N'oubliez pas que ce code pollue votre répertoire /tmp avec un nombre croissant de petits fichiers. Nettoyez le /tmp de temps en temps ou ajoutez les commandes appropriées pour le nettoyage (par exemple ~/.bash_logout).