Tại sao một số lệnh 'treo' thiết bị đầu cuối cho đến khi chúng hoàn thành?


22

Đôi khi bạn chạy một chương trình từ thiết bị đầu cuối, nói rằng, lxpanel . Thiết bị đầu cuối sẽ không đưa bạn trở lại dấu nhắc, nó sẽ bị treo. Bạn có thể nhấn Ctrl+ Cđể quay lại dấu nhắc, nhưng điều đó sẽ giết lxpanel. Tuy nhiên, nhấn Alt+ F2(bật lên một cửa sổ để nhận lệnh) và chạy lxpanelhoạt động một cách duyên dáng.

Tại sao lại thế này? Có gì khác nhau giữa việc chạy lệnh từ thiết bị đầu cuối và từ cửa sổ 'chạy' xuất hiện khi bạn nhấn Alt+ F2?

lxpanel ở đây chỉ được sử dụng làm ví dụ. Tôi đã trải nghiệm điều này với nhiều chương trình


1
Mẹo: GNU Screen ( screen) có thể, trong số những thứ khác, được sử dụng để "bọc" các quy trình chạy dài hơn. Bạn có thể tách ra khỏi nó, quay trở lại shell, sau đó gắn lại và xem đầu ra từ quá trình đang chạy. Reattachment thậm chí có thể được thực hiện từ một thiết bị đầu cuối khác, SSH, vv Cũng có thể có các chương trình khác cho phép bạn thực hiện loại điều này.
poplitea

Câu trả lời:


28

Theo mặc định, thiết bị đầu cuối sẽ chạy chương trình ở phía trước, vì vậy bạn sẽ không trở lại trình bao cho đến khi chương trình kết thúc. Điều này hữu ích cho các chương trình đọc từ stdin và / hoặc ghi vào thiết bị xuất chuẩn - bạn thường không muốn nhiều chương trình chạy cùng một lúc. Nếu bạn muốn một chương trình chạy trong nền, bạn có thể bắt đầu nó như thế này:

$ lxpanel &

Hoặc nếu nó đã chạy, bạn có thể tạm dừng nó bằng Ctrl+ Zvà sau đó chạy bgđể di chuyển nó vào nền. Dù bằng cách nào, bạn sẽ kết thúc với một dấu nhắc shell mới, nhưng chương trình vẫn đang chạy và đầu ra của nó sẽ xuất hiện trong thiết bị đầu cuối (vì vậy nó có thể đột ngột xuất hiện trong khi bạn đang gõ phím)

Một số chương trình (thường là daemon) sẽ rẽ nhánh một quy trình riêng khi chúng bắt đầu, và sau đó để quy trình chính thoát ngay lập tức. Điều này cho phép chương trình tiếp tục chạy mà không chặn vỏ của bạn


Vậy hệ thống thực sự đang làm gì khi bạn chạy chương trình qua cửa sổ 'run' bằng cách nhấn Alt + f2? (ít nhất là trên gnome và openbox, alt + f2 thực hiện điều đó). Tôi hỏi bởi vì ngay khi bạn gõ lệnh, chương trình bắt đầu và hộp sẽ biến mất. nó chỉ là thêm một & cho nó?
sqram

2
@lyrae: theo mặc định, shell chờ chương trình hoàn tất trước khi tiếp tục phiên shell, nó không "treo", theo bất kỳ định nghĩa nào về "hang"; alt + f2 không chờ chương trình. Lý do shell chờ chương trình hoàn thành là vì shell có thể chuyển hướng bất cứ thứ gì người dùng nhập vào shell sang đầu vào tiêu chuẩn của chương trình và / hoặc đầu ra tiêu chuẩn của chương trình. Vì alt + f2 chủ yếu được sử dụng để bắt đầu chương trình GUI, nên alt + f2 không cung cấp khả năng sử dụng đầu vào / đầu ra tiêu chuẩn và do đó không cần phải chờ đợi.
Lie Ryan

1
@lyrae: alt + f2 không làm gì đặc biệt để bắt đầu chương trình ở chế độ nền; đó là cái vỏ đang làm điều gì đó đặc biệt, thêm '&' là chức năng của cái vỏ. Khi bắt đầu một lệnh không có '&', shell sẽ chuyển hướng đầu vào tiêu chuẩn của chương trình thành đầu vào tiêu chuẩn của chính nó và đầu ra tiêu chuẩn của chương trình thành đầu ra tiêu chuẩn của riêng nó (một chút được đặt ra, vì shell cũng cung cấp nhiều dịch vụ khác, như chặn Ctrl -C, để gửi lệnh tín hiệu SIGINT đến chương trình nền trước). '&' Nói với shell không được thực hiện những điều đó và chỉ bắt đầu chương trình (cũng bị chiếm dụng).
Lie Ryan

