Làm cách nào để gắn thiết bị đầu cuối vào quy trình tách rời?


99

Tôi đã tách ra một quy trình từ thiết bị đầu cuối của mình, như thế này:

$ process &

Thiết bị đầu cuối đó hiện đã đóng cửa từ lâu, nhưng processvẫn đang chạy và tôi muốn gửi một số lệnh đến quy trình đó. Điều đó có thể không?



1
Tìm kiếm retty, neercsvv và xem thêm serverfault.com/questions/24425 , serverfault.com/questions/115998
Gilles

Câu trả lời:


112

Vâng, đúng vậy. Đầu tiên, tạo một đường ống : mkfifo /tmp/fifo. Sử dụng gdb để đính kèm vào quy trình: gdb -p PID

Sau đó đóng stdin : call close (0); và mở lại:call open ("/tmp/fifo", 0600)

Cuối cùng, viết đi (từ một thiết bị đầu cuối khác, vì gdb có thể sẽ bị treo):

echo blah > /tmp/fifo


6
Rất ấn tượng!
Phường Samuel Edwin

1
Tôi có thể làm điều gì đó tương tự như chuyển hướng quá trình xuất chuẩn sang tệp không?
rustyx

@rustyx: Chưa được kiểm tra, nhưng điều này sẽ hoạt động: tạo một tệp chứ không phải là một đường ống , touch /tmp/thefile. Stdout là 1, vì vậy call close (1); Ngoài ra, sử dụng các quyền chính xác để viết : call open ("/tmp/thefile", 0400). Tất nhiên echo…là không cần thiết.
Ansgar Esztermann

Điều đó thật tuyệt! Tôi đang sử dụng điều này để gửi phản hồi "y" hoặc "n" cho các quy trình nhất định đã được tách ra hoàn toàn. Quá trình tách rời có thiết bị xuất chuẩn đến một cửa sổ riêng. Tuy nhiên, khi tôi thực hiện thủ thuật này, tôi có thể thấy rằng nó không "nhận" được 'y' hoặc 'n' ngay khi tôi lặp lại nó, tôi phải thoát gdb và tách nó ra và sau đó nó nhận được tất cả các tiếng vang Có cách nào để thực hiện việc này mà không cần phải thoát gdb trước khi quá trình nhận đầu vào từ fifo không?
krb686

Thật không may, nó chỉ có vẻ treo trên call open("/tmp/fifo", 0600). bất kỳ trợ giúp sẽ được đánh giá rất cao
cung thủ

27

Khi thiết bị đầu cuối ban đầu không còn truy cập được ...

reptyrcó thể là những gì bạn muốn, xem https://serverfault.com/a/284795/187998

Trích dẫn từ đó:

Có một cái nhìn tại reptyr , mà chính xác đó. Trang github có tất cả các thông tin.

reptyr - Một công cụ cho các chương trình "ptying".

reptyr là một tiện ích để lấy một chương trình đang chạy và gắn nó vào một thiết bị đầu cuối mới. Bắt đầu một quá trình dài qua ssh, nhưng phải rời đi và không muốn làm gián đoạn nó? Chỉ cần khởi động một màn hình, sử dụng reptyr để lấy nó, sau đó giết phiên ssh và về nhà.

SỬ DỤNG

reptyr PID

"Reptyr PID" sẽ lấy quy trình với id PID và gắn nó vào thiết bị đầu cuối hiện tại của bạn.

Sau khi đính kèm, quá trình sẽ lấy đầu vào từ và ghi đầu ra vào thiết bị đầu cuối mới, bao gồm ^ C và ^ Z. (Thật không may, nếu bạn chạy nền, bạn vẫn sẽ phải chạy "bg" hoặc "fg" trong thiết bị đầu cuối cũ. Điều này có thể không thể khắc phục một cách hợp lý mà không cần vá vỏ của bạn.)


12

Tôi khá chắc chắn rằng bạn không thể.

