Как правильно защитить .bash_history от сокращения?

Вопрос или проблема

Что я могу сделать, чтобы мой .bash_history только дополнялся?

Я работаю в различных средах, таких как singularity, apptainer, docker, podman и через ssh с различными настройками и монтированиями. Каждая из сред может иметь разное значение HISTFILESIZE, на разных машинах может быть что-то в /etc/profile.d, и я установил HISTFILE=.bash_historymy HISTFILESIZE="" HISTSIZE="" в моих ~/.bashrc и ~/.profile и ~/.bash_profile.

Проблема в том, что если одна из сред устанавливает HISTFILESIZE, бац — мой .bash_history теряется. Я устанавливаю свой собственный HISTFILESIZE в моем .bashrc, но если я выполню source /nfs/my/friends/.profile или другие скрипты, они переопределят HISTFILESIZE и не тронут HISTFILE, так что мой отдельный HISTFILE по-прежнему будет усечен. Когда это случается, я теряю свою историю. Это происходило со мной много раз на протяжении многих лет в различных системах и средах.

На протяжении довольно длительного времени у меня был скрипт в ~/.bashrc, который создает несколько резервных копий .bash_history и вращает их, это сопровождалось проверкой размера, например:

name="$(basename "$HISTFILE")"
backupdir=~/.cache/bash_history/
mkdir -p "$backupdir"
file="$HISTFILE"
for ((i=1;i<5;++i)); do
   cp "$file" "$backupdir/$name.$i"
   file="$backupdir/$name.$i"
done

Так что у меня было 5 “сессий”, чтобы восстановить файл истории или создать его резервную копию или “склеить” их вместе.

Мне кажется, что это было неудовлетворительным временным решением. Существует ли правильное решение для защиты от усечения bash .bash_history? Я бы предположил, что можно было бы запускать “diff” между старым и новым и объединять только пропущенные фрагменты с задней части .bash_history. Я не думаю, что сделать .bash_history fifo – это хорошее решение. Например, я был бы счастлив, если бы оболочка восстанавливала потерянные усеченные команды при следующем выполнении ~/.bashrc из резервного файла.

Если вы используете файловую систему, поддерживающую атрибут “только добавление”, вы можете установить его:

sudo chattr +a .bash_history

(Это привилегированная операция.)

Затем включите histappend — это заставляет оболочку обновлять .bash_history только путем добавления к нему, и это включает открытие файла в режиме только добавление:

shopt -s histappend

Любая оболочка, у которой эта опция не установлена, не сможет обновить файл истории.

Ваше решение очень похоже на logrotate 😀

Но серьезно, я думаю, что общая проблема заключается в том, что

история оболочки — это всего лишь файл, и в Unix нет ничего, что могло бы помешать программе, которая может добавлять в файл, сократить его.

Это невозможно “решить” без специального атрибута файла только для добавления (как объяснено в ответе Стивена), так как это связано с концепцией файлов. Если вы не можете установить этот атрибут, подход “есть унифицирующий слой, который объединяет независимые реализации этого файла” — это единственный выход.

Ваш подход кажется относительно разумным.

Другие подходы предпочитают поддерживать историю в качестве сетевой службы, к которой оболочки подключаются для просмотра и добавления истории. Это может также подойти вам.

Atuin — это такая служба, которую вы можете запустить на своей машине. Проблема, с которой вы столкнетесь, заключается в том, что вам нужно будет не только настроить оболочку в вашем контейнере (в любом случае потребуется сделать это для добавления с использованием файла), но также нужно будет перенаправить порт на вашем хосте в ваш контейнер или в удаленную сессию оболочки и т.д. (Или вы используете их централизованный хостинг оболочки. Содержимое ваших команд оболочки полностью зашифровано, они не могут его читать, но вы не можете скрыть, когда и за какими публичными IP-адресами вы работаете.)

.

Ответ или решение

Чтобы правильно защитить файл .bash_history от усечения, необходимо учесть множество факторов, таких как работа в различных средах и стирание настроек, которые могут повлиять на историю команд. Понимание этих аспектов и использование соответствующих техник поможет сохранить полную историю команд в разных системах.

Теория

.bash_history — это файл, который хранит историю команд Bash, выполненных пользователем. Однако, этот файл может быть усечен из-за действия настройки HISTFILESIZE, которая определяет максимальный размер истории в строках. Когда история достигает этого размера, старые команды удаляются, чтобы освободить место для новых. Это поведение может быть проблематичным в средах, где используются разные настройки, так как они могут превалировать над вашими персональными конфигурациями.

Одним из способов противодействия этому является использование атрибута "только для добавления", если файловая система поддерживает его. Это гарантирует, что команды будут только дописываться в конец файла и никакие другие операции, такие как усечение, не смогут произойти. Однако, это требует прав доступа администратора, что может быть не всегда возможно.

Другой подход заключается в использовании параметра histappend. Эта настройка гарантирует, что новые команды будут добавляться в конец файла .bash_history, а не перезаписывать его с нуля.

Пример

На практике, для настройки файла .bash_history можно выполнить следующие шаги. Во-первых, установите атрибут "только для добавления" для файла .bash_history с помощью команды:

sudo chattr +a .bash_history

После этого нужно включить параметр histappend, добавив в ваш ~/.bashrc следующие строки:

shopt -s histappend

Эти действия обеспечат, что файл всегда будет дополняться, и никакие внешние условия не смогут его усечь.

Приложение

Даже если вышеописанные методы представлены просто, их практическое применение требует соблюдения некоторых тонкостей. Например, если вы работаете в контейнерах, таких как Docker или Singularity, необходимо удостовериться, что конфигурации, специфичные для этих контейнеров, не меняют стандартных настроек, которые вы установили на уровне пользователя.

Так же важно регулярно резервировать файл истории. Похожая на logrotate система резервного копирования, например, может быть полезной в случаях, когда не удается полностью избежать усечения из-за разных сетевых и контейнерных конфигураций. Регулярное копирование файла .bash_history с автоматической ротацией может быть надежной стратегией для восстановления команд, если усечение все-таки произошло.

Помимо этого, можно рассмотреть использование сетевых сервисов управления историей, таких как Atuin, которые позволяют централизованно хранить и управлять историей команд. Это может быть особенно полезно, если у вас есть доступ к собственному серверу, на котором можно развернуть такой сервис, или если вы готовы использовать облачные решения с защитой данных.

Обеспечение целостности и полноты истории команд — задача комплексная, требующая внимательного подхода к настройкам и постоянного мониторинга изменений в различных рабочих средах. Обратите внимание на даем подходы, модернизируйте их под ваши нужды и помните, что в конечном счете ваша история команд — это ключ к восстановлению производительности и эффективности работы в Unix-подобных системах.

Оцените материал
Добавить комментарий

Капча загружается...