1
@LieRyan một số điều bạn nói shell thực tế được xử lý bởi trình điều khiển đầu cuối của kernel và "với &" thường "đặc biệt" hơn "không có", ngoài việc gọi shell chờ () [hoặc Waitpid hoặc tương đương] không được thực hiện bởi alt-f2.
Random832

6

Khi bạn khởi động chương trình trong một thiết bị đầu cuối, thiết bị đầu cuối sẽ "treo" cho đến khi chương trình của bạn dừng lại. Bằng cách nhấn Ctrl+ cbạn đang đóng chương trình của mình và do đó quay lại dấu nhắc. Bạn sẽ thấy điều này với tất cả các ứng dụng GUI, ví dụ thử dùng Firefox.

Khi bạn sử dụng một số phương pháp khác như Alt + F2 hoặc nhấp qua các menu, chương trình của bạn được khởi động ở chế độ nền để không có gì lạ xảy ra (và dù sao cũng không có dấu nhắc lệnh).

Nếu bạn vẫn muốn khởi chạy ứng dụng GUI từ thiết bị đầu cuối, hãy nối &vào cuối lệnh của bạn, như vậy

lxpanel &

Điều này báo cho thiết bị đầu cuối chạy lxpaneltrong nền và cung cấp cho bạn một dấu nhắc khác ngay lập tức.


3

Các chương trình chạy thông qua một shell chạy ở nền trước của shell đó theo mặc định. Điều này làm cho shell tạm dừng hoạt động và stdin / stdout / sterr trực tiếp từ thiết bị đầu cuối đến chương trình. Các chương trình chạy qua môi trường máy tính để bàn được chia rẽ , điều này khiến chúng chạy độc lập với chương trình chạy chúng. Điều này có thể được mô phỏng trong hầu hết các shell bằng cách gắn thêm một &lệnh, mặc dù điều này vẫn sẽ kết nối std * với thiết bị đầu cuối (mặc dù việc đọc từ stdin trên chương trình nền có thêm các biến chứng).


2

& Nền tảng tốt ngoại trừ các chương trình quay trở lại yêu cầu tương tác giao diện điều khiển sau này (ví dụ: "cập nhật apt -y &" cuối cùng sẽ chuyển sang trạng thái STOP vì nó muốn nhắc người dùng một câu hỏi "thực sự thực sự bắt buộc?" .... khi không còn ai xem nữa).

Để cắm lỗ hổng đó và thông báo cho quá trình một thiết bị đầu cuối sẽ thực sự không bao giờ có sẵn cho nó, tôi nối thêm <& - vào một số lệnh của tôi, tách chúng ra khỏi thiết bị đầu cuối đang hoạt động nói với chúng rằng STDIN không còn có thể. Hãy chắc chắn / bin / bash là vỏ của bạn nếu bạn sử dụng mặc dù. Kịch bản sẽ tiến hành ghi nhật ký bất kỳ lỗi nào liên quan đến việc không có giả hành có sẵn để đưa ra bất kỳ dấu nhắc nào.

Ví dụ:

`./runme.sh &> runme.log <&- & disown`

là cách cuối cùng của tôi để tách rời khỏi phiên cuối cùng hiện tại. Cả STDOUT và STDERR đều được đăng nhập vào runme.log, sẽ không có vấn đề gì nếu bảng điều khiển hoặc trình bao của bạn chấm dứt sớm hơn hoặc nếu bạn đăng xuất / su vào một tài khoản khác (không có rác thiết bị đầu cuối từ runme) và nhờ vào ngay cả cha mẹ và con Mối quan hệ PID được loại bỏ.

CẬP NHẬT: ngay cả khi tôi gặp rắc rối với một semaphore liên kết nó với tên của cha mẹ ban đầu, vì vậy bây giờ tôi khuyên bạn nên thay thế:

at now <<< "(cmd1; cmd2; etc.) &> logfile.log"

Tất nhiên, xóa &> nếu bạn muốn nhận email đầu ra từ CRON hoặc chuyển hướng tất cả sang / dev / null thay vì một tệp.


Một cách ít phức tạp hơn để đạt được mà tôi bắt đầu sử dụng làat now <<< "(cmd1; cmd2; etc.) &> logfile.log"
Marcos
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.