Làm cách nào tôi có thể từ chối một quy trình đang chạy và liên kết nó với một vỏ màn hình mới?


159

Tôi có một chương trình đang chạy trên vỏ SSH. Tôi muốn tạm dừng nó và có thể bỏ tạm dừng việc thực hiện nó khi tôi quay lại.

Một cách tôi nghĩ để làm điều đó là chuyển quyền sở hữu của nó sang một vỏ màn hình, do đó giữ cho nó chạy trong đó.

Có một cách khác để tiến hành?


8
Xem thêm Tôi có thể nohup / sàng lọc một quy trình đã bắt đầu không? Resume lệnh đang chạy trong phiên SSH bị bỏ , trong đó đề cập đến một số giải pháp dựa trên ptrace không (hiện tại) được đề cập ở đây.
Gilles

Từ những câu hỏi như unix.stackexchange.com/a/4039/13496 Tôi đang nghe về rettyneercs . Hmmm ... tự hỏi nếu có một lớp như " màn hình ở đây" trước khi tôi chạy một quy trình vào lần tới thì tôi có nên mất thiết bị đầu cuối trong tương lai không, điều đó sẽ giúp bạn dễ dàng lấy lại stdin / out / err
Marcos

Vấn đề thứ yếu / tiềm ẩn trong câu hỏi này tôi không thể hiểu là ... tại sao shell lại chọn từ chối một công việc bị đình chỉ khi có một công việc mới hơn / chỉ được đưa ra trong nền mà thậm chí không cần / đợi stdin? Đây là cách đối xử mà tôi đã quen với việc không biết điều gì khác biệt ở đây ...
Marcos

Câu trả lời:


86

Sử dụng GNU screenlà đặt cược tốt nhất của bạn.

Màn hình bắt đầu chạy khi bạn đăng nhập lần đầu - Tôi chạy screen -D -R, chạy lệnh của bạn và ngắt kết nối hoặc tạm dừng nó CTRL-Zvà sau đó ngắt kết nối khỏi màn hình bằng cách nhấn CTRL-Asau đó D.

Khi bạn đăng nhập lại vào máy, kết nối lại bằng cách chạy screen -D -R. Bạn sẽ ở trong cùng một vỏ như trước đây. Bạn có thể chạy jobsđể xem quy trình bị đình chỉ nếu bạn đã làm như vậy và chạy %1(hoặc công việc tương ứng #) để tiến hành lại nó.


2
Ồ, tôi không thể tin rằng câu trả lời của GNU Screen hiện được xếp hạng thấp nhất. Tui bỏ lỡ điều gì vậy?
Faheem Mitha

1
Có lẽ! Có vẻ như tốt nhất với tôi.
Andrew Yochum

1
Nhìn lại, rõ ràng đây là giải pháp không gây đau đớn nhất, miễn là bạn có thể lập kế hoạch phù hợp và khởi chạy các quy trình của mình từ trong môi trường màn hình. Dù sao, tôi đã làm cho nó câu trả lời chính thức!
levesque

28
Tôi nghĩ rằng điều này không trả lời câu hỏi. Câu hỏi bắt đầu với " Tôi có một chương trình đang chạy ". Câu trả lời này cho rằng nó chưa chạy được
Anko

vâng, anh ấy đã viết rõ ràng rằng anh ấy muốn đưa nó vào một phiên chiếu :-)
Florian Heigl

112

Bạn có thể thu hồi quyền sở hữu của thành phố, chương trình đào tạo từ vỏ với tích disownhợp:

# press Ctrl+Z to suspend the program
bg
disown

Tuy nhiên, điều này chỉ báo cho shell không gửi SIGHUPtín hiệu đến chương trình khi shell thoát ra. Chương trình sẽ giữ lại bất kỳ kết nối nào với thiết bị đầu cuối, thường là các luồng đầu vào, đầu ra và lỗi tiêu chuẩn. Không có cách nào để gắn lại những thứ đó đến một thiết bị đầu cuối khác. ( Màn hình hoạt động bằng cách mô phỏng một thiết bị đầu cuối cho mỗi cửa sổ, vì vậy các chương trình được gắn vào cửa sổ màn hình.)


Có thể gắn lại các trình biên dịch vào một tệp khác bằng cách đính kèm chương trình trong trình gỡ lỗi (nghĩa là sử dụng ptrace) và thực hiện cuộc gọi open, dupclose. Có một vài công cụ làm điều này; đây là một quá trình khó khăn và đôi khi họ sẽ phá vỡ quy trình thay thế. Các khả năng bao gồm (các liên kết được thu thập từ các câu trả lời cho Làm cách nào tôi có thể từ chối một quy trình đang chạy và liên kết nó với một vỏ màn hình mới?tôi có thể mở khóa / sàng lọc một quy trình đã bắt đầu không? ):


disownloại bỏ quá trình từ danh sách kiểm soát công việc.
ctrl-alt-delor

3
Tại sao không disown -h?
Cees Timmerman

@CeesTimmerman Điều đó để lại công việc trong bảng công việc của shell, nhưng lợi thế của điều đó là gì?
Gilles

