Jak podłączyć terminal do odłączonego procesu?


99

Odłączyłem proces z mojego terminala, taki jak ten:

$ process &

Ten terminal jest już od dawna zamknięty, ale processnadal działa i chcę wysłać polecenia do standardowego wejścia tego procesu. Czy to jest możliwe?



1
Szukać retty, neercsitp, a także zobaczyć serverfault.com/questions/24425 , serverfault.com/questions/115998
Gilles

Odpowiedzi:


112

Tak to jest. Po pierwsze, stworzenie rury: mkfifo /tmp/fifo. Użyj gdb, aby dołączyć do procesu: gdb -p PID

Następnie zamknij stdin: call close (0); i otwórz go ponownie:call open ("/tmp/fifo", 0600)

Na koniec zapisz (z innego terminala, ponieważ gdb prawdopodobnie się zawiesi):

echo blah > /tmp/fifo


6
Bardzo imponujące!
Samuel Edwin Ward

1
Czy mogę zrobić coś podobnego do przekierowania standardowego procesu do pliku?
rustyx

@rustyx: Nietestowane, ale to powinno działać: utworzyć plik zamiast fajki, touch /tmp/thefile. Stdout to 1, więc call close (1); również użyć odpowiednich uprawnień do zapisu: call open ("/tmp/thefile", 0400). To echo…oczywiście nie jest potrzebne.
Ansgar Esztermann

To jest świetne! Używam tego do wysyłania odpowiedzi „y” lub „n” na niektóre procesy, które zostały całkowicie odłączone. Odłączony proces ma swoje standardowe wyjście w osobnym oknie. Kiedy jednak wykonuję tę sztuczkę, widzę, że nie „odbiera” „y” ani „n”, gdy tylko ją echo, muszę wyjść z gdb i odłączyć go, a następnie odpowiednio odbiera wszystkie echa, więc czy istnieje sposób na wykonanie tego bez konieczności wychodzenia z gdb, zanim proces odbierze dane wejściowe z fifo?
krb686

niestety po prostu wydaje się zawieszony call open("/tmp/fifo", 0600). każda pomoc byłaby bardzo mile
widziana

27

Gdy oryginalny terminal nie jest już dostępny ...

reptyrmoże być tym, czego chcesz, patrz https://serverfault.com/a/284795/187998

Cytat stamtąd:

Spójrz na reptyr , który właśnie to robi. Strona github zawiera wszystkie informacje.

reptyr - Narzędzie do „ponownego pisania” programów.

reptyr to narzędzie do pobierania istniejącego programu i dołączania go do nowego terminala. Rozpoczął długotrwały proces nad ssh, ale musisz odejść i nie chcesz go przerywać? Po prostu uruchom ekran, użyj reptyr, aby go złapać, a następnie zabij sesję ssh i idź do domu.

STOSOWANIE

reptyr PID

„reptyr PID” pobierze proces o identyfikatorze PID i załączy go do bieżącego terminala.

Po dołączeniu proces pobierze dane wejściowe i zapisze dane wyjściowe w nowym terminalu, w tym ^ C i ^ Z. (Niestety, jeśli będziesz to robił w tle, nadal będziesz musiał uruchomić „bg” lub „fg” w starym terminalu. Prawdopodobnie nie jest to możliwe do naprawienia w rozsądny sposób bez łatania powłoki).


12

Jestem pewien, że nie możesz.

Sprawdź za pomocą ps x. Jeśli proces ma ?jak kontrolujący tty , nie można wysyłać dane wejściowe do niego więcej.

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

W tym przykładzie możesz wysłać dane wejściowe do 9947zrobienia czegoś takiego echo "test" > /dev/pts/1. Drugi proces ( 9942) jest nieosiągalny.

Następnym razem możesz użyć screen lub tmux, aby uniknąć tej sytuacji.


5
Lub dtachjeśli nie potrzebujesz całości screen.
manatwork

4
W standardach (POSIX, SUS) nie ma mowy, ale w wielu (większości?) Systemach jest to możliwe przy użyciu mechanizmów używanych przez debuggery. Zobacz odpowiedź Ansgara . Dzięki niemu rootmożesz nawet zrobić to z procesami innych użytkowników.
dmckee,

3
Wykonanie echo "test" > /dev/pts/1nie wyśle ​​danych wejściowych do procesu 9947- wyświetli słowo „test” na terminalu tego procesu.
psmears,

6

EDYCJA : Jak powiedział Stephane Gimenez, nie jest to takie proste. Pozwala tylko na drukowanie na innym terminalu.

Możesz spróbować napisać do tego procesu za pomocą / proc . Powinien znajdować się w / proc / pid / fd / 0 , więc prosty:

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

powinien to zrobić. Nie próbowałem tego, ale powinno działać, o ile proces ten nadal ma prawidłowy deskryptor pliku stdin . Możesz to sprawdzić za pomocą ls -lon / proc / pid / fd / .

  • jeśli jest to link do / dev / null => jest zamknięty
  • jeśli jest to link do / dev / pts / X lub socket => jest otwarty

Zobacz nohup, aby uzyskać więcej informacji na temat utrzymania procesów w działaniu.


2
To nie takie proste. Na przykład, jeśli stdin jest połączone z terminalem, po echowłożeniu czegoś do urządzenia końcowego po prostu wydrukuje to, co napisałeś na terminalu, nie zostanie ono przesłane do procesu.
Stéphane Gimenez

5

Samo zakończenie wiersza poleceń &nie całkowicie odłączy proces, po prostu uruchomi go w tle. (Za pomocą zshmożesz &!go faktycznie odłączyć, w przeciwnym razie musisz to zrobić disownpóźniej).

Gdy proces działa w tle, nie będzie już odbierał danych wejściowych z terminala sterującego. Ale możesz wysłać go z powrotem na pierwszy plan, fga następnie ponownie odczytać dane wejściowe.

W przeciwnym razie nie jest możliwa zewnętrzna zmiana jego deskryptorów plików (w tym stdin) lub ponowne podłączenie zagubionego kontrolera… chyba że użyjesz narzędzi do debugowania (zobacz odpowiedź Ansgara lub spójrz na rettykomendę).



@Rogach stwierdził „Ten terminal jest już długo zamknięty”.
andcoz

1
@andcoz: Tak, ale miał szczęście, że program nie został PODSUMOWANY. Sugerowałem bezpieczniejszą metodę.
Stéphane Gimenez

tutaj, disown działa naprawdę tylko wtedy, gdy najpierw przekierowuję standardowe wyjście, jak w >>/dev/stderrprzeciwnym razie, kiedy zamknę terminal, proces „odrzucenia” też się skończy. Nigdy tak naprawdę tego nie zrozumiałem…
Aquarius Power
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.