Tại sao chạy lệnh Linux shell với &?


28

Tôi đang sử dụng Red Hat Linux Enterprise phiên bản 5. Tôi đã nhận thấy mọi người đôi khi chạy các lệnh với một vài & tùy chọn. Ví dụ, trong lệnh dưới đây, có hai & dấu hiệu. Mục đích của chúng là gì? Có phải chúng luôn được sử dụng cùng với nohup?

nohup foo.sh <script parameters> >& <log_file_name> &

Câu trả lời:


15

Ngoài câu trả lời của Martin, Ash và Kevin, đôi khi bạn sẽ thấy một ký hiệu và được sử dụng toán học một chút và * :

$ echo $(( 11 & 7 ))
3

Trong trường hợp bạn không quen thuộc với các toán tử bit:

11: 1011
 7: 0111
-------- AND
 3: 0011

Ở mỗi vị trí có một bit trong số thứ nhất VÀ số thứ hai, đặt bit đó thành một trong câu trả lời.

* Tính năng trong câu trả lời của Kevin được gọi là hợp lý VÀ.

Để giải thích câu trả lời của Ash, khi được sử dụng để chuyển hướng, ký hiệu và có thể yêu cầu trình bao mô tả tệp mô tả tệp. Trong lệnh này echo "hello" > outputfile 2>&1 ampersand gây ra bất kỳ đầu ra nào có thể đi đến lỗi tiêu chuẩn (stderr, mô tả tệp 2) để đi đến cùng một nơi với đầu ra tiêu chuẩn (stdout, mô tả tệp 1, mặc định cho bên trái > ). Các >& outputfile toán tử là viết tắt cho > outputfile 2>&1.

Ngoài ra, mới trong Bash 4, có hai thuật ngữ mới cho các mệnh đề trong case chỉ huy ;&;;& ảnh hưởng đến việc một trường hợp "rơi qua" và, nếu vậy, liệu thử nghiệm tiếp theo có được thực hiện hay không.


Thật tuyệt, Dennis! Giả sử tôi sử dụng nhật ký đầu cuối ssh vào máy, sau đó sử dụng đầu cuối của ssh để thực thi lệnh (giả sử quy trình dài hạn), thì nếu tôi thoát khỏi phiên cuối, thì quy trình dài hạn của lệnh sẽ bị chấm dứt? Và nếu tôi muốn lệnh tiếp tục thực thi ngay cả khi tôi thoát shell, tôi nên sử dụng nohup hoặc & amp; (ở cuối lệnh) hoặc sử dụng cả nohup và & amp;?
George2

1
@ George2: Không, >& filename xuất cả stdout và stderr vào cùng một tệp. Nếu bạn chỉ muốn chuyển hướng stderr (và để stdout một mình), bạn sẽ làm 2> filename. Đối với câu hỏi khác của bạn, rất có thể bạn sẽ sử dụng cả hai nohup&.
Dennis Williamson

1
@ George2: Nếu bạn không làm nền lệnh thì bạn sẽ không nhận được dấu nhắc shell để bạn có thể đưa ra lệnh logout hoặc là exit chỉ huy.
Dennis Williamson

2
George: Nếu bạn không sử dụng & amp;, thì bạn sẽ không bao giờ lấy lại lời nhắc của mình để làm bất cứ điều gì khác. Thiết bị đầu cuối sẽ là hung hung hung cho đến khi quá trình (bất kể đó là gì) kết thúc hoặc nó bị chấm dứt / bị giết. & Amp; đảm bảo rằng quá trình chạy trong nền. Tuy nhiên, nếu bạn đăng xuất, hệ điều hành sẽ chấm dứt tất cả các quy trình của bạn, điều này cũng giết chết quá trình nền của bạn. Nếu bạn dùng không bạn đang nói với quá trình, hãy bỏ qua lệnh mà sẽ chấm dứt bạn.
Martin Marconcini

1
@ George2: Vâng. "miễn dịch với hangups" == "quá trình tiếp tục" và "không tty" == "thoát phiên giao diện điều khiển thiết bị đầu cuối"
Dennis Williamson

31

Trong tập lệnh bash shell, ampersand & amp; 'được sử dụng để xử lý các quá trình:

find -name hello &

