Я пытаюсь создать сценарий удара, который сохранит терминальную историю в файл под названием hist.txt. Используя history > hist.txt
кажется, не работает в сценарии удара, но хорошо работает при выполнении в командной строке.
Любое руководство значительно ценится.
Спасибо Judy
В первую очередь, обратите внимание, что Ваша история уже находится в файле. При выполнении удара его имя обычно ~/.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
установлен на моей нормальной сессии оболочки, но пуст при запущении скрипта.
Так, для получения истории у Вас есть несколько опций:
Значение по умолчанию 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.
Запустите скрипт с 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
в этом ответе, потому что легче читать, чем .
, но для максимальной совместимости, .
должен использоваться.