Как просмотреть вывод работающего процесса в другой сессии bash?

200

Я оставил скрипт, работающий на удаленной машине, когда работал на нем локально. Я могу подключиться через SSH к компьютеру от имени того же пользователя и увидеть, как работает скрипт ps.

$ ps aux | grep ipcheck
myuser  18386  0.0  0.0  18460  3476 pts/0    S+   Dec14   1:11 /bin/bash ./ipchecker.sh

Это просто вывод на стандартный вывод в локальном сеансе (я запускал ./ipchecker.shиз окна локального терминала, без перенаправления, без использования screenetc).

Есть ли в любом случае из сеанса SSH я могу просмотреть вывод этой запущенной команды (не останавливая ее)?

Пока лучшее, что я нашел, - это использовать, strace -p 18386но я получаю орды текста, взлетающего по экрану, это слишком детально. Я могу остановиться, straceа затем просеять вывод и найти текст, выводимый на стандартный вывод, но он очень длинный и запутанный, и, очевидно, пока он остановлен, я могу что-то пропустить. Я хотел бы найти способ увидеть вывод сценария вживую, как если бы я работал локально.

Кто-нибудь может улучшить это? Очевидный ответ - перезапустить скрипт с перенаправлением или в screenсеансе и т. Д., Это не критически важный сценарий, поэтому я мог бы это сделать. Скорее, однако, я вижу это как забавное учебное упражнение.

jwbensley
источник
Ваш процесс работает в виртуальной консоли или в среде, подобной GUI / xterm?
Джиппи
4
Вы можете ограничить вывод strace одним системным вызовом:strace -p 4232 -e write
otokan
@jippie На машине установлен полный графический интерфейс (Linux Mynt 13, рабочий стол XFCE), я запустил gnome-терминал.
jwbensley
3
На этом сайте есть как минимум дюжина подобных вопросов. Ищите reptyr здесь, чтобы найти несколько из них (и ответ).
Стефан Шазелас

Ответы:

180

Если все, что вы хотите сделать, это шпионить за существующим процессом, вы можете использовать strace -p1234 -s9999 -e writeгде 1234 - это идентификатор процесса. ( -s9999избегает сокращения строк до 32 символов и writeсистемного вызова, который производит вывод.) Если вы хотите просматривать только данные, записанные в определенном файловом дескрипторе, вы можете использовать что-то вроде strace -p1234 -e trace= -e write=3просмотра только данных, записанных в файловом дескрипторе 3 ( -e trace=предотвращает систему звонки от входа). Это не даст вам выход, который уже был произведен.

Если вывод прокручивается слишком быстро, вы можете lessнаправить его в пейджер, например , или отправить его в файл с помощью strace -o trace.log ….

Во многих программах вы можете перенаправить последующий вывод с помощью ptrace hack, либо на ваш текущий терминал, либо на новый сеанс экрана. См. Как я могу отречься от запущенного процесса и связать его с новой экранной оболочкой? и другие связанные темы.

Обратите внимание, что в зависимости от того, как настроена ваша система, вам может потребоваться выполнить все эти straceкоманды от имени пользователя root, даже если процесс выполняется под вашим пользователем без каких-либо дополнительных привилегий. (Если процесс запущен от имени другого пользователя или установлен как setuid или setgid, вам потребуется запускать straceс правами root.) Большинство дистрибутивов позволяют процессу отслеживать только его дочерние элементы (это обеспечивает умеренное преимущество в плане безопасности - предотвращает некоторые непосредственные внедрения вредоносного ПО, но не предотвращает косвенную инъекцию путем изменения файлов). Это контролируется kernel.yama.ptrace_scomesysctl.

жилль
источник
18
Я не думаю, что есть способ сузить вывод до стандартного вывода ?
Джона
3
Можете ли вы объяснить все аргументы?
Пользователь
6
Было много обратной косой черты и чисел во многих выходных данных, которые я получал от nodejs; Есть ли какие-либо сведения о том, в какой кодировке они могут быть? Также было много простого текста, и это было все, что мне было нужно.
ThorSummoner
3
"Можете ли вы объяснить все аргументы?" @ Пользователь:man strace
Pistos
3
@RafaelMoni Программа для выполнения того, что вы просите, называется отладчиком.
Жиль
140

Вы можете получить доступ к выводу через procфайловую систему.

tail -f /proc/<pid>/fd/1

1= stdout, 2= stderr

tvlooy
источник
7
Он дает мне: «не могу открыть / proc / <мой pid> / fd / 1 для чтения: нет такого устройства или адреса».
Ярослав Никитенко
18
да <мой pid> должен быть вашим идентификатором процесса
tvlooy
29
Это не сработает, если вывод идет в tty (или перенаправлен на /dev/null) - он будет работать, только если вывод перенаправлен в файл.
mattdm
1
Протестировано на Ubuntu 16.04, и оно не работает. В сеансе я делаю: ping google.esа в другом - как root: tail -f /proc/`pgrep ping`/fd/2и ничего не отображается.
david.perez
1
Ты прав. Потому что fd 1 и 2 являются символическими ссылками на устройство / dev / pts. Вы не можете использовать хвостовое устройство. Запланируйте команду ping как cronjob, а затем сделайте то же самое. tail -f потом сработает
твлоой
9

В BSD вы можете использовать, watchкоторый отслеживает данный tty, например

watch /dev/pts/0

В Linux это будет невозможно, если процесс не был запущен в мультиплексоре, например, screenили tmux. См. Также: Reptyr: присоединение запущенного процесса к новому терминалу.

