Polecenie historii w skrypcie bash

20

Historia to polecenie wbudowane w powłokę, którego nie mogłem użyć w skrypcie BASH. Czy istnieje sposób, aby to osiągnąć za pomocą skryptu BASH?
Oto mój skrypt dla Ciebie:

#!/bin/bash
history |  tail -100 > /tmp/history.log
cd /tmp
uuencode history.log history.txt  | mail -s "History log of server" hello@hel.com
Vijay Ramachandran
źródło

Odpowiedzi:

32

Bash domyślnie wyłącza historię w nieinteraktywnych powłokach, ale można ją włączyć.

#!/bin/bash
HISTFILE=~/.bash_history
set -o history
history | tail 

Ale jeśli próbujesz monitorować aktywność na tym serwerze, historia powłoki jest bezużyteczna (trywialne jest uruchamianie poleceń, które nie pojawiają się w historii). Zobacz Jak mogę zalogować wszystkie uruchomienia procesów w systemie Linux .

Jeśli debugujesz skrypt, historia powłoki nie jest najlepszym sposobem na uzyskanie użytecznych informacji. O wiele lepszym narzędziem jest narzędzie do śledzenia debugowania: umieszczone set -xw górnej części skryptu. Śledzenie jest zapisywane jako błąd standardowy.