Kiểm tra bằng cách sử dụng ps x. Nếu một quá trình có ?như tty kiểm soát , bạn không thể gửi đầu vào cho nó nữa.

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

Trong ví dụ này, bạn có thể gửi đầu vào để 9947làm một cái gì đó như echo "test" > /dev/pts/1. Quá trình khác ( 9942) không thể truy cập.

Lần tới, bạn có thể sử dụng màn hình hoặc tmux để tránh tình trạng này.


5
Hoặc dtachnếu bạn không cần một tổng thể screen.
manatwork

4
Không có cách nào trong các tiêu chuẩn (POSIX, SUS), nhưng trên nhiều hệ thống (nhất?) Nó có thể sử dụng các cơ chế mà Debuggers sử dụng. Xem câu trả lời của Ansgar . Với rootbạn thậm chí có thể làm điều này với các quy trình của người dùng khác.
dmckee

3
Làm echo "test" > /dev/pts/1sẽ không gửi đầu vào cho quá trình 9947- nó sẽ ra chữ "thử nghiệm" trên thiết bị đầu cuối của quá trình đó.
psmears

6

EDIT : Như Stephane Gimenez đã nói, nó không đơn giản. Nó chỉ cho phép bạn in ra một thiết bị đầu cuối khác.

Bạn có thể thử viết vào quá trình này bằng cách sử dụng / Proc . Nó nên được đặt trong / Proc / pid / fd / 0 , vì vậy đơn giản:

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

Hãy làm nó. Tôi đã không thử nó, nhưng nó sẽ hoạt động, miễn là quá trình này vẫn có một mô tả tập tin stdin hợp lệ . Bạn có thể kiểm tra nó với ls -lon / Proc / pid / fd / .

  • nếu đó là một liên kết đến / dev / null => nó đã bị đóng
  • nếu đó là liên kết đến / dev / pts / X hoặc ổ cắm => nó sẽ mở

Xem nohup để biết thêm chi tiết về cách giữ cho các quy trình chạy.


2
Nó không đơn giản. Ví dụ: Nếu stdin được liên kết với thiết bị đầu cuối, echoing một cái gì đó đến thiết bị đầu cuối sẽ chỉ in những gì bạn đã viết trên thiết bị đầu cuối, nó sẽ không được truyền đến quy trình.
Stéphane Gimenez

5

Chỉ cần kết thúc dòng lệnh với &sẽ không hoàn toàn tách rời quá trình, nó sẽ chỉ chạy nó trong nền. (Với zshbạn có thể sử dụng &!để thực sự tách nó ra, nếu không bạn phải làm disownđiều đó sau).

Khi một quá trình chạy trong nền, nó sẽ không nhận được đầu vào từ thiết bị đầu cuối kiểm soát của nó nữa. Nhưng bạn có thể gửi nó trở lại nền trước fgvà sau đó nó sẽ đọc lại đầu vào.

Mặt khác, không thể thay đổi bên ngoài các bộ lọc của nó (bao gồm cả stdin) hoặc gắn lại thiết bị đầu cuối kiểm soát bị mất trừ khi bạn sử dụng các công cụ gỡ lỗi (xem câu trả lời của Ansgar hoặc xem rettylệnh).


Và có một câu hỏi liên quan ở đây: unix.stackexchange.com/q/17648/9426
Stéphane Gimenez

@Rogach tuyên bố "Thiết bị đầu cuối đó đã đóng cửa từ lâu".
andcoz

1
@andcoz: Có nhưng anh ấy đã rất may mắn khi chương trình chưa được SIGHUPed. Tôi đã đề xuất một phương pháp an toàn hơn.
Stéphane Gimenez

Ở đây, disown chỉ thực sự hoạt động nếu lần đầu tiên tôi chuyển hướng stdout như với >>/dev/stderr, nếu không, khi tôi đóng thiết bị đầu cuối, quá trình "bị từ chối" cũng sẽ kết thúc .. Tôi chưa bao giờ thực sự hiểu điều này ..
Aquarius Power
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.