Sẽ khiến lệnh find bị rẽ nhánh và chạy trong nền (bạn luôn có thể giết nó bằng lệnh PID).


Cảm ơn Martin, giả sử tôi sử dụng đăng nhập thiết bị đầu cuối ssh vào máy, sau đó sử dụng thiết bị đầu cuối của ssh để thực thi lệnh (giả sử quy trình dài hạn), sau đó nếu tôi thoát phiên cuối, thì quy trình dài hạn của lệnh sẽ bị chấm dứt ? Và nếu tôi thực thi lệnh bằng cách sử dụng & amp; trong thiết bị đầu cuối ssh, ngay cả khi tôi thoát khỏi thiết bị đầu cuối, quy trình chạy dài của lệnh vẫn chạy, đúng không?
George2

1
Đó là chính xác George. Quá trình nền nên tiếp tục cho đến khi chúng thoát hoặc bạn giết chúng. Tuy nhiên, như đã được chỉ ra, bạn sẽ không cần phải tránh quá trình để chết khi người dùng đăng xuất.
Martin Marconcini

Cảm ơn Martin! Tôi muốn biết lý do tại sao chúng ta cần sử dụng cả & amp; và nohup, và các chức năng riêng lẻ của chúng là gì khiến chúng ta đạt được mục tiêu cho phép lệnh tiếp tục chạy ngay cả khi bảng điều khiển đầu cuối thoát. Tôi đã đọc trang man cho nohup, và nó được đề cập "chạy lệnh miễn dịch với hangouts, với kết quả không phải là tty", tôi bối rối không biết liệu miễn dịch với hangouts có phải là điều bạn muốn để lệnh tiếp tục chạy mà không bị ảnh hưởng giao diện điều khiển thiết bị đầu cuối? Nếu vậy, tôi nghĩ sử dụng nohup là đủ và không cần sử dụng & amp;. Có ý kiến ​​gì không?
George2

1
Bạn cần sử dụng Cả hai, nếu bạn không sử dụng & amp;, thiết bị đầu cuối sẽ không cho phép bạn nhập bất kỳ lệnh nào khác. Cách tốt nhất để bạn nhìn thấy nó, chỉ là thử nó. Một ví dụ điển hình là một lệnh mất một chút thời gian, như find: find -name someName / & gt; somefile.txt hãy thử điều đó với nohup và & amp; và thấy sự khác biệt.
Martin Marconcini

Điều này có một câu trả lời tuyệt vời cho câu hỏi nohup: serverfault.com/questions/311593/
joshperry

26

tại sao chạy lệnh Linux shell với & amp;?

Để lấy lại lời nhắc của bạn ngay lập tức và chạy quy trình trong nền.

Chức năng của chúng là gì?

không cho phép quá trình nền tiếp tục chạy ngay cả sau khi người dùng đăng xuất (hoặc thoát khỏi vỏ khởi tạo).

& gt; & amp; chuyển hướng cả đầu ra tiêu chuẩn và lỗi tiêu chuẩn vào tệp nhật ký.

& amp; chạy toàn bộ trong nền, cung cấp cho bạn nhắc lại ngay lập tức.

Giải trình:

Mỗi quy trình Linux sẽ mở ba kênh I / O, một "stdin" đầu vào, "đầu ra tiêu chuẩn" và một đầu ra lỗi tiêu chuẩn "stderr". Chúng có thể được sử dụng cho nhị phân nhưng là văn bản truyền thống. Khi hầu hết các chương trình thấy stdin đóng, chúng sẽ thoát (điều này có thể được lập trình viên thay đổi).

Khi vỏ cha mẹ thoát ra, stdin được đóng lại trên con cái và (thường là thường) chúng cũng thoát ra. Ngoài ra, trẻ em nhận được tín hiệu phần mềm, SIGHUP, cho biết người dùng đã "gác máy" (trước đây là modem) và mặc định ở đây cũng là để thoát. (Lưu ý, một lập trình viên có thể thay đổi tất cả những điều này khi viết chương trình).

Vì vậy, những gì nohup làm là cho trẻ xử lý một môi trường I / O riêng biệt, buộc các phần bên trong vào một thứ không gắn với vỏ cha mẹ và che chắn cho đứa trẻ khỏi tín hiệu SIGHUP. Khi người dùng ngắt kết nối, bạn sẽ thấy quy trình nền nohup thuộc sở hữu của init (quy trình 1), chứ không phải trình bao của người dùng.