Gilles „SO- przestań być zły”
źródło
To odmawia pracy w skrypcie:histtest.sh: 5: set: Illegal option -o history
Ken Sharp
4
@KenSharp To dlatego, że próbowałeś użyć go w skrypcie sh (a Twój shdash ocenia dokładnie na podstawie treści komunikatu o błędzie). Aby uzyskać dostęp do historii bash, musisz użyć bash (skrypt rozpoczynający się od #!/bin/bashlub #!/usr/bin/env bash).
Gilles „SO- przestań być zły”
1
@KenSharp Tak to jest. Oczywiście uruchomiłeś go pod kreską, biorąc pod uwagę komunikat o błędzie. Bash nie ma komunikatu o błędzie Illegal option(powiedziałby set: history: invalid option name).
Gilles „SO- przestań być zły”
problem polega na tym, że dodaje do polecenia wszystkie polecenia następujące set -o history po historii, które zostaną wypełnione wpisami takimi jak if [... vars=$(...itp.
nath
1
@nath Właśnie o to pytano. Jest to prawie bezcelowe, jak wskazałem. Monitorowanie aktywności to trudny problem, którego historia powłoki nie rozwiąże. Jeśli debugujesz skrypt, set -xjest to o wiele bardziej przydatne.
Gilles „SO- przestań być zły”
6

Nie jestem pewien, czy faktycznie korzysta on z funkcji historii, gdy jest uruchamiany nieinteraktywnie, w przeciwnym razie każdy uruchamiany skrypt powłoki zaśmieciłby historię poleceń.

Dlaczego nie pójść bezpośrednio do źródła ${HOME}/.bash_history, należy wymienić history | tail -100z tail -100 ${HOME}/.bash_history. (Jeśli używasz znaczników czasu, prawdopodobnie będziesz musiał zrobić coś w stylu grep -v ^# ${HOME}/.bash_history | tail -100).

Kjetil Jorgensen
źródło
Rzeczywiście, przy pomocy znaczników czasu powinieneś faktycznie greq -v '^#[0-9]\+$'(czasami „
wykonuję
I faktycznie, w moim przypadku, muszę użyć poprawnego numeru linii historii , ale istnieje różnica między wyjściem historyi wyjściem grepmetody ...
PlasmaBinturong
Ok, fix było zsynchronizować listę historii z pliku historii tak: history -a; history -c; history -r. (dodaj, wyczyść, przeczytaj)
PlasmaBinturong
2

Jeśli chcesz użyć danych wyjściowych historypolecenia z aktywnej sesji powłoki w skrypcie, możesz użyć aliasu, aby najpierw uruchomić polecenie. Następnie, w tym samym aliasie, możesz wywołać pozostałą część skryptu. Dzięki takiej konfiguracji można osiągnąć zasadniczo ten sam wynik, co historypolecenie w skrypcie.

Na przykład możesz utworzyć taki alias, zakładając, że nazwa skryptu to script.sh:

alias hy_tmp='history | tail -100 > /tmp/history.log ; bash /patch/to/script.sh'

I zmień skrypt na następujący:

#!/bin/bash
cd /tmp
uuencode history.log history.txt  | mail -s "History log of server" hello@hel.com

Znalazłem to pytanie, pisząc proces łączenia, sortowania i synchronizacji ~/bash_historyplików na dwóch komputerach, dzięki czemu łatwo będzie wyszukiwać polecenia, z których korzystałem w przeszłości.

O wiele łatwiej jest zaktualizować mój plik historii zbiorczej bez konieczności logowania się do nowej powłoki w celu ~/bash_historyzaktualizowania. W przypadku monitorowania serwera to oczywiście nie zadziała, jak wspomniano w innych odpowiedziach.

Moje użycie w szczególności to:

alias hbye='history | cut -c 8- > /home/chris/.bash_history_c; bash /hby.sh

Skrypt hby.shnastępnie pobiera wszystkie unikalne wpisy ze wszystkich ~/.bash_history*plików.

clk
źródło
1

Utwórz skrypt o nazwie script.shjak poniżej. Tworzy skrypt o nazwie X i umieszcza w nim Y Liczba linii twojej historii.

#!/bin/bash
SCRIPT_NAME=$1
NUMBER_OF_LINES_BACK=$2

# Enable History in a non interactive shell
HISTFILE=~/.bash_history
set -o history

# echo shabang line and x number of lines of history to new script
echo \#\!\/bin\/bash > $SCRIPT_NAME.sh; history | tail -n $NUMBER_OF_LINES_BACK >> $SCRIPT_NAME.sh;
chmod u+x $SCRIPT_NAME.sh;

# Open the newly created script with vim
vim $SCRIPT_NAME.sh;
~

Następnie, jeśli chcesz utworzyć skrypt do wykonania zadania o nazwie „zadanie”, nad którym pracowałeś przez ostatnie 14 uruchomionych linii

script.sh task 14

Następnie posprzątaj swoją historię, aby stworzyć fajny skrypt!

Eric
źródło
histtest.sh: 5: set: Illegal option -o history
Ken Sharp
1

Polecenie historii jest domyślnie wyłączone w skrypcie bash, dlatego nawet polecenie historii nie będzie działać w pliku .sh. w celu przekierowania prosimy o przekierowanie pliku bash_history w pliku .sh.

lub mechanizm historii można włączyć również, wspominając plik historii i zmieniając parametry czasu działania, jak wspomniano poniżej

#!/bin/bash
HISTFILE=~/.bash_history
set -o history 

Uwaga: wspomniane powyżej dwa wiersze na górze pliku skryptu. teraz polecenie historii będzie działać w historii.

linux.cnf
źródło
0

Każdy użytkownik ma swój własny plik historii, który jest wynikiem polecenia historii. Zamiast użycia polecenia historii w skrypcie powłoki, możesz użyć pliku historii dla użytkownika. W .bash_historykatalogu domowym użytkownika będzie plik, który będzie plikiem historii użytkownika.

amit singh
źródło
-1

Krótka odpowiedź :

służy history -pdo jawnego wykonywania ekspansji historii.

Oto przykład.

Jeden przypadek użycia często się dla mnie zdarza:

  • poprzednie polecenie pobiera listę nazw plików i wypisuje na standardowe wyjście,
  • Muszę edytować te pliki za pomocą vima.

Od czasu mojej bash set -o histexpandzwykle piszę na maszynie

vim $(!!)

aby edytować pliki wymienione za pomocą poprzedniego polecenia.

Niestety czasami zdarza się błąd, więc włączam weryfikację przez shopt -s histverify.

Teraz mogę zweryfikować rozszerzenie przy koszcie jednego dodatkowego Returnklucza.

Dzisiaj chcę zawinąć te szczegóły w funkcję bash, ponieważ często ich używam,

function vk() {
    set -o history && set -o histexpand;
    vim -i ~/.viminfok $($(history -p !!));
}

Tutaj używam dwóch zagnieżdżonych command substitution, wewnętrznego do rozwinięcia !!do poprzedniego polecenia, zewnętrznego do wykonania i uzyskania wyniku.

Teraz mogę osiągnąć ten sam efekt, mając tylko trzy klucze, a jednym z nich jest Return!

qeatzy
źródło