Qual é a melhor maneira de remover automaticamente .zsh_history após um certo tempo?

Qual é a melhor maneira de remover automaticamente .zsh_history após um certo tempo?

Eu sinto que existenenhuma opção de configuração ZSHpara remover automaticamente .zsh_historyapós um determinado período (por exemplo, com mais de um mês a partir de agora). Qual seria o hack mais simples para conseguir isso?

Responder1

Correto, não há opções de expiração baseadas em tempo para .zsh_history. Provavelmente porque qualquer tipo de expiração cronometrada requer o EXTENDED_HISTORYformato (que inclui o horário de início de cada comando) e EXTENDED_HISTORYé um recurso mais novo – mais recente que a maioria das opções de expiração, pelo menos.

Além disso, a funcionalidade zsh não tem o melhor relacionamento com o conceito confuso de "tempo" - basta ler as restrições nos sinalizadores globbing baseados em tempo para apreciar isso:

Qualquer parte fracionária da diferença entre o tempo de acesso e a parte atual nas unidades apropriadas é ignorada na comparação. Por exemplo, echo *(ah-5)ecoaria arquivos acessados ​​nas últimas cinco horas, enquanto echo *(ah+5)ecoaria arquivos acessados ​​há pelo menos seis horas, já que tempos estritamente entre cinco e seis horas são tratados como cinco horas.

Além disso, se você tiver alguma das opções de remoção de duplicatas ativada, o zsh removerámais velhoentradas em favor da mais nova, portanto a lista de entradas "antigas" está em constante fluxo, tornando a expiração baseada no tempo mais complicada.

Se você quiser fazer isso, como diz LSerni, analisar você mesmo é provavelmente a melhor opção. Uma coisa complicada sobre isso é que as entradas de várias linhas no histórico são escritas literalmente, ou seja, em várias linhas - então você não pode analisá-las simplesmente "linha por linha" porque algumas linhas não são entradas do histórico, elas são continuações.

Minha outra preocupação é que provavelmente não háverdadeiramentemaneira segura de fazer isso, exceto integrá-lo diretamente ao gerenciamento de histórico do zsh, porque qualquer código externo que modifique o arquivo de histórico está em constante perigo de interferência (ou interferência) de uma instância em execução do zsh. Quero dizer, a menos que você escreva algo bashque só funcione quando vocênão é possívelestar logado, como durante as partes de usuário único dos processos de inicialização ou desligamento.

Este código Python evita esse problema copiando o histórico para um novo arquivo, lendo-o e, em seguida, gravando as entradas que passam a data limite para umdiferentenovo arquivo. O arquivo de destino pode ser alterado para .zsh_historysubstituir o arquivo original, mas não assumo nenhuma responsabilidade por qualquer corrupção de arquivo que possa ocorrer.

Entradas mais antigas CUTOFFsão descartadas (usei 7 dias no exemplo, mas você pode facilmente mudar 7para 30ou 31por um mês). Presume-se que isso esteja sendo executado $HOMEcomo diretório de trabalho.

Isso também pressupõe que o histórico seja classificado por tempo, não sei quão segura é essa suposição. (Se não for verdade, você pode acabar mantendo mais entradas do que o pretendido, porque uma vez atingido o carimbo de data e hora da primeira entradadepoiso tempo limite, tudo depois está incluído. Portanto, as entradas mais antigas que vierem depois da primeira mais recente serão preservadas acidentalmente. O que parece ser o tipo certo de resultado incorreto a ser favorecido, em vez de possivelmente descartar algo não intencional.)

#!/usr/bin/python3

import shutil
import time
from itertools import dropwhile

CUTOFF = time.time() - (86400 * 7)  # one week ago

hist = []
shutil.copy2(".zsh_history", ".zsh_history.bak")
with open(".zsh_history.bak", "rb") as f:
    for l in f.readlines():
        if l.startswith(b': '):
            # Start of a new history entry
            # Add a new tuple (time, history_line) to the list
            ts = int(l.split(b':')[1])
            hist.append((ts, l))
            continue
        # Continuation line, append it to the previous entry
        prev = hist.pop()
        hist.append((prev[0], b''.join([prev[1], l])))

with open(".zsh_history.new", "wb") as f:
    # Drop list entries while timestamp < CUTOFF,
    # Then write contents of each remaining entry to file
    for l in dropwhile(lambda x: x[0] < CUTOFF, hist):
        f.write(l[1])

informação relacionada