Wymuszanie „dodanego” aliasu do każdego polecenia

11

Czy można przymusowo dodać alias czasu (z braku lepszego sposobu wyrażenia go) do każdego polecenia w bash?

Na przykład chciałbym mieć konkretnego użytkownika, który za każdym razem, gdy uruchamiane jest polecenie, zawsze jest zawinięte dateprzed i po nim lub time.

Czy to możliwe, a jeśli tak, to w jaki sposób?

królikarnia
źródło
Spojrzałem wcześniej i nie mogłem znaleźć sposobu na zrobienie tego dokładnie. Jak mówi Caleb, możesz używać preexec, ale nie chcesz uruchamiać go w preexec(np. preexec() { time $1; }), Ponieważ powłoka nadal uruchamia go po preexecpowrocie. Więc najlepsze, co możemy zrobić, to coś podobnego.
Mikel
@Mikel Myślę, że możesz użyć tej preexec()funkcji, aby otoczyć wszystko, co było wykonywane, pobierając polecenie, uruchamiając je z wnętrza funkcji, a następnie zwracając jakiś błąd, aby powłoka nie wykonała samego polecenia.
Caleb

Odpowiedzi:

10

Możesz zarejestrować czas uruchomienia wiersza poleceń i czas wyświetlania monitu. Bash już śledzi datę rozpoczęcia każdego wiersza poleceń w swojej historii i możesz zanotować czas, kiedy wyświetlasz następny monit.

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"

Daje to tylko drugą rozdzielczość i tylko czas zegara ściennego. Jeśli chcesz uzyskać lepszą rozdzielczość, musisz użyć zewnętrznego datepolecenia obsługującego %Nformat nanosekund oraz DEBUGpułapki, którą należy wywołać dateprzed uruchomieniem polecenia na czas.

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

Nawet przy DEBUGpułapce nie sądzę, aby istniał sposób automatycznego wyświetlania czasów procesora dla każdego polecenia lub bardziej dyskryminujący niż monit o monit.


Jeśli chcesz użyć innej powłoki, oto jak uzyskać raport czasu dla każdego polecenia w zsh (nie uogólnia to na inne zadania):

REPORTTIME=0

Można ustawić REPORTTIMEdowolną wartość całkowitą, informacje o taktowaniu będą wyświetlane tylko dla poleceń, które wykorzystały więcej niż tyle sekund czasu procesora.

Zsh wziął tę funkcję z csh, w którym wywoływana jest zmienna time.

Gilles „SO- przestań być zły”
źródło
3

Twoje opcje tutaj będą zależeć od twojej powłoki. W zshtam wygodna funkcja nazywa się hak preexec(), który jest prowadzony tuż przed wszelkich interaktywnych poleceń powłoki. Tworząc funkcję o tej nazwie, możesz powodować wykonywanie zadań. Można również śledzić z funkcji o nazwie precmd(), która będzie działać tuż przed następnym wierszu jest zasysane, który będzie tuż po swoim wykończeń dowodzenia.

Tworząc tę ​​parę funkcji, możesz mieć dowolne dowolne polecenia, które chcesz uruchamiać przed i po każdym poleceniu wydanym w wierszu polecenia. Możesz użyć tego do rejestrowania użycia powłoki, tworzenia blokad, testowania środowiska lub, jak w twoim przykładzie, obliczania czasu lub zasobów spędzonych podczas wykonywania polecenia.

W tym przykładzie utworzymy sobie znacznik czasu testu przed uruchomieniem polecenia, preexec()a następnie obliczymy czas spędzony na wykonaniu polecenia precmd()i wyprowadzimy go przed pytaniem lub wylogujemy. Przykład:

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

Uwaga: W tym konkretnym przykładzie jest jeszcze łatwiejsza funkcja wbudowana. Wszystko, co musisz zrobić, to włączyć raportowanie w czasie wykonywania w ZSH, a zrobi to automatycznie.

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

W bardziej praktycznej realizacji preexec(), używam go zobaczyć jeśli powłoka jest uruchomiony wewnątrz tmuxczy screen, a jeżeli tak, aby wysyłać informacje o aktualnie uruchomionego polecenia Upstream ma być wyświetlany w nazwie karty.

Niestety w bash ten mały mechanizm nie istnieje. Oto próba powielenia przez jednego człowieka . Zobacz także odpowiedź Gillesa na podobny fajny mały hack.

Caleb
źródło
1
A oto uproszczona wersja sztuczki precmd-through-DEBUG .
Gilles 'SO - przestań być zły'
szkoda, że ​​nie był dostępny w bash!
warren
Zobacz linki Gillesa i innych, można to wdrożyć w bashu z odrobiną dodatkowej zabawy. Znowu, dlaczego po prostu nie uruchomisz zsh? To bujana muszla, która ma więcej dobrych powodów, aby się nią przestawić!
Caleb
2
Jeśli używasz zsh, istnieje jeszcze lepszy sposób, aby to zrobić. Zmienna środowiskowa REPORTTIME, gdy jest ustawiona, wyświetli informacje o czasie wykonania (tak jakbyś uruchomił polecenie z „time” przed nim) dla każdego polecenia trwającego dłużej niż $ REPORTTIME sekund. Po prostu ustaw na 0 i powinien wskazywać czas dla każdego polecenia, z podziałem na system użytkownika / sysa do uruchomienia.
Joseph Garvin
1

Najłatwiej byłoby to ustawić PROMPT_COMMAND. Zobacz zmienne Bash :

PROMPT_COMMAND
Jeśli jest ustawiony, wartość jest interpretowana jako polecenie do wykonania przed wydrukowaniem każdego głównego monitu ( $PS1).

Na przykład, aby uniknąć zastąpienia dowolnego istniejącego polecenia, możesz:

PROMPT_COMMAND="date ; ${PROMPT_COMMAND}"
cjm
źródło
nie wiedziałem o tym - wygląda na dobry początek, @cjm
warren
1
To początek, ale nie rozwiązuje problemu, kiedy wiadomo, kiedy polecenie zostało uruchomione. Sam monit może zostać narysowany kilka minut, godzin lub dni przed wpisaniem i uruchomieniem polecenia.
Caleb
0

csh/ tcshma najlepsze wsparcie dla tej funkcji (i zawsze ją miał).

  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.

Innymi słowy, set time=1wydrukuje czas zajęty (system, użytkownik, który upłynął) przez dowolne polecenie, które zajęło więcej niż 1 sekundę czasu procesora. Zwykły set timeumożliwi wydrukowanie czasu dla wszystkich poleceń.

Alexis
źródło