Это , кажется , единственный способ для отладки процесса (например strace, dtrace/ dtruss, gdb, lldbи т.д.).

Поскольку вы использовали straceдля извлечения любого значимого вывода, вам нужно отфильтровать по уточняющему выражению (например, file), а затем проанализировать вывод. Вот пример:

strace -e trace=write -s1000 -fp 18386 2>&1 | grep -o '".\+[^"]"'

Для этого он печатает операцию записи процесса (длина 1000), заданного параметром PID (используется pgrepдля поиска по имени), перенаправляет стандартную ошибку в вывод (для фильтрации) и печатает строку в двойных кавычках.

Если вы имеете дело с двоичным выводом, вы можете проанализировать символы escape-последовательностей, используя read-r) и printf%b), например

while read -r -t1 line; do printf "%b" $line; done

Проверьте help readналичие дополнительных параметров (например, -nдля печати после определенного количества символов, а не перевода строки).

Вот более полный пример:

strace -e trace=write -s1000 -fp 18386 2>&1 \
| grep --line-buffered -o '".\+[^"]"' \
| grep --line-buffered -o '[^"]\+[^"]' \
| while read -r line; do
  printf "%b" $line;
done

Для примеров, использующих любой процесс, пожалуйста, проверьте: Как разобрать strace в оболочке в обычный текст? при переполнении стека

kenorb
источник
4
  1. Возможно, вы сможете посмотреть на удаленный экран, используя, ssh localhost 'DISPLAY=:0.0 xwd -root' | xwud -scaleгде localhostследует заменить учетные данные для входа на удаленный сервер и :0.0номер дисплея вашего графического интерфейса.

  2. Используйте x11vnc, который является VNC-сервером для вашего X-сеанса на экране.

  3. При запуске на одной из 6 виртуальных консолей попробуйте sudo setterm -dump 2 -file /dev/stdout, где вы замените 2соответствующий vc.

jippie
источник
4

Я бы посоветовал сделать именованный канал ( mkfifo), а затем записать в этот файл. Тогда читай из него. Вы всегда можете сделать это с помощью таких вещей, как tailминимизация вывода и т. Д. Всякий раз, когда вы очищаете канал (считываете из него), он очищается, поэтому выход не сохраняется.

Другой вариант - записать все в файл (очень похоже на файл журнала), а затем проанализировать его в любое время. Это было бы предпочтительным действием, если вы хотите сохранить весь вывод.

Полемон
источник
3

Вы всегда можете запустить процесс с помощью nohup и &

nohup rsync source_file dest_file &

Затем вы можете проверить прогресс любого tty с помощью:

tail -f nohup.out

Это прекрасно работает для меня.

Пабло Луна
источник
6
Этот вопрос я хотел бы узнать о том, как просмотреть вывод процесса запуска оповещения, а не о том, как запустить процесс в фоновом режиме, как подсказывает ваш ответ,
jwbensley,
На самом деле ваше упоминание: nohup просветите меня! Спасибо!
Nam G VU
1

Очень просто получить вывод - захватить вывод в файл и настроить этот файл.

IF DO: ./ipcheck

INSTEAD DO: ./ipcheck> [replacewithyourfilename]

Это создаст выходной файл, в котором находится ваш скрипт. Затем из любой другой оболочки bash вы можете просто скопировать файл:

tail [replacewithyourfilename] -f

MrAllen
источник
Перенаправление файлов имеет тенденцию использовать блочную буферизацию по умолчанию (см. setbuf(3)), Что может создавать tailпроблемы.
thrig
5
Также это не помогает с вопросом о том, как просмотреть вывод уже запущенного процесса, а не о том, как перенаправить стандартный вывод для нового процесса.
jwbensley
1

Разбор вывода strace:

Я использовал верхний ответ (с моим идентификатором процесса 28223) ...

> sudo strace -p28223 -s9999 -e write
...
write(9, "Info\nI\nCare\nabout", 55) = 55
...

Чтобы определить, что меня волнует write(9. (9 используется ниже, это, вероятно, дескриптор файла и может отличаться для вашего процесса.) Затем я написал быстрый скрипт Ruby для анализа и отображения их.

Вставьте следующее в /usr/bin/parse_strace.rb

#!/usr/bin/ruby

num = ARGV[0]
STDIN.each { |line|
  if (line.match(/write\(#{ num },\s*"(.*?)"/)) then
    puts $1.split('\x').map { |s| s.to_i(16).chr }.join()
  end
}

Не забывай chmod a+x /usr/bin/parse_strace.rb

Я вызываю strace -xx(выводит hex, поэтому регулярное выражение соответствует), добавляя в скрипт (включая STDERR) мой 9первый аргумент.

sudo sh -c 'strace -xx -p28223 -s9999 -e write 2>&1 | parse_strace.rb 9'

И, вуаля, он выводит исходное STDOUT процесса, новые строки, цвет и все!

Присоединение к процессу STDOUT

Джефф Уорд
источник
0

Вы не можете получить идентификатор процесса и связаться с ним по USR1,

$pgrep -l '^ipchecker.sh$'

который печатает PID вашего скрипта, а затем использовать его для

$ kill -USR1 PID

Я понимаю, что USR1 - это «определяемый пользователем» сигнал, означающий, что тот, кто создал программу, может использовать ее для обозначения «выключить», «сбросить ваши логи», «распечатать тысячу раз» или что-то еще.

Saeed
источник