Tuy nhiên, nohup không thể thực hiện công việc hoàn toàn nếu quy trình được chạy ở nền trước, vì vậy & amp; được sử dụng để chạy chương trình trong nền, nơi nó có thể vui vẻ chạy với hoặc không có người dùng đăng nhập.


Giả sử tôi sử dụng nhật ký đầu cuối ssh vào máy, sau đó sử dụng đầu cuối của ssh để thực thi lệnh (giả sử quy trình dài hạn), thì nếu tôi thoát khỏi phiên cuối, thì quy trình dài hạn của lệnh sẽ bị chấm dứt? Và nếu tôi muốn lệnh tiếp tục thực thi ngay cả khi tôi thoát shell, tôi nên sử dụng nohup hoặc & amp; (ở cuối lệnh) hoặc sử dụng cả nohup và & amp;?
George2

1
Chính xác, sử dụng cả nohup và & amp; để quá trình tiếp tục sau khi ngắt kết nối SSH.
kmarsh

Cảm ơn Kmarsh! Tôi muốn biết lý do tại sao chúng ta cần sử dụng cả & amp; và nohup, và các chức năng riêng lẻ của chúng là gì khiến chúng ta đạt được mục tiêu cho phép lệnh tiếp tục chạy ngay cả khi bảng điều khiển đầu cuối thoát. Tôi đã đọc trang man cho nohup, và nó được đề cập "chạy lệnh miễn dịch với hangouts, với kết quả không phải là tty", tôi bối rối không biết liệu miễn dịch với hangouts có phải là điều bạn muốn để lệnh tiếp tục chạy mà không bị ảnh hưởng giao diện điều khiển thiết bị đầu cuối? Nếu vậy, tôi nghĩ sử dụng nohup là đủ và không cần sử dụng & amp;. Có ý kiến ​​gì không?
George2

1
Tôi sẽ chỉnh sửa câu trả lời của tôi để trả lời.
kmarsh

13

Ngoài câu trả lời của @ Martin: Công dụng khác của ký hiệu ( >& như trên) là để bắt cả hai stdoutstderr. Thông thường, nếu bạn chuyển hướng đầu ra thành một tệp chỉ với '& gt;', bạn sẽ chỉ nhận được đầu ra stdout, thiếu bất kỳ lỗi nào.


1. Cảm ơn Ash, tôi muốn xác nhận với bạn rằng "& gt; & amp; & lt; tên tệp nhật ký & gt;", sẽ chuyển tất cả thiết bị xuất chuẩn và thiết bị xuất chuẩn vào tệp nhật ký, đúng không? 2. Và sử dụng "& gt; & lt; tên tệp nhật ký & gt;" Sẽ kết xuất tất cả các thiết bị xuất chuẩn vào tệp nhật ký, đúng không?
George2

1
@George: Vâng, đúng vậy.
Ash

Cảm ơn Ash! Tôi muốn biết lý do tại sao chúng ta cần sử dụng cả & amp; và nohup, và các chức năng riêng lẻ của chúng là gì khiến chúng ta đạt được mục tiêu cho phép lệnh tiếp tục chạy ngay cả khi bảng điều khiển đầu cuối thoát. Tôi đã đọc trang man cho nohup, và nó được đề cập "chạy lệnh miễn dịch với hangouts, với kết quả không phải là tty", tôi bối rối không biết liệu miễn dịch với hangouts có phải là điều bạn muốn để lệnh tiếp tục chạy mà không bị ảnh hưởng giao diện điều khiển thiết bị đầu cuối? Nếu vậy, tôi nghĩ sử dụng nohup là đủ và không cần sử dụng & amp;. Có ý kiến ​​gì không?
George2

4

Ngoài câu trả lời của Martin và Ash, đôi khi bạn có thể thấy việc sử dụng một && mã thông báo. Điều này được sử dụng để nói "chạy lệnh thứ hai khi và chỉ khi lệnh đầu tiên chạy thành công." Một lệnh được viết tốt sẽ, nếu nó có bất kỳ lỗi nào, không thoát thành công.

