2016-08-22 14 views
15

tôi đã nhận thấy rằng nhiều kịch bản entrypoint.sh cho Docker làm điều gì đó như thế này:

#!/bin/bash 
set -e 

... code ... 

exec "[email protected]" 

các set -eexec "[email protected]" cho là gì?

+0

Xem [BashFAQ # 105] (http://mywiki.wooledge.org/BashFAQ/105) lại: tại sao 'set -e' được coi là dễ bị lỗi hơn xử lý lỗi bằng tay. (Nếu vội vàng, bỏ qua sự tương tự ở phía trên cho các bài tập dưới đây). –

Trả lời

8

set -e - lối ra kịch bản nếu có lệnh không (non-zero giá trị)

exec "[email protected]" - sẽ chuyển hướng các biến đầu vào, xem chi tiết here

+0

"Sẽ chuyển hướng biến đầu vào"? Eh? 'exec' chắc chắn có chế độ sử dụng nơi nó thực hiện chuyển hướng, nhưng đây không phải là chế độ đó. –

2

set -e đặt tùy chọn trình bao để thoát ngay lập tức nếu bất kỳ lệnh nào đang chạy thoát với mã thoát khác không. Kịch bản lệnh sẽ trở lại với mã thoát của lệnh không thành công. Từ trang bash người đàn ông:

bộ -e:

Exit ngay lập tức nếu một đường ống (có thể bao gồm một lệnh đơn giản duy nhất), một danh sách, hoặc một lệnh phức hợp (xem SHELL GRAMMAR trên) , thoát với trạng thái khác 0. Vỏ không thoát ra nếu lệnh thất bại là một phần của danh sách lệnh ngay lập tức sau một thời gian hoặc cho đến khi từ khóa, một phần của thử nghiệm theo các từ được bảo vệ hoặc elif, một phần của bất kỳ lệnh nào được thực thi trong & & hoặc | | danh sách ngoại trừ lệnh sau cuối cùng & & hoặc ||, bất kỳ lệnh nào trong đường ống nhưng cuối cùng hoặc nếu giá trị trả lại của lệnh bị đảo ngược với! Nếu một lệnh ghép không phải là subshell trả về trạng thái khác 0 vì lệnh không thành công khi -e bị bỏ qua, trình bao sẽ không thoát. Một bẫy trên ERR, nếu được thiết lập, được thực hiện trước khi thoát khỏi trình bao. Tùy chọn này áp dụng cho môi trường shell và mỗi môi trường vỏ con riêng biệt (xem COMMAND EXECUTION MÔI TRƯỜNG ở trên), và có thể khiến các subshells thoát ra trước khi thực thi tất cả các lệnh trong subshell.

Nếu lệnh ghép hoặc hàm hệ vỏ thực hiện trong ngữ cảnh trong đó -e bị bỏ qua, không có lệnh nào được thực hiện trong lệnh ghép hoặc hàm chức năng sẽ bị ảnh hưởng bởi cài đặt -e, ngay cả khi -e là thiết lập và một lệnh trả về trạng thái lỗi. Nếu một lệnh ghép hoặc hàm shell đặt -e trong khi thực hiện trong một ngữ cảnh trong đó -e bị bỏ qua, cài đặt đó sẽ không có hiệu lực cho đến khi lệnh ghép hoặc lệnh chứa hàm gọi hoàn tất.


exec "[email protected]" thường được sử dụng để làm cho entrypoint một đường chuyền qua mà sau đó chạy lệnh Docker. Nó sẽ thay thế shell đang chạy hiện tại bằng lệnh mà "[email protected]" trỏ tới. Theo mặc định, biến đó trỏ tới các đối số dòng lệnh.

Nếu bạn có hình ảnh có điểm nhập trỏ đến entrypoint.sh và bạn chạy vùng chứa của mình dưới dạng docker run my_image server start, sẽ dịch để chạy entrypoint.sh server start trong vùng chứa. Tại đường exec entrypoint.sh, shell chạy như pid 1 sẽ tự thay thế bằng lệnh server start.

Điều này rất quan trọng để xử lý tín hiệu. Nếu không sử dụng exec, server start trong ví dụ trên sẽ chạy dưới dạng pid khác và sau khi thoát, bạn sẽ quay lại tập lệnh shell của mình. Với một vỏ trong pid 1, một SIGTERM sẽ bị bỏ qua theo mặc định. Điều đó có nghĩa là tín hiệu dừng duyên dáng mà docker stop gửi tới vùng chứa của bạn, sẽ không bao giờ được nhận bởi quy trình server. Sau 10 giây (theo mặc định), docker stop sẽ từ bỏ việc tắt máy duyên dáng và gửi SIGKILL sẽ buộc ứng dụng của bạn thoát nhưng với khả năng mất dữ liệu hoặc kết nối mạng bị đóng, nhà phát triển ứng dụng có thể đã mã hóa nếu họ nhận được tín hiệu . Nó cũng có nghĩa là container của bạn sẽ luôn mất 10 giây để dừng lại.

Lưu ý rằng với các lệnh shell như shiftset --, bạn có thể thay đổi giá trị "[email protected]". Ví dụ. đây là một phần ngắn của một kịch bản mà loại bỏ các /bin/sh -c "..." từ lệnh có thể xuất hiện nếu bạn sử dụng cú pháp vỏ Docker cho CMD:

# convert `/bin/sh -c "server start"` to `server start` 
if [ $# -gt 1 ] && [ x"$1" = x"/bin/sh" ] && [ x"$2" = x"-c" ]; then 
    shift 2 
    eval "set -- $1" 
fi 

.... 

exec "[email protected]" 
+0

Xem [thông số thử nghiệm 'POSIX'] (http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html), đánh dấu '-a' đã lỗi thời. '[" $ # "-gt 1] && [" $ 1 "=/bin/sh]' là thay thế chính xác (không cần hack 'x" $ 1 "' khi chỉ sử dụng cú pháp không lỗi thời). –

+0

Ngoài ra, 'ca 2; set - $ 1' không giống như cách 'eval' sẽ phân tích cú pháp chuỗi. Hãy xem xét '/ bin/sh -c 'printf"% s \ n "" hello world "" tạm biệt thế giới "'', nếu bạn muốn một trường hợp thử nghiệm cụ thể, và xem [Bash không phân tách cú pháp khi chuyển đổi một chuỗi thành các đối số ] (https://stackoverflow.com/questions/15857027/bash-doesnt-parse-quotes-when-converting-a-string-to-arguments). –

+0

@CharlesDuffy cảm ơn vì mẹo trên tùy chọn lỗi thời, tôi chắc chắn tôi sẽ mắc lỗi này một lần nữa, thói quen cũ sẽ chết khó khăn. Với 'eval', tôi tin rằng tôi vẫn muốn rằng để phản ánh hành vi của'/bin/sh -c' sẽ có trên chuỗi, nhưng xin vui lòng cho tôi biết nếu tôi đang thiếu một cái gì đó. – BMitch

Các vấn đề liên quan