Como pegar o histórico bash ou as últimas x linhas numéricas do processo shell rodando em outro tty

5

interessante pequeno dilema. Este é o Centos. Ontem à noite eu entrei no console físico em um tty. Eu lancei um comando e o deixei rodar durante a noite. O tty ainda está logado, mas atualmente estou logado remotamente via ssh (não estou no console).

Gostaria de saber os parâmetros de comando exatos que usei (não me lembro), então gostaria de ver o comando que executei nesse tty. Como o shell ainda está em execução, ele não escreveu nada em bash_history - o histórico dessa instância ainda está na memória.

Então, minha pergunta é se existe uma maneira de recuperar remotamente o que eu quero, talvez:

(a) enviando um sinal para o shell em execução, fazendo com que ele descarregue seu histórico bash (b) examinar o ambiente da concha em funcionamento para obter sua informação histórica (c) examinando o xx mais recente das linhas da sessão tty para que eu possa ver o que eu digitei

ou algum outro meio ....

    
por Michael Martinez 25.07.2013 / 19:14

3 respostas

3

Ok, eu percebi. Esta é realmente uma coisa muito bacana de saber, como posso prever ter muitos usos.

  1. abra uma sessão ssh no host remoto. Inicie uma tela ou sessão tmux com algumas janelas. Você pode determinar o pseudo-dispositivo para cada janela digitando "tty". Digamos que temos "/ dev / pts / [123]" correspondente a três shells que estamos executando na sessão de tela

  2. determine o pid do processo bash em questão (aquele para o qual você quer redirecionar entrada e saída). este processo está atualmente associado a um dispositivo de terminal como / dev / tty1

  3. da janela de tela 1, execute "gdb -p [pid]" e execute os seguintes comandos no gdb:

    a. p dup2 (open ("/ dev / pts / 2", 0), 0) # isto muda a entrada padrão para o processo alvo

    b. p dup2 (open ("/ dev / pts / 3", 1), 1) # isto muda a saída padrão para o processo alvo

    c. p dup2 (open ("/ dev / pts / 3", 1,), 2) # isto muda o erro padrão para o processo alvo

    d. desanexar

    e. sair

em outras palavras, o que a etapa 3 faz é tornar a janela 2 a entrada padrão e a janela 3 a saída.

4.da janela 1 (/ dev / pts / 1), "ls -l / proc / [pid] / fd" para verificar as alterações do descritor de arquivo para o processo bash que queremos manipular

5.o que você digita na janela 2 agora é alimentado em dois lugares: o shell bash original associado a essa janela e o processo de destino. portanto, na janela 2 (/ dev / pts / 2), digite "hhiissttoorryy [return] [return]". o motivo pelo qual você precisa digitar tudo duas vezes é porque a entrada é dividida para o shell bash atual e o shell bash de destino. Isso ocorre porque o operador sabe que há duas fontes que estão tocando na entrada do teclado para / dev / pts / 2 e distribui de forma justa os caracteres digitados. o primeiro caractere vai para um destino, o próximo vai para o segundo destino, etc. Se você tivesse três processos cujo stdin era / dev / pts / 3, você teria que digitar cada caractere três vezes. O kernel alimenta os caracteres de entrada no modo round-robin para os destinatários.

6. Você pode contornar o inconveniente acima, definindo temporariamente o stdin para o shell bash original do Windows 2 para algum dispositivo não utilizado, como / dev / tty5 ou algo assim. isso faz com que o teclado / dev / pts / 2 seja a entrada padrão para apenas um processo (em vez de dois). Agora você pode digitar os comandos como normais (eles simplesmente não serão ecoados na tela em que você está, eles serão ecoados para / dev / pts / 3).

7. uma vez que você digitou 'history' e foi alimentado para o processo de destino, cujo stdout é a janela 3, mude para a janela 3 para que você possa ver a saída do comando. agora você tem o histórico de comandos para o shell bash de destino.

8. volte à janela 1, use gdb novamente em [pid] para redefinir o padrão in, out, err para o shell de destino de volta para seus valores originais (/ dev / tty1). E você também pode definir o stdin da Janela 2 de volta para o que deveria ser.

  1. Se quiser, você pode limpar os descritores de arquivos extras removendo-os com 'exec 3 > & -' para remover o fd 3, por exemplo

Observe que, quando você executa o gdb em um processo em execução, ele suspende a execução do processo da mesma maneira que o SIGSTOP. Quando você o "desconecta", ele retorna como no SIGCONT. Isso permite manipular os descritores de arquivos sem consequências adversas.

Eu não tentei, mas provavelmente você pode tornar o acima exposto ainda mais fácil e amigável ao abrir um shell, determinando seu tty ou pty, temporariamente definindo o padrão atribuído do shell para um dispositivo não-utilizado, atribuindo o tty / pty como padrão in / out para o shell de destino. Dessa forma, você pode usar uma única tela para todas as entradas e saídas com o shell de destino.

RESUMO: com o procedimento acima, desde que você tenha um shell para o qual tenha acesso, você pode usá-lo como entrada / saída padrão para qualquer outro processo / shell no sistema. Isso é útil, por exemplo, se você quiser interagir com um shell em execução no console, mas não tiver acesso físico ao host (ou a uma solução sem iluminação). Isso, obviamente, pode ser generalizado para qualquer número de situações em que você deseja que um shell específico assuma o controle da entrada / saída para qualquer processo de sua escolha.

    
por 26.07.2013 / 03:16
1

Ainda enfrento esta situação semi-regulatória e finalmente encontrei algumas maneiras mais simples de recuperar comandos de histórico na memória de minhas sessões bash "órfãs":

(nota: em cada exemplo abaixo, substitua PID pelo id do processo da sessão bash órfã)

Acione efetivamente history -a :

$ gdb -p PID -batch -ex 'call maybe_append_history(get_string_value("HISTFILE"))'

Despeje as últimas 10 entradas do histórico no seu terminal local (pty)

$ gdb -p PID -batch -ex 'call append_history(10, "'$(tty)'")'

Backup de todo o histórico em um arquivo temporário:

$ gdb -p PID -batch -ex 'call write_history("/tmp/history-backup.txt")'

Notas:

  • Testado com o bash 4.3 no Ubuntu 16.04.01.
  • No meu sistema, eu tive que invocar usando sudo gdb - até mesmo para acessar meus próprios processos bash.
  • Se a chamada for bem sucedida, você deverá ver $1 = 0 (se vir outros valores, eles provavelmente são errno 's - por exemplo, ao tentar anexar a um arquivo que ainda não existe, você receberá $1 = 2 (ENOENT)).
  • Essa abordagem é baseada em estudar o que o código bash C faz em resposta ao comando history ; Por exemplo: builtins / history.def # L203-L212
por 02.04.2017 / 21:22
-1

Você pode conseguir essas informações em /proc/${PID}/cmdline .

    
por 25.07.2013 / 19:23