Как сохранить историю терминала в файл из файла bash?
Я пытаюсь создать сценарий bash, который сохранит историю терминала в файл с именем hist.txt. С помощью history > hist.txt
похоже, не работает в скрипте bash, но работает нормально при выполнении в командной строке.
Любое руководство с благодарностью.
Спасибо джуди
2 ответа
Короткий ответ
Запустите скрипт с source
или же .
:
source ./script_name.sh
или же
. ./script_name.sh
Последний немного более совместим для разных оболочек.
Длинный ответ
Этот вопрос подчеркивает важный момент, который заключается в том, что сценарии оболочки запускаются в своем собственном контексте. Чтобы увидеть, что это значит, рассмотрим следующий сценарий оболочки:
#!/bin/bash
cd /
ls
Если вы запустите это, вы получите что-то вроде этого:
bin boot dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
Но вы заметите, что после запуска сценария вы по-прежнему находитесь в том каталоге, в котором находились до запуска: cd /
Внутри сценария фактически не влияет на ваш сеанс - он влияет только на контекст, в котором выполнялся сценарий, который создается для запуска сценария и уничтожается после его возврата.
source
Команда будет "читать и выполнять команды из аргумента имени файла в текущем контексте оболочки", поэтому любые команды, такие как cd
внутри это повлияет на ваш текущий сеанс. Если вы должны запустить скрипт выше, передав его source
вы обнаружите, что вы оказались в корневом каталоге после его запуска.
В этом случае проблема заключается в том, что history
команда выдает историю текущего контекста оболочки; контекст оболочки, в котором работает ваш скрипт без использования source
не имеет истории, поэтому ничего не записывает в выходной файл. Если вы используете source
он будет выполнен в правильном контексте и будет работать как положено.
NB: source
встроенная оболочка, а не программа как таковая - в Bash, source
является синонимом .
, но только в некоторых оболочках .
будет работать - я использовал source
в этом ответе, потому что это легче читать, чем .
, но для максимальной совместимости, .
должен быть использован.
Прежде всего, обратите внимание, что ваша история уже находится в файле. Если вы используете Bash, его имя обычно ~/.bash_history
, Более конкретно, это то, что вы установили переменную HISTFILE
к. Если вы хотите скопировать его в другой файл, просто запустите cat "$HISTFILE" > hist.txt
Теперь о том, почему history
Команда не работает в сценарии оболочки bash, потому что сценарии выполняются в неинтерактивной дочерней оболочке текущего сеанса оболочки. Дочерние оболочки не наследуют всю родительскую среду (поэтому не все установленные переменные), только переменные, которые были экспортированы. Чтобы проиллюстрировать, сценарий ниже будет отображать значение переменной $var
:
#!/bin/bash
echo "$var"
Теперь установите $var
к чему-то и запустите скрипт:
$ var="foo"
$ foo.sh
VAR:
Затем сначала экспортируйте переменную:
$ var="foo"
$ export var
$ foo.sh
VAR: foo
Как вы можете видеть, когда переменная была экспортирована, она доступна для дочерних оболочек.
Как я уже упоминал ранее, история хранится в файле, указанном переменной $HISTFILENAME
, Поскольку это не экспортируется по умолчанию, оно не устанавливается при запуске скрипта:
$ cat foo.sh
#!/bin/bash
echo "HISTFILE: $HISTFILE"
$ ./foo.sh
HISTFILE:
$ echo $HISTFILE
/home/terdon/.bash_history
Как вы можете видеть в приведенном выше примере, переменная HISTFILE
устанавливается в моем обычном сеансе оболочки, но пусто при запуске скрипта.
Итак, чтобы получить историю, у вас есть несколько вариантов:
По умолчанию
HISTFILE
значение$HOME/.bash_history
, Если вы не изменили это, вы можете просто запустить эту команду в вашем скрипте:cat "$HOME/.bash_history" > history
Вы можете передать
$HISTFILE
переменная к вашему сценарию иcat
тот:#!/bin/bash cat "$1" > history
Сохранить выше как
foo.sh
и беги так:./foo.sh "$HISTORY"
Убедитесь, что переменная экспортирована. Добавьте эту строку в свой
~/.bash_profile
(если он существует) или~/.profile
(если~/.bash_profile
не существует) файлы:export HISTFILE
Затем выйдите и снова войдите в систему, и вы сможете запустить
history > hist.txt
из сценария, как и ожидалось. Это потому чтоexport VAR
означает "сделать $VAR доступным для дочерних оболочек". В практическом плане это означает, что значениеHISTFILE
будет наследоваться неинтерактивной оболочкой, которую вы используете для запуска скрипта.Теперь, пока
HISTFILE
будет установлен, он не был прочитан оболочкой, выполняющей скрипт. Итак, чтобы заставить его работать, вам нужно прочитать его сhistory -r
первый. Весь сценарий будет выглядеть так:$!/bin/bash history -r history > hist.txt
Или просто экспортируйте его вручную перед запуском скрипта:
$ export HISTFILE
Но вам все равно нужно
history -r
в сценарии.Вы можете
source
это как предложено ответом @p0llard.