Я пытаюсь создать bash-скрипт, который сохранит историю терминала в файл с именем hist.txt. Использование history > hist.txt
не похоже на работу в скрипте bash, но прекрасно работает при выполнении в командной строке.
Любое руководство с благодарностью.
Спасибо джуди
~/.bash_history
файл пользователя .Ответы:
Короткий ответ
Запустите скрипт с помощью
source
или.
:или
Последний немного более совместим для разных оболочек.
Длинный ответ
Этот вопрос подчеркивает важный момент, который заключается в том, что сценарии оболочки запускаются в своем собственном контексте. Чтобы увидеть, что это значит, рассмотрим следующий сценарий оболочки:
Если вы запустите это, вы получите что-то вроде этого:
Но вы заметите, что после запуска сценария вы по-прежнему находитесь в том каталоге, в котором находились до запуска:
cd /
внутренний сценарий фактически не влиял на ваш сеанс - он влиял только на контекст, в котором выполнялся сценарий, что создается для запуска сценария и уничтожается после его возврата.Команда
source
будет «читать и выполнять команды из аргумента имени файла в текущем контексте оболочки», так что любые команды, какcd
внутри, будут влиять на ваш текущий сеанс. Если бы вы запустили приведенный выше сценарий, передав егоsource
вам, вы обнаружите, что вы оказались в корневом каталоге после его запуска .В этом случае проблема в том, что
history
команда выдает историю текущего контекста оболочки; контекст оболочки, в котором ваш скрипт запускается без использования,source
не имеет истории, поэтому он ничего не записывает в выходной файл. Если вы используетеsource
его, он будет работать в правильном контексте и будет работать как положено.NB:
source
встроенная оболочка, а не программа как таковая - в Bashsource
является синонимом.
, но в некоторых оболочках.
будет работать только - я использовалsource
этот ответ, потому что его легче читать.
, но для максимальной совместимости.
следует использоваться.источник
Прежде всего, обратите внимание, что ваша история уже находится в файле. Если вы используете bash, его обычно называют
~/.bash_history
. Более конкретно, это то, что вы установили для переменнойHISTFILE
. Если вы хотите скопировать его в другой файл, просто запуститеcat "$HISTFILE" > hist.txt
Теперь о том, почему
history
команда не работает в сценарии оболочки bash, потому что сценарии выполняются в неинтерактивной дочерней оболочке текущего сеанса оболочки. Дочерние оболочки не наследуют всю родительскую среду (поэтому не все установленные переменные), только переменные, которые были экспортированы. Чтобы проиллюстрировать, скрипт ниже будет отображать значение переменной$var
:Теперь установите
$var
что-нибудь и запустите скрипт:Затем сначала экспортируйте переменную:
Как вы можете видеть, когда переменная была экспортирована, она доступна для дочерних оболочек.
Как я упоминал ранее, история хранится в файле, указанном переменной
$HISTFILENAME
. Поскольку это не экспортируется по умолчанию, оно не устанавливается при запуске скрипта:Как вы можете видеть в приведенном выше примере, переменная
HISTFILE
устанавливается в моем обычном сеансе оболочки, но пуста при запуске сценария.Итак, чтобы получить историю, у вас есть несколько вариантов:
Значением по умолчанию
HISTFILE
является$HOME/.bash_history
. Если вы не изменили это, вы можете просто запустить эту команду в вашем скрипте:Вы можете передать
$HISTFILE
переменную в ваш скрипт иcat
это:Сохраните выше как
foo.sh
и запустите так:Убедитесь, что переменная экспортирована. Добавьте эту строку в ваши
~/.bash_profile
(если она существует) или~/.profile
(если~/.bash_profile
не существует) файлы:Затем выйдите из системы и снова войдите в систему, и вы сможете запустить
history > hist.txt
скрипт, как и ожидалось. Это потому, чтоexport VAR
означает «сделать $ VAR доступным для дочерних оболочек». В практическом плане это означает, что значениеHISTFILE
будет унаследовано неинтерактивной оболочкой, которую вы используете для запуска вашего скрипта.Теперь, пока
HISTFILE
будет установлено значение, оно не было прочитано оболочкой, выполняющей скрипт. Итак, чтобы заставить его работать, вам нужноhistory -r
сначала прочитать его . Весь сценарий будет выглядеть так:Или просто экспортируйте его вручную перед запуском скрипта:
Но вам все равно нужно
history -r
в сценарии.Вы можете сделать
source
это, как подсказывает ответ @ p0llard .источник