Как мне подключить терминал к отдельному процессу?

99

Я отключил процесс от моего терминала, как это:

$ process &

Этот терминал давно закрыт, но processвсе еще работает, и я хочу отправить некоторые команды в стандартный процесс этого процесса. Это возможно?

Рогач
источник

Ответы:

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…, конечно, не нужно.
Ансгар Эстерманн
Это здорово! Я использую это, чтобы отправить "y" или "n" ответы на определенные процессы, которые были полностью отключены. Отдельный процесс имеет свой стандартный вывод в отдельном окне. Однако, когда я делаю этот трюк, я вижу, что он не "получает" 'y' или 'n', как только я повторяю его, я должен выйти из gdb и отсоединить его, а затем он получает все эхо соответственно, поэтому Есть ли способ сделать это, не выходя из GDB, прежде чем процесс получит входные данные из fifo?
krb686
к сожалению , это только кажется , висит на call open("/tmp/fifo", 0600). любая помощь будет принята с благодарностью
Лучник
27

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

reptyrможет быть, что вы хотите, см. https://serverfault.com/a/284795/187998

Цитата оттуда:

Посмотрите на reptyr , который делает именно это. Страница github содержит всю информацию.

reptyr - инструмент для "перепечатывания" программ.

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

ИСПОЛЬЗОВАНИЕ

PID рептира

«reptyr PID» захватит процесс с идентификатором PID и подключит его к вашему текущему терминалу.

После подключения процесс примет входные данные и запишет выходные данные на новый терминал, включая ^ C и ^ Z. (К сожалению, если вы справитесь с этим, вам все равно придется запускать «bg» или «fg» в старом терминале. Вероятно, это невозможно исправить разумным способом без исправления вашей оболочки.)

NiKiZe
источник
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) недоступен.

В следующий раз вы можете использовать screen или tmux, чтобы избежать этой ситуации.

andcoz
источник
5
Или dtachесли вам не нужно целое screen.
manatwork
4
Там нет никакого способа в стандартах (POSIX, SUS), но и на многих (большинство?) Систем это является возможным с помощью механизмов, отладчики использования. Смотрите ответ Ансгара . С помощью rootвы можете даже сделать это с процессами других пользователей.
dmckee
3
Выполнение echo "test" > /dev/pts/1не отправит входные данные процессу 9947- оно выведет слово «тест» на терминал этого процесса.
psmears
6

РЕДАКТИРОВАТЬ : Как сказал Стефан Гименес, это не так просто. Это позволяет вам печатать только на другом терминале.

Вы можете попытаться написать в этот процесс, используя / proc . Он должен находиться в / proc / pid / fd / 0 , поэтому просто:

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

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

  • если это ссылка на / dev / null => она закрыта
  • если это ссылка на / dev / pts / X или сокет => она открыта

Смотрите nohup для более подробной информации о том, как сохранить процессы запущенными.

Корен
источник
2
Это не так просто. Например, если stdin связан с терминалом, если echoчто-то на терминальное устройство просто напечатает то, что вы написали на терминале, оно не будет передано процессу.
Стефан Гименес
5

Простое завершение командной строки &не полностью отсоединит процесс, а просто запустит его в фоновом режиме. (С помощью zshвы можете использовать, &!чтобы фактически отсоединить его, в противном случае вы должны сделать disownэто позже).

Когда процесс выполняется в фоновом режиме, он больше не будет получать входные данные от своего управляющего терминала. Но вы можете отправить его обратно на передний план, fgи тогда он снова будет читать ввод.

В противном случае, невозможно внешне изменить его файловые дескрипторы (включая stdin) или подключить потерянный управляющий терминал ... если вы не используете инструменты отладки (см . Ответ Ансгара или посмотрите на rettyкоманду).

Стефан Хименес
источник
И здесь есть связанный вопрос: unix.stackexchange.com/q/17648/9426
Стефан
@Rogach заявил: «Этот терминал давно закрыт».
andcoz
1
@andcoz: Да, но ему повезло, что программа не была взломана. Я предлагал более безопасный метод.
Стефан Гименес
здесь, disown действительно работает, только если я сначала перенаправляю стандартный вывод, как с помощью >>/dev/stderr, в противном случае, когда я закрываю терминал, процесс «отречения» тоже закончится .. Я никогда не понимал этого, хотя…
Aquarius Power