@Gilles: vì vậy bạn vẫn có thể fghoặc killnó, và xem nếu nó tự kết thúc.
Peter Cordes

Những tiện ích được đề cập làm việc với một nhóm các quy trình (ví dụ bzcat a.bz2 | grep text)? Man cho reptyrrằng nó không hỗ trợ di chuyển các quá trình với trẻ em.
dma_k

64

Để di chuyển một quá trình giữa các thiết bị đầu cuối hoặc gắn lại một từ chối, bạn có thể sử dụng ví dụ reptyr .


1
Vâng, đã lưu nó, cảm ơn! Tôi đọc trang web của tác giả về cách nó hoạt động tốt hơn các công cụ tương tự hoặc cũ hơn, vd. cho các chương trình ncurses.
Marcos

4
Điều này thật tuyệt; nó sẽ giải quyết tình trạng khó khăn của một người bạn là liên tục mất công việc của cô ấy bằng cách chạy thẳng vào ssh và sau đó cần phải lên tàu. "Rất tiếc, quên sử dụng màn hình. Một lần nữa."
Adam Katz

3
+1 Mặc dù screencâu trả lời được chấp nhận tất nhiên là lý tưởng, nhưng nó không thực sự trả lời câu hỏi, mà cụ thể yêu cầu một cách để chuyển một quy trình hiện đang chạy sang screenhoặc tương tự. Cũng xem câu trả lời này: serverfault.com/a/284795
toxefa

1
Tiết kiệm sống tuyệt đối. Cho phép tôi đính kèm lại để chạy apt dist-Nâng cấp đang chờ xác nhận của người dùng.
andig

28

Giải pháp yêu thích của tôi là sử dụng tmux, bạn có thể tách phiên và gắn lại vào thiết bị đầu cuối khác.

Khi bạn tách ra từ phiên trước, bạn có thể đóng thiết bị đầu cuối một cách an toàn; sau đó sử dụng tmux attachđể quay lại phiên, ngay cả khi bạn đã đăng xuất.


1
bạn cũng có thể chia sẻ phiên của mình với bạn của bạn và sử dụng nhiều cửa sổ và bảng và nhiều hơn nữa! thích nó ^ _ ^
igor

ví dụ về việc sử dụng xin vui lòng?
Vitaly Zdanevich

21

Ngoài ra còn có một tiện ích nhỏ gọi là retty cho phép bạn gắn lại các chương trình đang chạy đến một thiết bị đầu cuối khác.


19

Tôi không sử dụng nó thường xuyên, nhưng neercs tuyên bố sẽ hỗ trợ điều này. Đây là một screenchương trình giống như với các tính năng ưa thích linh tinh như quản lý khung tốt hơn, nhưng điều chính nó cung cấp là khả năng nhập một quy trình vào một khung


2
Hấp dẫn. Nó chơi bẩn ( ptrace), nhưng nó không chỉ thao túng các mô tả tập tin, nó tạo ra quá trình. Nó có thể lấy find /, nhưng bị hỏng một bash tương tác.
Gilles

@Gilles Tôi không thể nhớ nó đã diễn ra như thế nào khi tôi thử, nhưng nó không có tiếng tăm gì cả, tôi được bảo là nó thất bại khá thường xuyên
Michael Mrozek

9

Nếu bạn chỉ muốn tạm dừng nó và khởi động lại sau đó, bạn có thể sử dụng killvới STOPhoặc CONTtín hiệu.

Đầu tiên hãy tìm hiểu các quy trình PID với

$ ps aux

Sau đó gửi các tín hiệu đến PID đó được liệt kê cho quá trình

$ kill -STOP <PID>

$ kill -CONT <PID>

9

"Tiêm mã" từ ThomasHabets dường như chính xác là thứ tôi cần:

https://github.com/ThomasHabets/injcode

Chương trình mã hóa cho phép nhập mã tùy ý vào quy trình đang chạy, cho dù bạn có biết trước hay không và đang chạy màn hình hoặc tmux

Từ README:

Ví dụ 1: di chuyển irssi từ thiết bị đầu cuối này sang thiết bị đầu cuối khác

Có lẽ di chuyển nó vào một màn hình.

Đầu tiên bắt đầu irssi trong một thiết bị đầu cuối.

Chạy phần mềm trong một thiết bị đầu cuối khác: $ tiêm mã -m retty

Bây giờ Irssi nên được chuyển đến thiết bị đầu cuối thứ hai, bao gồm cả thiết bị đầu cuối kiểm soát mới.


1

Điều này làm việc cho tôi:

  1. bg quá trình
  2. jobs -l tìm số quy trình
  3. tmux bắt đầu quản lý cửa sổ shell
  4. reptyr -L PROCESSNUMBER

reptyrĐiều -Lcần thiết là làm cho nó hoạt động:

-L Like '-l', but also redirect the child's stdio to the slave.

vì lỗi này:

$ reptyr 30622

[-] Unable to open the tty in the child.
Unable to attach to pid 30622: Permission denied

Và với -L

$ reptyr -L 30622
Opened a new pty: /dev/pts/4
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.