[kevin@box ~]$ ls file && echo removing file && rm file
ls: file: No such file or directory
[kevin@box ~]$ touch file
[kevin@box ~]$ ls file && echo removing file && rm file
file
removing file
[kevin@box ~]$

Thật tuyệt, Kevin! Giả sử tôi sử dụng nhật ký đầu cuối ssh vào máy, sau đó sử dụng đầu cuối của ssh để thực thi lệnh (giả sử quy trình dài hạn), thì nếu tôi thoát khỏi phiên cuối, thì quy trình dài hạn của lệnh sẽ bị chấm dứt? Và nếu tôi muốn lệnh tiếp tục thực thi ngay cả khi tôi thoát shell, tôi nên sử dụng nohup hoặc & amp; (ở cuối lệnh) hoặc sử dụng cả nohup và & amp;?
George2

Một trong hai sẽ làm việc. NOHUP là cách làm ban đầu, tôi tưởng tượng (nhưng hoàn toàn đoán được), nhưng nền tảng hoạt động ngay bây giờ. Một sự khác biệt quan trọng là khi chạy một vỏ tương tác bằng cách sshing vào một hệ thống từ xa. Quá trình NOHUP sẽ chạy ở nền trước, nhưng sẽ tiếp tục chạy nếu bạn thoát, trong khi quá trình nền sẽ quay lại ngay lập tức sau khi bạn sinh ra lệnh. Nhưng khi bạn cố gắng thoát khỏi một vỏ tương tác với một lệnh chạy trong nền, bạn sẽ được cảnh báo trước.
Kevin M

2

Câu trả lời của Martin là tốt, nhưng một chút mơ hồ. Lệnh luôn được rẽ nhánh và được thực thi, nhưng hành vi shell bình thường là chờ lệnh cho đến khi thoát. Các ký hiệu và đặt nó vào nền để bạn lấy lại dấu nhắc thiết bị đầu cuối và bạn có thể làm những việc khác. Nếu quy trình đưa dữ liệu ra thiết bị xuất chuẩn hoặc thiết bị xuất chuẩn, điều này sẽ được trộn lẫn với bất cứ điều gì bạn đang làm tại dấu nhắc và có thể làm bạn bối rối. Đây là lý do tại sao bạn chuyển hướng sau đó với & gt; & amp; /path/to/logfile.txt.

Để đáp ứng với George2, hành vi bình thường đối với thoát vỏ là gửi tín hiệu SIGHUP tới tất cả các quy trình trong cùng một nhóm quy trình (về cơ bản là thứ bạn sinh ra) và chúng thường sẽ chấm dứt. Nếu bạn muốn điều này tiếp tục ngay cả khi bạn đóng quá trình shell, bạn có thể sử dụng lệnh nohup để làm cho chúng bỏ qua tín hiệu này và tiếp tục chạy. Có một tên đặc biệt cho loại quy trình này, nó được gọi là quy trình daemon (phát âm là 'quỷ').


Cảm ơn Giàu! Giả sử tôi sử dụng nhật ký đầu cuối ssh vào máy, sau đó sử dụng đầu cuối của ssh để thực thi lệnh (giả sử quy trình dài hạn), thì nếu tôi thoát khỏi phiên cuối, thì quy trình dài hạn của lệnh sẽ bị chấm dứt? Và nếu tôi muốn lệnh tiếp tục thực thi ngay cả khi tôi thoát shell, tôi nên sử dụng nohup hoặc & amp; (ở cuối lệnh) hoặc sử dụng cả nohup và & amp;? Và tại sao?
George2

Này george, xin lỗi tôi sẽ trả lời rất muộn. Có, nếu bạn thoát khỏi trình bao, quá trình dài hạn sẽ bị chấm dứt. Nếu bạn muốn nó tiếp tục, bạn cần thực hiện cả nohup (để không bị chấm dứt khi đóng vỏ) và & amp; (để đặt trong nền, vì vậy bạn có thể Crtl-D hoặc thoát khỏi vỏ của bạn). Bạn cũng có thể xem lệnh setsid, lệnh này sẽ cho phép tiến trình của bạn chạy, để nó bỏ qua SIGHUP theo một cách hơi khác.
Rich Homolka

Câu trả lời tuyệt vời, giải thích các thực tiễn tốt nhất cho các quy trình bắt đầu chạy nền.
Marcel Valdez Orozco
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.