Як я можу приєднати термінал до відокремленого процесу?


99

Я відірвав процес від мого терміналу, наприклад:

$ process &

Цей термінал зараз давно закритий, але processвін все ще працює, і я хочу надіслати кілька команд в stdin цього процесу. Це можливо?



1
Пошук retty, neercsі т.д. , а також побачити serverfault.com/questions/24425 , serverfault.com/questions/115998
Жиль

Відповіді:


112

Так. По- перше, створити канал: mkfifo /tmp/fifo. Використовуйте gdb для приєднання до процесу: gdb -p PID

Потім закрийте STDIN: call close (0); і відкрийте його знову:call open ("/tmp/fifo", 0600)

Нарешті, запишіть (з іншого терміналу, оскільки gdb, ймовірно, буде висіти):

echo blah > /tmp/fifo


6
Дуже вражає!
Семюель Едвін Уорд

1
Чи можу я зробити щось подібне, щоб перенаправити stdout процесу до файлу?
rustyx

@rustyx: неперевірена, але це повинно працювати: створити файл , а не трубу, touch /tmp/thefile. Stdout - 1, так call close (1); Крім того , використовувати правильні дозволу для запису: call open ("/tmp/thefile", 0400). Це echo…, звичайно, не потрібно.
Ansgar Esztermann

Це чудово! Я використовую це, щоб надсилати відповіді "у" або "п" на певні процеси, які були повністю відірвані. Відірваний процес має свій відтінок до окремого вікна. Коли я виконую цей трюк, я можу побачити, що він не "отримує" "у" або "п", як тільки я повторюю його, я мушу вийти з gdb і відключити його, і тоді він отримає всі відлуння відповідно, так чи є спосіб це зробити, не виходячи з gdb до того, як процес отримає вхід з файлу?
krb686

на жаль, це, здається, зависло call open("/tmp/fifo", 0600). будь-яка допомога буде дуже вдячна
лучник

27

Коли оригінальний термінал більше не доступний ...

reptyrможе бути те, що ви хочете, див. https://serverfault.com/a/284795/187998

Цитата звідти:

Погляньте на рептирій , який робить саме це. На сторінці github є вся інформація.

reptyr - Інструмент для "перенастроювання" програм.

reptyr - це утиліта для прийняття наявної запущеної програми та приєднання її до нового терміналу. Почався тривалий процес над ssh, але доведеться вийти з нього і не хочете його переривати? Просто запустіть екран, використовуйте рептирій, щоб схопити його, а потім вбити ssh сеанс і повернутися додому.

ВИКОРИСТАННЯ

рептирій PID

"reptyr PID" захопить процес із ідентифікатором PID та додасть його до поточного терміналу.

Після приєднання процес буде приймати вхід з та записувати вихід у новий термінал, включаючи ^ C та ^ Z. (На жаль, якщо ви працюєте з фоном, вам все одно доведеться запускати "bg" або "fg" у старому терміналі. Це, ймовірно, неможливо виправити розумним чином, не виправляючи оболонку.)


12

Я цілком впевнений, що ви не можете.

Перевірте використання ps x. Якщо процес має в ?якості керуючого терміналу , ви не можете відправити свій внесок в нього більше.

9942 ?        S      0:00 tail -F /var/log/messages
9947 pts/1    S      0:00 tail -F /var/log/messages

У цьому прикладі ви можете надіслати дані для 9947виконання чогось подібного echo "test" > /dev/pts/1. Інший процес ( 9942) недоступний.

Наступного разу ви можете використовувати екран або tmux, щоб уникнути цієї ситуації.


5
Або dtachякщо вам не потрібно ціле screen.
манастирська робота

4
Там немає ніякого способу в стандартах (POSIX, SUS), але і на багатьох (більшість?) Систем це є можливим з допомогою механізмів, отладчики використання. Дивіться відповідь Ансгара . З цим rootви могли навіть зробити це для інших користувачів.
dmckee

3
Здійснення echo "test" > /dev/pts/1не надсилатиме введення в процес 9947- воно виводить слово "тест" на термінал цього процесу.
psmears

6

EDIT : Як сказав Стефан Гіменес, це не так просто. Це дозволяє лише друкувати на іншому терміналі.

Ви можете спробувати записатись у цей процес за допомогою / proc . Він повинен розташовуватися в / proc / pid / fd / 0 , так що простий:

echo "hello" > /proc/PID/fd/0

повинен це зробити. Я не пробував цього, але він повинен працювати, доки цей процес все ще має дійсний дескриптор файлів stdin . Ви можете перевірити його ls -lна / Proc / PID / FD / .

  • якщо це посилання на / dev / null =>, воно закрите
  • якщо це посилання на / dev / pts / X або socket => воно відкрите

Докладніше про те, як тримати процеси, перегляньте nohup .


2
Це не так просто. Наприклад, якщо stdin зв'язаний з терміналом, echoто щось на термінальному пристрої буде просто надрукувати те, що ви написали на терміналі, воно не буде передано в процес.
Стефан Гіменез

5

Щойно закінчення командного рядка &не повністю від'єднає процес, він просто запустить його у фоновому режимі. ( zshВи можете використовувати його &!для фактичного від'єднання, інакше ви це зробите disownпізніше).

Коли процес працює у фоновому режимі, він більше не отримуватиме вхід від свого керуючого терміналу. Але ви можете відправити його на перший план за допомогою, fgі тоді він знову прочитає дані.

В іншому випадку неможливо зовнішньо змінити свої fileescriptors (включаючи stdin) або повторно встановити втрачений керуючий термінал ... якщо тільки ви не використовуєте інструменти для налагодження (див . Відповідь Ansgar або ознайомтеся з rettyкомандою).


І тут пов'язане питання: unix.stackexchange.com/q/17648/9426
Stéphane Gimenez

@Rogach заявив: "Цей термінал давно закритий".
andcoz

1
@andcoz: Так, але йому пощастило, що програма не була ПОСОБА. Я пропонував більш безпечний метод.
Стефан Гіменез

тут, відректися тільки дійсно працює , якщо я перший перенаправити стандартний висновок , як з >>/dev/stderr, в іншому випадку, коли я закрити термінал, то «відрікся» процес закінчиться дуже .. Я ніколи не розумів цього Тхо ..
Водолій Потужність
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.