Вопрос или проблема
Сегодня я заметил, что моя история bash полностью очищена. Я не выполнял команды history -c
и не удалял файл .bash_history
. Помимо удаления файла .bash_history
и команды history -c
, как еще может быть очищена история bash?
При закрытии нескольких экземпляров bash одновременно существует известная проблема гонки, которая может привести к очистке истории. Это происходит потому, что при записи файла истории bash не используется блокировка.
Чет Рейми (текущий сопровождающий bash) дал хорошее объяснение условий возникновения этой проблемы:
Текущий код (bash-4.3-devel) работает примерно так, если предположить отсутствие
ошибок (lib/readline/histfile.c:history_do_write()):
- переименовать (histfile, histfile~)
- открыть файл с O_CREAT|O_TRUNC
- выделить буфер, достаточный для хранения всех данных истории
- записать все записи истории одним вызовом write(2)
- закрыть файл
- удалить (histfile~)
Код bash-4.2 работает так же, за исключением того, что он не создает резервную копию
файла истории. Каждый экземпляр оболочки выполняет эти действия при выходе, если
параметр histappend не установлен, как в вашей конфигурации.Есть несколько причин, по которым файл истории может оказаться с нулевой длиной: может
произойти сбой malloc, или сбой записи. В bash-4.2 уже ничего нельзя сделать с
усеченным файлом истории на этом этапе. В bash-4.3 будет восстановлен предыдущий файл
истории.
Эта тема на рассылке из bug-bash содержит достаточно обсуждений проблем, возможных решений и связанных с ними вопросов.
Есть также некоторые другие возможности:
- В какой-то момент ваша
HISTSIZE
илиHISTFILESIZE
была установлена в 0 - В какой-то момент ваше
history-size
в readline было установлено в 0 - Кто-то, преднамеренно или случайно, стер историю bash (через
> "$HISTFILE"
или аналогичным образом)
В последнем случае, возможно, вы захотите проверить, что никто не пользовался вашим аккаунтом и не пытался скрыть свои следы грубым способом. Проверьте last
, /var/log/auth
(или /var/log/secure
на CentOS/RHEL), а также любое установленное вами программное обеспечение для учёта процессов и/или аудита.
Как я случайно удалил свою историю bash:
Я разрабатывал собственный альтернативный скрипт readline для терминала с нуля: https://tiswww.cwru.edu/php/chet/readline/rluserman.html
а затем тестировал его в терминале. GNU Readline имеет встроенные инструкции по размеру истории и её сохранению, поэтому размер истории может быть установлен по умолчанию, и таким образом вся ваша история может быть стерта.
Восстановление истории, если она осталась в памяти:
Если вы поймаете это до перезагрузки или если терминал был оставлен открытым до очистки, вы можете найти свою историю в памяти. Запустите history | cut -c 8- > histback_user1.txt
на всех открытых терминалах и для каждого пользователя. Если это создаст файл с вашей расширенной историей, то вы сможете заменить ~/.bash_history
на histback_user1.txt
. Также проверьте историю всех пользователей, недавно вошедших в систему, а также историю root. Удалить историю bash можно случайно при множестве обстоятельств, поэтому, если вы хотите быть уверены в отсутствии потерь в истории, вам нужен ежедневный скрипт резервирования.
.
Ответ или решение
Неожиданное исчезновение истории команд в bash может вызывать много вопросов, особенно если вы не выполняли команду history -c
или не удаляли файл .bash_history
. Ваша проблема может быть связана с несколькими техническими моментами, влияющими на сохранность и доступность командной истории, которые рассмотрим подробно.
Теория
История команд bash хранится в файле, который обычно называется .bash_history. При завершении сеанса bash, команды, вводимые вами во время этого сеанса, записываются в этот файл, что позволяет вам просматривать историю даже после перезапуска сеанса. Однако существуют различные факторы, которые могут привести к тому, что этот файл станет пустым или его содержимое будет утеряно.
Основные причины обнуления истории bash:
-
Состояние гонки при завершении нескольких сеансов: Когда вы закрываете несколько окон терминала одновременно, возникает ситуация гонки. Поскольку блокировка файла истории в bash не используется, два сеанса могут конкурировать за доступ к файлу одновременно. Это может привести к тому, что один из сеансов перезапишет изменения другого, что в результате может оставить файл пустым.
-
Сбои при записи: Согласно объяснению от Чета Рэйми, текущий процесс записи истории bash включает несколько шагов, таких как выделение памяти для буфера и запись данных за один вызов. Если один из этих шагов (например, выделение памяти или запись) завершится с ошибкой, файл может остаться пустым.
-
Настройка переменных окружения: Если переменные
HISTSIZE
илиHISTFILESIZE
в bash были случайно установлены в 0, это могло бы привести к обнулению истории. Подобный эффект может возникнуть и при настройке параметров readline, еслиhistory-size
установили в 0. -
Умышленное или случайное удаление истории: История может быть стерта вручную. Например, команда
> "$HISTFILE"
в скрипте или командной строке сбросит файл до нулевой длины. Не исключена возможность, что кто-то с доступом к вашей учётной записи мог выполнить такие действия.
Примеры
Ваша история может исчезнуть из-за ситуации гонки. Представьте, что у вас открыто несколько окон терминала, и вы заканчиваете работу, закрывая их одно за другим. В момент записи истории несколько сеансов пытаются одновременно записать данные, и один из них может привести к потере истории предыдущего.
В другой ситуации, если параметр HISTSIZE
был настроен на 0 в вашем ~/.bashrc
или ином конфигурационном файле, это приведет к тому, что никакие команды не сохраняются после завершения сеанса.
Применение
Для устранения данной проблемы и предотвращения её повторного возникновения, рассмотрите следующие действия:
-
Проверьте настройки конфигурации bash: Убедитесь, что
HISTSIZE
иHISTFILESIZE
не равны 0. Это можно сделать, открыв~/.bashrc
и~/.bash_profile
. -
Используйте
histappend
: Чтобы добавить команды к существующей истории, а не перезаписывать её, добавьтеshopt -s histappend
в ваш файл конфигурации bash. -
Регулярное резервное копирование: Настройте автоматический скрипт, который будет ежедневно сохранять копию вашего
.bash_history
, что сократит риски утраты данных при возникновении ошибок. -
Проверка безопасности: Если вы подозреваете внешнее вмешательство, исследуйте журнал доступа
last
и файлы журналов, такие как/var/log/auth.log
или/var/log/secure
. Это может предоставить информацию о подозрительной активности в вашей системе. -
Использование иных инструментов и форматов: Рассмотрите возможность использования инструментов, таких как Zsh или Fish, которые могут иметь более безопасное управление историей и дополнительные функции для восстановления утраченной информации.
Восполагая этими знаниями, вы сможете лучше управлять и защищать свою командную историю в bash, избегая потерь данных и нежелательных проблем в будущем.