
Existe algum comando ou maneira de remover todas as entradas do histórico do shell bash contendo uma string específica? isso será útil para remover comandos do histórico contendo senha. Eu sei que podemos remover cada entrada do histórico pelo seu número, mas o problema é que ela exclui apenas uma entrada por vez e preciso retirar o número a cada vez para remover uma nova entrada.
por exemplo. O comando histórico mostra 5 entradas contendo a senha abcabc e quero remover todas as entradas do comando histórico contendo a string 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
Tentei seguir o comando que deu o erro conforme indicado abaixo
servername:~ # sed -i 'g/abcabc/d' /home/user1/.bash_history
sed: -e expression #1, char 2: extra characters after command
Expectativa: Nenhum erro e todas as entradas contendo a string abcabc devem ser removidas.
Responder1
Outra semelhante à resposta do @cprn, mas usando awk
(em vez de cut
) e uma função:
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
inverte as linhas da saída (alguns posts apontaram que não é comum a todos os sistemas)[-z $1 ]
:true
se o primeiro argumento passado para a função ($1
) estiver vazio.mapfile -t
(página de manual;alguns guias): lêstdin
em uma variável de array (result
)"${result[@]}"
retorna a matriz
awk '{print $1}'
(Guia do usuário GNU,breves guias,página de manual): usado para ambos: identificar uma correspondência e processá-la. Ele divide os dados delimitados por espaços em branco (padrão) e os armazena nas$n
variáveis.'{pring $1}'
lê paraexecutarprint
ação na primeira palavra.
Uso:
del_word_history history
del_word_history abcabc
history -w
O abaixo é umsolução mais limpaque verifica se obtivemos o idx
número de history
, em vez de alguma outra palavra de uma entrada multilinha:
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
}
As principais diferenças são:
- obtemos as linhas completas na variável array
lines
viamapfile
awk '{ if ($1 ~ /^[0-9]+$/) { print $1 }}'
verifica se a primeira palavra de cada linha é um número e éstdout
a mesma primeira palavra (e chega àidx
variável)[ -n ${idx}" ] just checks if
idx` não está vazio
Responder2
Eu sei que é antigo, mas fiz isso em um loop assim:
for ln in $( history | grep my_phrase | cut -f2 -d' '); do
history -d $ln
done
$(...)
- substituição de comando, retornosstdout
de...
cut -f2 -d' '
- corta a segunda coluna da saída delimitada por espaço, ou seja, número da linhahistory -d $ln
- remove determinado número de linha do histórico
Um forro para fácil copiar e colar:
for ln in $( history | grep my_phrase | cut -f2 -d' '); do history -d $ln; done
Responder3
você pode usar sed
para remover entradas de .bash_history
.
Mas como é uma senha para evitar digitá-la novamente na CLI, aconselho você a editar seu .bashrc
arquivo e garantir que a linha with HISTCONTROL
esteja definida como ignoreboth
ou ignorespace
. Isso permitiria que você digitasse o comando bash
e não os colocasse no histórico se eles começassem com um espaço:
promtpt:$ sed -i '/abcabc/d' /home/user/.bash_history
Observe o espaço entre $
e o comando, isso faria com que a linha fosse ignorada no histórico do bash.
-i
: significa editar arquivo embutido.
d
no final significa remover a linha contendo a expressão entre /
.
Esta solução só funciona em Linux GNU sed
.