Question Comment récupérer l’historique bash ou les dernières lignes du numéro x du processus shell exécuté sur un autre terminal


intéressant petit dilemme. C'est centos. La nuit dernière, je me suis connecté à la console physique sur un terminal. J'ai lancé une commande et l'ai laissée courir pendant la nuit. Le terminal est toujours connecté, mais je suis actuellement connecté à distance via ssh (je ne suis pas sur la console.)

J'aimerais connaître les paramètres de commande exacts que j'ai utilisés (je ne m'en souviens pas), alors j'aimerais voir la commande que j'ai exécutée sur ce terminal. Comme le shell est toujours en cours d'exécution, il n'a rien écrit dans bash_history - l'historique de cette instance est toujours en mémoire.

Donc, ma question est de savoir s'il existe un moyen de récupérer à distance ce que je veux, peut-être:

(a) envoyer un signal au shell en cours d'exécution, le faisant vider son historique bash (b) examiner l'environnement du shell en cours d'exécution pour obtenir ses informations d'historique (c) examiner le x # de lignes le plus récent de la session tty afin que je puisse voir ce que j'ai tapé

ou un autre moyen ...


5
2017-07-25 17:14


origine


Tuer le processus de shell? Graceful terminate écrira bash_history. - Nathan C
Oui, j'envisage cela, mais je risque de perdre l'historique que je veux si d'autres processus bash écrivent eux-mêmes beaucoup d'histoire (> HISTSIZE). Je suis en quelque sorte à la recherche d'une solution pour laquelle je n'ai pas à tuer le processus shell. - Michael Martinez
Pour référence ultérieure, vous pouvez demander à bash de mettre à jour automatiquement le fichier d’historique après chaque commande. Puis un simple history vous aurait montré. Voir unix.stackexchange.com/questions/1288/… - Mark Wagner


Réponses:


Ok, je l'ai compris. C’est en fait une très bonne chose à savoir, car je peux prévoir qu’elle aura de nombreuses utilisations.

  1. ouvrez une session ssh sur l'hôte distant. lancer une session screen ou tmux avec quelques fenêtres. Vous pouvez déterminer le pseudo-périphérique pour chaque fenêtre en tapant "tty". Disons que nous avons "/ dev / pts / [123]" correspondant à trois shells que nous exécutons dans la session screen

  2. détermine le pid du processus bash en question (celui pour lequel vous voulez rediriger les entrées et les sorties). ce processus est actuellement associé à un périphérique terminal tel que / dev / tty1

  3. à partir de la fenêtre d’écran 1, exécutez "gdb -p [pid]" et exécutez les commandes suivantes dans gdb:

    une. p dup2 (open ("/ dev / pts / 2", 0), 0) # ceci modifie l’entrée standard du processus cible

    b. p dup2 (open ("/ dev / pts / 3", 1), 1) # cela modifie la sortie standard du processus cible

    c. p dup2 (open ("/ dev / pts / 3", 1,), 2) # change l’erreur standard pour le processus cible

    ré. détacher

    e. quitter

en d'autres termes, l'étape 3 fait de Window 2 l'entrée standard et de Window 3 la sortie.

4.de la fenêtre 1 (/ dev / pts / 1), "ls -l / proc / [pid] / fd" pour vérifier les modifications du descripteur de fichier pour le processus bash que nous voulons manipuler

5.ce que vous tapez dans la fenêtre 2 est maintenant alimenté à deux endroits: le shell bash d'origine associé à cette fenêtre et le processus cible. par conséquent, à partir de la fenêtre 2 (/ dev / pts / 2), tapez "hhiissttoorryy [return] [return]". la raison pour laquelle vous devez tout taper deux fois est que l'entrée est divisée à la fois dans le shell bash actuel et le shell bash cible. En effet, le système d'exploitation sait que deux sources exploitent l'entrée du clavier pour / dev / pts / 2 et qu'il répartit équitablement les caractères que vous tapez. le premier caractère va à une destination, le suivant va à la deuxième destination, etc. Si vous aviez trois processus dont le stdin était / dev / pts / 3, vous devrez alors taper chaque caractère trois fois. Le noyau fournit les caractères saisis tour à tour aux destinataires.

6.Vous pouvez contourner l'inconvénient ci-dessus en définissant temporairement le stdin du shell bash de Windows 2 d'origine sur un périphérique inutilisé, tel que / dev / tty5 ou quelque chose du genre. cela fait du clavier / dev / pts / 2 l’entrée standard pour un seul processus (au lieu de deux). vous pouvez maintenant taper les commandes comme d'habitude (elles ne seront simplement pas répercutées sur l'écran dans lequel vous vous trouvez, elles seront répercutées sur / dev / pts / 3 à la place.)

