интересная дилемма. Это Centos. Вчера вечером я вошел в физическую консоль на tty. Я запустил команду и позволил ей работать всю ночь. Терминал по-прежнему находится в системе, но в настоящее время я удаленно авторизован через ssh (меня нет на консоли).
Я хотел бы знать точные параметры команды, которые я использовал (я не помню), поэтому я хотел бы увидеть команду, которую я выполнял на этом терминале. Поскольку оболочка все еще работает, она ничего не записала в bash_history - история этого экземпляра все еще находится в памяти.
Итак, мой вопрос в том, есть ли способ удаленно получить то, что я хочу, возможно:
(a) отправка сигнала запущенной оболочке, заставляющая ее сбрасывать свою историю bash (b) изучение среды запущенной оболочки для получения информации о ее истории (c) проверка последних x # строк из сеанса tty, чтобы Я вижу, что я напечатал
или каким-то другим способом ....
Хорошо, я разобрался. На самом деле это довольно изящная вещь, поскольку я предвижу, что она найдет множество применений.
открыть сеанс ssh на удаленном хосте. запустить сеанс экрана или tmux с несколькими окнами. Вы можете определить псевдоустройство для каждого окна, набрав «tty». Допустим, у нас есть «/ dev / pts / [123]», соответствующий трем оболочкам, которые мы запускаем в сеансе экрана.
определить pid рассматриваемого процесса bash (того, для которого вы хотите перенаправить ввод и вывод). этот процесс в настоящее время связан с терминальным устройством, таким как / dev / tty1
из окна экрана 1 запустите «gdb -p [pid]» и выполните следующие команды в gdb:
а. p dup2 (open ("/ dev / pts / 2", 0), 0) # это изменяет стандартный ввод для целевого процесса
б. p dup2 (open ("/ dev / pts / 3", 1), 1) # это изменяет стандартный вывод для целевого процесса
c. p dup2 (open ("/ dev / pts / 3", 1,), 2) # это изменяет стандартную ошибку для целевого процесса
d. отделить
е. уволиться
Другими словами, шаг 3 делает Окно 2 стандартным вводом, а Окно 3 выводом.
4. из окна 1 (/ dev / pts / 1) «ls -l / proc / [pid] / fd», чтобы проверить изменения файлового дескриптора для процесса bash, которым мы хотим управлять
5. то, что вы вводите в окне 2, теперь передается в два места: исходная оболочка bash, связанная с этим окном, и целевой процесс. поэтому в окне 2 (/ dev / pts / 2) введите «hhiissttoorryy [return] [return]». Причина, по которой вы должны вводить все дважды, заключается в том, что входные данные делятся как на текущую оболочку bash, так и на целевую оболочку bash. Это потому, что операционная система знает, что есть два источника, которые используют ввод с клавиатуры для / dev / pts / 2, и справедливо распределяет символы, которые вы вводите. первый символ переходит к одному месту назначения, следующий - ко второму месту назначения и т. д. Если у вас было три процесса, чей стандартный ввод был / dev / pts / 3, то вам пришлось бы вводить каждый символ по три раза. Ядро передает входящие символы получателям циклически.
6. Вы можете обойти вышеуказанное неудобство, временно установив stdin для исходной оболочки Window 2 bash на какое-либо неиспользуемое устройство, например / dev / tty5 или что-то в этом роде. это делает клавиатуру / dev / pts / 2 стандартным вводом только для одного процесса (вместо двух). теперь вы можете вводить команды как обычно (они просто не будут отображаться на экране, в котором вы находитесь, вместо этого они будут отображаться в / dev / pts / 3).
7. так как вы набрали «история» и она была передана целевому процессу, стандартный вывод которого - окно 3, переключитесь в окно 3, чтобы вы могли видеть вывод команды. теперь у вас есть история команд для целевой оболочки bash.
8. вернувшись в окно 1, снова используйте gdb на [pid], чтобы сбросить стандартные значения in, out, err для целевой оболочки обратно к их исходным значениям (/ dev / tty1). И вы также можете вернуть стандартный ввод Window 2 на то, что должно быть.
Обратите внимание, что когда вы запускаете gdb в запущенном процессе, он приостанавливает выполнение процесса так же, как и SIGSTOP. Когда вы его «отсоединяете», он возобновляет работу, как в SIGCONT. Это позволяет манипулировать дескрипторами файлов без неблагоприятных последствий.
Я не пробовал, но вы, вероятно, можете сделать описанное выше еще проще и удобнее, открыв оболочку, определив ее tty или pty, временно установив назначенный стандарт оболочки для неиспользуемого устройства, назначив tty / pty как стандартный ввод / вывод для целевой оболочки. Таким образом, вы можете использовать один экран для всего ввода и вывода с целевой оболочкой.
РЕЗЮМЕ: с помощью описанной выше процедуры, если у вас есть оболочка, к которой у вас есть доступ, вы можете использовать ее в качестве стандартного входа / выхода для любого другого процесса / оболочки в системе. Это полезно, например, если вы хотите взаимодействовать с оболочкой, запущенной на консоли, но у вас нет физического доступа к хосту (или решения для отключения света). Это, конечно, можно обобщить на любое количество ситуаций, когда вы хотите, чтобы конкретная оболочка контролировала ввод / вывод для любого процесса по вашему выбору.
Я до сих пор сталкиваюсь с этой ситуацией полурегулярно и, наконец, придумал несколько более простых способов восстановления команд истории в памяти из моих "осиротевших" сеансов bash:
(примечание: в каждом примере ниже замените PID
с идентификатором процесса осиротевшего сеанса bash)
history -a
:$ gdb -p PID -batch -ex 'call maybe_append_history(get_string_value("HISTFILE"))'
$ gdb -p PID -batch -ex 'call append_history(10, "'$(tty)'")'
$ gdb -p PID -batch -ex 'call write_history("/tmp/history-backup.txt")'
Ноты:
sudo gdb
- даже для доступа к моим собственным процессам bash.$1 = 0
(если вы видите другие значения, они, вероятно, errno
's - например, при попытке добавить в файл, который еще не существует, вы получите $1 = 2
(ENOENT)).history
команда; например: builtins / history.def # L203-L212Вы можете получить эту информацию из /proc/${PID}/cmdline
.