
Есть ли какая-либо команда или способ удалить все записи из истории оболочки bash, содержащие определенную строку? Это будет полезно для удаления команд из истории, содержащих пароль. Я знаю, что мы можем удалить каждую запись истории по ее номеру, но проблема в том, что она удаляет только одну запись за раз, и мне нужно каждый раз выводить номер, чтобы удалить новую запись.
например. Команда History показывает 5 записей, содержащих пароль abcabc, и я хочу удалить все записи из команды History, содержащие строку abcabc.
975 2019-03-15 11:20:30 ll
976 2019-03-15 11:20:33 ll cd
977 2019-03-15 11:20:36 ll CD
978 2019-03-15 11:20:45 chown test1:test1 CD
979 2019-03-15 11:20:53 chown test1:test1 ./CD
980 2019-03-15 11:20:57 chown test1:test1 .\CD
981 2019-03-15 11:22:04 cd /tmp/logs/
982 2019-06-07 10:36:33 su test1
983 2019-08-22 08:35:10 su user1
984 2019-08-22 08:35:15 /opt/abc/legacy.exe -password abcabc
985 2019-09-24 07:20:45 cd /opt/test1/v6r2017x
986 2019-09-24 07:20:46 ll
987 2019-09-24 07:21:18 cd /tmp/
988 2019-09-24 07:21:19 ll
989 2019-09-24 07:21:24 cd linux_a64/
990 2019-09-24 07:21:25 /opt/abc/legacy.exe -password abcabc
991 2019-09-24 07:24:03 cd build/
992 2019-09-24 07:24:04 ll
993 2019-09-24 07:24:07 cd ..
994 2019-09-24 07:24:10 /opt/abc/legacy.exe -password abcabc
995 2019-09-24 07:24:15 cd someapp/bin
996 2019-09-24 07:24:21 ll
997 2019-09-24 07:24:33 cd .
998 2019-09-24 07:24:35 cd ..
999 2019-09-24 07:24:36 ll
Попробовал следующую команду, которая выдала ошибку, как указано ниже
servername:~ # sed -i 'g/abcabc/d' /home/user1/.bash_history
sed: -e expression #1, char 2: extra characters after command
Ожидание: ошибок не возникнет, и все записи, содержащие строку abcabc, должны быть удалены.
решение1
Еще один ответ, похожий на ответ @cprn, но с использованием awk
(вместо cut
) и функции:
function del_word_history () {
if [ -z "${1}" ]; then return false; fi
mapfile -t result <<< "$(history | grep "${1}" | tac | awk '{print $1}')"
for idx in "${result[@]}"; do
history -d $idx
done
}
tac
инвертирует строки вывода (в некоторых сообщениях указывалось, что это не свойственно всем системам)[-z $1 ]
:true
если первый аргумент, переданный функции ($1
), пуст.mapfile -t
(страница руководства;некоторые гиды): считываетstdin
в переменную массива (result
)"${result[@]}"
возвращает массив
awk '{print $1}'
(Руководство пользователя GNU,краткие руководства,страница руководства): используется для обоих: определения совпадения и его обработки. Он разделяет данные, разделенные пробелами (по умолчанию), и сохраняет их в$n
переменных.'{pring $1}'
читает длявыполнитьprint
действие над первым словом.
Использование:
del_word_history history
del_word_history abcabc
history -w
Ниже представленоболее чистое решениекоторый проверяет, получили ли мы номер idx
, history
а не какое-либо другое слово многострочной записи:
function del_word_history () {
if [ -z "${1}" ]; then return false; fi
mapfile -t lines <<< "$(history | grep "${1}" | tac)"
for line in "${lines[@]}"; do
idx="$(printf '%s' "${line}" | awk '{ if ($1 ~ /^[0-9]+$/) { print $1 } }')"
if [ -n "${idx}" ]; then
echo "removing line ${idx}"
history -d $idx
fi
done
}
Основные отличия:
- мы получаем полные строки в переменной массива
lines
черезmapfile
awk '{ if ($1 ~ /^[0-9]+$/) { print $1 }}'
проверяет, что первое слово каждой строки является числом, и этоstdout
то же самое первое слово (и попадает вidx
переменную)[ -n ${idx}" ] just checks if
idx` не пуст
решение2
Я знаю, что это старо, но я просто сделал это в цикле, вот так:
for ln in $( history | grep my_phrase | cut -f2 -d' '); do
history -d $ln
done
$(...)
- замена команд,stdout
возвраты...
cut -f2 -d' '
- вырезает 2-й столбец разделенного пробелом вывода, т.е. номер строкиhistory -d $ln
- удаляет указанный номер строки из истории
Одна строка для легкого копирования и вставки:
for ln in $( history | grep my_phrase | cut -f2 -d' '); do history -d $ln; done
решение3
вы могли бы использовать sed
для удаления записей из .bash_history
.
Но так как это пароль, чтобы избежать повторного ввода пароля в CLI, я бы посоветовал вам отредактировать ваш .bashrc
файл и убедиться, что строка с HISTCONTROL
установлена на ignoreboth
или ignorespace
. Это позволит вам вводить команду bash
и не помещать их в историю, если они начинаются с пробела:
promtpt:$ sed -i '/abcabc/d' /home/user/.bash_history
Обратите внимание на пробел между $
и командой, это приведет к тому, что строка будет проигнорирована в истории bash.
-i
: означает редактирование файла в строке.
d
В конце означает удаление строки, содержащей выражение между /
.
Это решение работает только на Linux GNU sed
.