2010-10-28 26 views
6

Tôi có kịch bản bash sau:Bash script không thoát ngay lập tức khi `exit` được gọi

tail -F -n0 /private/var/log/system.log | while read line 
do 
    if [ ! `echo $line | grep -c 'launchd'` -eq 0 ]; then 
     echo 'launchd message' 
     exit 0 
    fi 
done 

Đối với một số lý do, nó được lặp lại launchd message, chờ đợi một đầy 5 giây, và sau đó thoát.

Tại sao điều này xảy ra và làm cách nào để thoát ngay sau khi nó lặp lại launchd message?

Trả lời

9

Vì bạn đang sử dụng đường ống, vòng lặp while đang được chạy trong một vỏ con. Chạy nó trong shell chính thay vào đó.

#!/bin/bash 

while ... 
do 
    ... 
done < <(tail ...) 
+0

Tôi nhận được lỗi cú pháp ở dòng đã hoàn thành ... – Chetan

+0

Ah, đó là vì tôi đang sử dụng/bin/sh, ngu ngốc. – Chetan

+0

Gọi bash là sh sẽ vô hiệu hóa một số tính năng nhất định, bao gồm cả thay thế quy trình. –

3

Như được chỉ ra bởi Ignacio, tail | while tạo một vỏ bọc con. Sự chậm trễ là bởi vì nó đang chờ dòng tiếp theo được ghi vào tệp nhật ký trước khi mọi thứ đóng lại.

Bạn có thể thêm dòng này ngay lập tức trước khi lệnh exit của bạn nếu bạn không muốn sử dụng thay thế tiến trình:

kill -SIGPIPE $$ 

Thật không may, tôi không biết cách nào để kiểm soát mã lối ra bằng phương pháp này. Nó sẽ là 141 là 128 + 13 (số hiệu của SIGPIPE).

Nếu bạn đang cố gắng khởi động trình nền phụ thuộc vào một trình tiện ích khác đã bắt đầu, có thể có cách tốt hơn để thực hiện điều đó.

Nhân tiện, nếu bạn đang viết kịch bản Bash (bạn phải sử dụng <() thay thế quy trình), bạn có thể viết if như sau: if [[ $line == *launchd* ]].

2

Bạn cũng có thể thoát khỏi vỏ con với mã thoát câu chuyện và sau đó kiểm tra giá trị của "$?" để có được hiệu ứng tương tự như bạn đang tìm kiếm:

tail -F -n0 /private/var/log/system.log | while read line 
do 
    if [ ! `echo $line | grep -c 'launchd'` -eq 0 ]; then 
     echo 'launchd message' 
     exit 10 
    fi 
done 
if [ $? -eq 10 ]; then exit 0; fi 
Các vấn đề liên quan