Как я могу увидеть точную командную строку, выполняемую внутри некоторого экземпляра bash?
У меня длинный экземпляр bash
(внутри screen
), который выполняет сложный набор команд внутри цикла (каждый цикл делает трубы, перенаправляет и т. д.).
Длинная командная строка была написана внутри терминала - она не находится внутри какого-либо скрипта. Теперь я знаю идентификатор процесса bash, и у меня есть root-доступ - как я могу видеть, что точная командная строка выполняется внутри этого bash
?
bash$ echo $$
1234
bash$ while true ; do \
someThing | somethingElse 2>/foo/bar | \
yetAnother ; sleep 600 ; done
И в другом экземпляре оболочки я хочу видеть, что командная строка выполняется внутри PID 1234:
bash$ echo $$
5678
bash$ su -
sh# cd /proc/1234
sh# # Do something here that will display the string \
'while true ; do someThing | somethingElse 2>/foo/bar | \
yetAnother ; sleep 600 ; done'
Возможно ли это?
EDIT # 1
Добавление встречных примеров для некоторых ответов, которые у меня есть.
-
Об использовании
cmdline
в разделе/proc/PID
: это не работает, по крайней мере, не в моем сценарии. Вот простой пример:$ echo $$ 8909 $ while true ; do echo 1 ; echo 2>/dev/null ; sleep 30 ; done
В другой оболочке:
$ cat /proc/8909/cmdline bash
-
Использование
ps -p PID --noheaders -o cmd
так же бесполезно:$ ps -p 8909 --no-headers -o cmd bash
-
ps -eaf
также не помогает:$ ps -eaf | grep 8909 ttsiod 8909 8905 0 10:09 pts/0 00:00:00 bash ttsiod 30697 8909 0 10:22 pts/0 00:00:00 sleep 30 ttsiod 31292 13928 0 10:23 pts/12 00:00:00 grep --color=auto 8909
То есть, нет вывода командной строки ORIGINAL, что я и ищу - т.е.
while true ; do echo 1 ; echo 2>/dev/null ; sleep 30 ; done
.
3 ответа
Я знал, что хватаюсь за соломинку, но UNIX никогда не терпит неудачу!
Вот как мне это удалось:
bash$ gdb --pid 8909
...
Loaded symbols for /lib/i386-linux-gnu/i686/cmov/libnss_files.so.2
0xb76e7424 in __kernel_vsyscall ()
Затем в приглашении (gdb)
я запустил команду, call write_history("/tmp/foo")
, который будет записывать эту историю в файл /tmp/foo
.
(gdb) call write_history("/tmp/foo")
$1 = 0
Затем я отсоединяюсь от процесса.
(gdb) detach
Detaching from program: /bin/bash, process 8909
И закройте gdb
.
(gdb) q
И конечно же ...
bash$ tail -1 /tmp/foo
while true ; do echo 1 ; echo 2>/dev/null ; sleep 30 ; done
Для облегчения повторного использования в будущем я написал сценарий bash , автоматизируя процесс.
Поскольку команда все еще запущена на экране, ее родительский bash не перечитывал любую историю, поэтому:
- повторное подключение к экрану
- нажмите
^Z
, затемup arrow
- bonus: оберните команду в одинарные кавычки (перемещаясь с помощью
^A^A
), потому что экран (1) - и^E
) и echo + перенаправить в файл -
fg
продолжить выполнение команды
Есть предостережения, но это довольно полезно в большинстве случаев.
Я знаю, что вы нашли свой собственный ответ, но есть причина, по которой вы не можете сделать что-то вроде этого:
(set -x; for f in 1 2 3 4 ; do echo "$f"; sleep $f; done)
Возможно, вы не можете согласовать вывод фактического задания и вывод из bash, показывающий текущую строку выполнения.
Кроме того, FWIW, если вы предпочитаете многословие, set -o xtrace
.