Depuis que vous avez tapé "historique" et qu'il a été transmis au processus cible, dont la sortie standard est stdout (fenêtre 3), basculez vers la fenêtre 3 afin que vous puissiez voir le résultat de la commande. vous avez maintenant l'historique des commandes pour le shell bash cible.

8. De retour à la fenêtre 1, utilisez à nouveau gdb sur [pid] pour réinitialiser le standard in, out, err pour que le shell cible retrouve ses valeurs d'origine (/ dev / tty1). Et vous pouvez également régler le Window 2 stdin sur ce qu'il devrait être.

  1. Si vous le souhaitez, vous pouvez nettoyer les descripteurs de fichier supplémentaires en les supprimant avec 'exec 3> & -' pour supprimer fd 3 par exemple

Notez que lorsque vous exécutez gdb sur un processus en cours d'exécution, il suspend l'exécution du processus de la même manière que SIGSTOP. Lorsque vous le "détachez", il reprend comme dans SIGCONT. Cela vous permet de manipuler les descripteurs de fichier sans conséquences néfastes.

Je ne l'ai pas essayé, mais vous pouvez probablement rendre ce qui précède encore plus facile et convivial en ouvrant un shell, en déterminant son tty ou son pty, en définissant temporairement la norme assignée au shell par un périphérique inutilisé, en assignant le tty / pty en entrée / sortie standard pour le shell cible. De cette façon, vous pouvez utiliser un seul écran pour toutes les entrées et sorties avec le shell cible.

Résumé: avec la procédure ci-dessus, tant que vous avez un shell auquel vous avez accès, vous pouvez l’utiliser comme entrée / sortie standard pour tout autre processus / shell du système. Ceci est utile, par exemple, si vous souhaitez interagir avec un shell qui s'exécute sur la console, mais que vous n'avez pas d'accès physique à l'hôte (ou à une solution light-out). Ceci peut bien sûr être généralisé à un certain nombre de situations dans lesquelles vous souhaitez qu'un shell spécifique prenne le contrôle de l'entrée / sortie pour n'importe quel processus de votre choix.


3
2017-07-26 01:16





Je fais toujours face à cette situation de façon semi-régulière et j'ai finalement trouvé des moyens plus simples de récupérer des commandes d'historique en mémoire à partir de mes sessions bash "orphelines":

(note: dans chaque exemple ci-dessous, remplacez PID avec l'ID de processus de la session bash orpheline)

Déclencher efficacement history -a:

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

Déposez les 10 dernières entrées d’historique sur votre terminal local (pty)

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

Sauvegarder l'intégralité de l'historique dans un fichier temporaire:

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

Remarques:

  • Testé avec bash 4.3 sur Ubuntu 16.04.01.
  • Sur mon système, je devais invoquer en utilisant sudo gdb - même pour accéder à mes propres processus bash.
  • Si l'appel est réussi, alors vous devriez voir $1 = 0 (Si vous voyez d'autres valeurs, elles sont susceptibles errnoC'est comme lorsque vous essayez d'ajouter un fichier qui n'existe pas encore, vous obtiendrez $1 = 2 (ENOENT)).
  • Cette approche est basée sur l’étude de ce que le code bash C fait en réponse à la historycommander; par exemple: builtins / history.def # L203-L212

1
2018-04-02 19:22



Je vais devoir vérifier ceci. Cela semble être un moyen plus simple que la façon compliquée dont je m'approchais. - Michael Martinez
Néanmoins, je pense qu’il est intéressant de disposer d’un éventail de solutions permettant de récupérer l’historique des commandes orphelines. Votre approche nécessite davantage de configuration, mais fonctionne avec presque tous les types de REPL (bash, zsh, tcsh, node.js, mongo, etc.); mes deux derniers exemples sont spécifiques aux logiciels utilisant GNU Readline; et premier exemple à bash. - humbletim


Vous pourrez peut-être obtenir ces informations auprès de /proc/${PID}/cmdline.


-1
2017-07-25 17:23



Non, cela vous donne la ligne de commande du processus en cours, qui est simplement "-bash" (le shell de connexion). Le processus en question est déjà terminé. - Michael Martinez
Vous devez utiliser le PID du processus que vous souhaitez consulter. Je pensais que vous aviez dit que le processus que vous souhaitiez était toujours en cours, de toute évidence, je lisais mal. - John
Oui, j'aurais dû dire que cela ne fonctionne plus. Je pense qu’il devrait exister un moyen de récupérer l’historique bash de sa mémoire / environnement, ou d’examiner la "vue" du tty (ses 10 dernières lignes environ) sans recourir à la programmation en C pour le faire. - Michael Martinez
D'accord, j'ai compris, mais comme je viens de m'inscrire, je ne peux pas "répondre à ma propre question" avant 8 heures. Je posterai ma réponse ici demain. - Michael Martinez