Câu trả lời:
&
Toán tử trailing ở cuối lệnh được sử dụng để đặt các lệnh vào nền. Đây thực sự là một cú pháp tiêu chuẩn được chỉ định bởi tiêu chuẩn POSIX :
Danh sách không đồng bộ
Nếu một lệnh bị chấm dứt bởi toán tử điều khiển ('&'), shell sẽ thực thi lệnh không đồng bộ trong một lớp con. Điều này có nghĩa là shell sẽ không đợi lệnh kết thúc trước khi thực hiện lệnh tiếp theo.
Định dạng để chạy một lệnh trong nền là:
lệnh1 & [lệnh2 & ...]
Mục đích của các lệnh nền là chạy một lệnh không có shell chính trong script hoặc shell tương tác đang chờ lệnh, điều này sẽ chặn thực thi các lệnh khác và gây bất tiện cho người dùng chờ. Điều này rất hữu ích để bắt đầu các lệnh chạy dài nhưng bạn cần tiếp tục làm việc trong trình bao hiện tại. Như bạn có thể đoán, điều này bắt nguồn từ thời không có trình giả lập thiết bị đầu cuối nhiều tab, nhưng thiết bị đầu cuối là phần cứng vật lý thực tế được kết nối với chính máy tính.
Từ định nghĩa bạn có thể thấy đó &
cũng đóng vai trò là bộ kết thúc lệnh cho danh sách các lệnh, giống như ;
vậy. Trong ví dụ cụ thể của bạn, pyprogramm >> /dev/null 2>&1 &
chỉ có một lệnh trong danh sách.
Tổng quát hơn
echo Hello ; echo World ;
và
echo Hello & echo World &
là hai ví dụ về danh sách được chấm dứt bởi các nhà khai thác ;
và &
. Một điểm khác biệt là &
danh sách kết thúc sẽ có kết nối đầu vào /dev/null
nếu điều khiển công việc bị tắt:
Nếu điều khiển công việc bị vô hiệu hóa (xem bộ, -m), đầu vào tiêu chuẩn cho danh sách không đồng bộ, trước khi thực hiện bất kỳ chuyển hướng rõ ràng nào, sẽ được coi là được gán cho một tệp có cùng thuộc tính là / dev / null. Điều này sẽ không xảy ra nếu kiểm soát công việc được kích hoạt. Trong mọi trường hợp, chuyển hướng rõ ràng của đầu vào tiêu chuẩn sẽ ghi đè hoạt động này.
Tuy nhiên, trong danh sách tuần tự, mỗi lệnh vẫn stdin
được kết nối với thiết bị đầu cuối nếu không có chuyển hướng rõ ràng.
Cũng lưu ý rằng, từ định nghĩa chúng ta đã đề cập trước đó, &
thực thi các lệnh trong subshell. Ngược lại, ;
danh sách kết thúc được thực thi trong shell hiện tại. Cũng có sự khác biệt về trạng thái thoát. Đối với &
tiêu chuẩn nói:
Trạng thái thoát của danh sách không đồng bộ sẽ bằng không.
Điều này rất có ý nghĩa khi bạn muốn đặt nhiều lệnh trong nền. Khi bạn viết một tập lệnh hoặc lệnh, bạn sẽ phải chọn các lệnh mà bạn không quan tâm nếu chúng thất bại hay không, hoặc bạn sẽ phải tìm cách xử lý trạng thái thoát khác không (lỗi). Trong ví dụ cụ thể của bạn, pyprogramm >> /dev/null 2>&1 &
chạy trong nền nên có một số cách cho biết nó có thất bại hay không, tuy nhiên đánh giá rằng bạn sử dụng 2>&1
bạn đang ẩn đầu ra lỗi bằng cách chuyển hướng và có thể bạn cho rằng tập lệnh không bị lỗi.
Ngược lại, ;
trạng thái thoát được định nghĩa là:
Trạng thái thoát của danh sách tuần tự sẽ là trạng thái thoát của lệnh cuối cùng trong danh sách.
Một lần nữa, điều này có ý nghĩa về cách bạn viết một danh sách tuần tự các lệnh trong dòng lệnh và cách bạn muốn mọi thứ được xử lý nếu một số lệnh trong danh sách không thành công.
Thực tế rằng đây là POSIX phương tiện độ nét rằng tất cả Bourne giống như vỏ, ý nghĩa bash
, dash
và ksh
phải hỗ trợ nó.
&
trong chuyển hướng khác với &
khi kết thúc lệnh. Nó có nghĩa là sao chép (sao chép) đối tượng mô tả tệp. Xem chính xác & có nghĩa là gì trong chuyển hướng đầu ra?
Trong bash
đó cũng có |&
toán tử (lưu ý không có khoảng cách giữa đường ống và ký hiệu). Từ hướng dẫn sử dụng bash :
Nếu | & được sử dụng, lỗi tiêu chuẩn của lệnh, ngoài đầu ra tiêu chuẩn của nó, được kết nối với đầu vào tiêu chuẩn của lệnh2 thông qua đường ống; nó là viết tắt cho 2> & 1 |. Điều này chuyển hướng ngầm định của lỗi tiêu chuẩn đến đầu ra tiêu chuẩn được thực hiện sau khi bất kỳ chuyển hướng nào được chỉ định bởi lệnh.
Nó có nghĩa là chạy lệnh trong nền. Kịch bản gọi tiếp tục thay vì chặn cho đến khi lệnh được gọi hoàn thành.
&
ẩn đầu ra không có vẻ đúng. Đoạn văn từ tiêu chuẩn mà bạn đang trích dẫn nói về đầu vào , không phải đầu ra . Lý do cho sự khác biệt giữa kiểm soát công việc có được kích hoạt hay không là do một quá trình nền cố gắng đọc từ tty sẽ bị đình chỉ. Tại thời điểm đó, bạn cần sử dụng điều khiển công việc để đặt nó ở phía trước để cung cấp đầu vào mà nó đang chờ. Tất cả điều đó không thể được thực hiện mà không có kiểm soát công việc và do đó nếu kiểm soát công việc bị vô hiệu hóa, stdin cần phải được chuyển hướng từ/dev/null
hoặc tương đương.