Forzare un alias "aggiunto" a ogni comando


11

È possibile aggiungere forzatamente un alias di temporizzazione (per mancanza di un modo migliore per esprimerlo) a ogni comando in bash?

Ad esempio, vorrei avere un utente specifico che ogni volta che viene eseguito un comando, viene sempre racchiuso tra dateprima e dopo o time.

È possibile e, in tal caso, come?


Ho guardato prima e non sono riuscito a trovare un modo per fare esattamente questo. Come dice Caleb, puoi usarlo preexec, ma non vuoi eseguirlo all'interno preexec(ad es. preexec() { time $1; }), Perché la shell lo esegue ancora dopo i preexecritorni. Quindi il meglio che possiamo fare è qualcosa di simile.
Mikel,

@Mikel Penso che potresti usare la preexec()funzione per avvolgere effettivamente qualsiasi cosa stesse eseguendo recuperando il comando, eseguendolo da te all'interno della funzione, quindi restituendo una sorta di errore in modo che la shell non continui a eseguire il comando stesso.
Caleb,

Risposte:


10

È possibile registrare l'ora in cui viene avviata una riga di comando e l'ora in cui viene visualizzato un prompt. Bash tiene già traccia della data di inizio di ciascuna riga di comando nella sua cronologia e puoi notare l'ora in cui visualizzi il prompt successivo.

print_command_wall_clock_time () {
  echo Wall clock time: \
    $(($(date +%s) - $(HISTTIMEFORMAT="%s ";
                       set -o noglob;
                       set $(history 1); echo $2)))
}
PROMPT_COMMAND=print_command_wall_clock_time$'\n'"$PROMPT_COMMAND"

Questo ti dà solo una seconda risoluzione e solo l'ora dell'orologio a muro. Se si desidera una risoluzione migliore, è necessario utilizzare un datecomando esterno che supporti il %Nformato per i nanosecondi e la DEBUGtrap da chiamare dateprima di eseguire il comando a tempo.

call_date_before_command () {
  date_before=$(date +%s.%N)
}
print_wall_clock_time () {
  echo Wall clock time: \
    $((date +"$date_before - %s.%N" | bc))
}
trap call_date_before_command DEBUG
PROMPT_COMMAND=print_command_wall_clock_time

Anche con la DEBUGtrappola, non penso che ci sia un modo per visualizzare automaticamente i tempi del processore per ciascun comando o essere più discriminante di un prompt per prompt.


Se sei disposto a usare una shell diversa, ecco come ottenere un rapporto orario per ogni comando in zsh (questo non si generalizza ad altre attività):

REPORTTIME=0

È possibile impostare REPORTTIMEqualsiasi valore intero, le informazioni di temporizzazione verranno visualizzate solo per i comandi che hanno utilizzato più di questo molti secondi di tempo del processore.

Zsh ha preso questa funzionalità da csh dove viene chiamata la variabile time.


3

Le tue opzioni qui dipenderanno dalla tua shell. In essa zshsi trova una pratica funzione hook chiamata preexec()che viene eseguita proprio prima di qualsiasi comando interattivo della shell. Creando una funzione con questo nome, puoi far eseguire le cose. È inoltre possibile eseguire il follow-up con una funzione chiamata precmd()che verrà eseguita appena prima che venga disegnato il prompt successivo, che sarà subito dopo la fine del comando.

Creando questa coppia di funzioni, è possibile avere qualsiasi comando arbitrario che si desidera eseguire prima e dopo qualunque comando venga emesso al prompt. È possibile utilizzarlo per registrare l'utilizzo della shell, creare blocchi, testare l'ambiente o come nell'esempio calcolare tempo o risorse impiegate durante l'esecuzione di un comando.

In questo esempio, creeremo noi stessi un timestamp di riferimento prima di eseguire un comando utilizzando preexec()quindi calcolare il tempo impiegato per eseguire il comando utilizzando precmd()e emetterlo prima del prompt o registrarlo. Esempio:

preexec() {
   CMDSTART=$(date +%s%N)
}
precmd() {
   CMDRUNTIME=$(($(date +%s%N)-$CMDSTART))
   echo "Last command ran for $CMDRUNTIME nanoseconds."
}

Nota: per questo esempio particolare, esiste una funzione incorporata ancora più semplice. Tutto quello che devi fare è attivare il runtime reporting in ZSH e lo farà automaticamente.

$ export REPORTTIME=0
$ ls -d
./
ls -BF --color=auto -d  0.00s user 0.00s system 0% cpu 0.002 total

In un'implementazione più pratica di preexec(), lo uso per vedere se la shell è in esecuzione all'interno tmuxo screene, in tal caso, per inviare informazioni a monte del comando attualmente in esecuzione da visualizzare nel nome della scheda.

Sfortunatamente in bash questo piccolo meccanismo non esiste. Ecco il tentativo di un uomo di replicarlo . Vedi anche la risposta di Gilles per un piccolo trucco simile.




vorrei che questo fosse disponibile in bash!
Warren,

Vedi i link di Gilles e altri, è implementabile in bash con un po 'di confusione in più. Di nuovo, perché non esegui semplicemente zsh? È un dondolo con più buone ragioni per cambiare di questo!
Caleb,

2
Se stai usando zsh c'è un modo ancora migliore per farlo. La variabile di ambiente REPORTTIME quando impostata genererà le informazioni sul tempo di esecuzione (come se avessi eseguito il comando con 'time' davanti ad esso) per qualsiasi comando che impiegasse più di $ REPORTTIME secondi. Basta impostarlo su 0 e dovrebbe indicare l'ora per ogni comando, con la ripartizione utente / sys per l'avvio.
Joseph Garvin,

1

Il modo più semplice sarebbe probabilmente impostare PROMPT_COMMAND. Vedi variabili Bash :

PROMPT_COMMAND
Se impostato, il valore viene interpretato come un comando da eseguire prima della stampa di ciascun prompt primario ( $PS1).

Ad esempio, per evitare di sovrascrivere qualsiasi comando prompt esistente, è possibile eseguire:

PROMPT_COMMAND="date ; ${PROMPT_COMMAND}"

non lo sapevo - sembra un buon inizio, @cjm
warren,

1
È un inizio, ma non affronta il problema di sapere quando è stato eseguito un comando. Il prompt stesso potrebbe essere disegnato minuti o ore o giorni prima che un comando fosse digitato ed eseguito.
Caleb,

0

csh/ tcshha il miglior supporto per questa funzione (e l'ha sempre avuto).

  The `time` shell variable can be set to execute the time builtin  command
  after the completion of any process that takes more than a given number
  of CPU seconds.

In altre parole, set time=1stamperà il tempo impiegato (sistema, utente, trascorso) da qualsiasi comando che ha impiegato più di 1 secondo di tempo di CPU. Plain set timeconsentirà di stampare l'ora per tutti i comandi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.