Как сохранить терминальную историю в файл из файла удара?

Я пытаюсь создать сценарий удара, который сохранит терминальную историю в файл под названием hist.txt. Используя history > hist.txt кажется, не работает в сценарии удара, но хорошо работает при выполнении в командной строке.

Любое руководство значительно ценится.

Спасибо Judy

8
задан 29 September 2016 в 07:14

2 ответа

В первую очередь, обратите внимание, что Ваша история уже находится в файле. При выполнении удара его имя обычно ~/.bash_history. Строго говоря, это - то, что Вы установили переменную HISTFILE кому. Если Вы хотите скопировать его в другой файл, просто работать cat "$HISTFILE" > hist.txt

Теперь, относительно почему history команда не работает в сценарии оболочки удара, поэтому скрипты запущены в неинтерактивной дочерней оболочке Вашей текущей сессии оболочки. Дочерние оболочки не наследовали всю среду родителя (так не все переменные набора), только переменные, которые были экспортированы. Для иллюстрирования сценарий ниже повторит значение переменной $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.

10
ответ дан 23 November 2019 в 05:23

Короткий ответ

Запустите скрипт с 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 это выполнится в корректном контексте и будет работать как ожидалось.

N.B.: source встроенная оболочка, не программа по сути - в Bash, source синонимично с ., но в некоторых оболочках только . будет работать - я использовал source в этом ответе, потому что легче читать, чем ., но для максимальной совместимости, . должен использоваться.

11
ответ дан 23 November 2019 в 05:23

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

Похожие вопросы: