Как сохранить историю терминала в файл из файла 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 устанавливается в моем обычном сеансе оболочки, но пусто при запуске скрипта.

Итак, чтобы получить историю, у вас есть несколько вариантов:

  1. По умолчанию HISTFILE значение $HOME/.bash_history, Если вы не изменили это, вы можете просто запустить эту команду в вашем скрипте:

    cat "$HOME/.bash_history" > history
    
  2. Вы можете передать $HISTFILE переменная к вашему сценарию и cat тот:

    #!/bin/bash
    cat "$1" > history
    

    Сохранить выше как foo.sh и беги так:

    ./foo.sh "$HISTORY"
    
  3. Убедитесь, что переменная экспортирована. Добавьте эту строку в свой ~/.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 в сценарии.

  4. Вы можете source это как предложено ответом @p0llard.

Другие вопросы по тегам