डॉक एंट्री लिपियों के लिए सेट-ई और "$ @" क्या करता है?


95

मैंने देखा है कि docker के लिए कई entrypoint.sh स्क्रिप्ट कुछ इस प्रकार है:

#!/bin/bash
set -e

... code ...

exec "$@"

set -eऔर इसके exec "$@"लिए क्या हैं ?


2
BashFAQ # 105 पुनः देखें : set -eहाथ से लिखित त्रुटि हैंडलिंग की तुलना में कहीं अधिक त्रुटि-प्रवण क्यों माना जाता है। (अगर जल्दबाजी में, नीचे दिए गए अभ्यास के लिए शीर्ष पर सादृश्य छोड़ें)।
चार्ल्स डफी

जवाबों:


72

यह मूल रूप से किसी भी कमांड लाइन तर्क को पारित करता है entrypoint.shऔर उन्हें कमांड के रूप में निष्पादित करता है। आशय मूल रूप से "इस .sh स्क्रिप्ट में सब कुछ है, तो उसी शेल में कमांड कमांड पर उपयोगकर्ता पास से चलता है"।

देख:


1
यह भी ध्यान दें कि exec "$@"वर्तमान में चल रही प्रक्रिया को बदल दिया जाएगा नई प्रक्रिया के साथ पारित तर्कों के लिए। डॉकर सिग्नलिंग के लिए महत्वपूर्ण: stackoverflow.com/a/32261019/99717
हॉके पार्कर

35

set -eयदि कोई कमांड चलाया जा रहा है तो गैर-शून्य निकास कोड के साथ बाहर निकलने के लिए एक शेल विकल्प सेट करता है। स्क्रिप्ट विफल कमांड के निकास कोड के साथ वापस आ जाएगी। बैश मैन पेज से:

सेट -e:

यदि एक पाइपलाइन (जिसमें एक एकल साधारण कमांड शामिल हो सकती है), एक सूची या एक कंपाउंड कमांड (ऊपर शेल शेलमर देखें), एक गैर-शून्य स्थिति से बाहर निकलता है। शेल से बाहर नहीं निकलता है यदि कमांड विफल रहता है तो कमांड लिस्ट का कुछ समय या कीवर्ड के तुरंत बाद का कमांड का हिस्सा है, अगर या एलिफ आरक्षित शब्दों के बाद टेस्ट का हिस्सा है, तो && या में निष्पादित किसी भी कमांड का हिस्सा || सूची को छोड़कर अंतिम और & / या के बाद कमांड, किसी भी कमांड को पाइपलाइन में लेकिन अंतिम, या यदि कमांड की वापसी मान के साथ उलटा किया जा रहा है! यदि कोई उप-कमांड के अलावा अन्य कंपाउंड कमांड एक गैर-शून्य स्थिति देता है क्योंकि एक कमांड विफल हो जाती है, जबकि उसे अनदेखा किया जा रहा है, तो शेल बाहर नहीं निकलता है। ईआरआर पर एक जाल, यदि सेट किया जाता है, तो शेल बाहर निकलने से पहले निष्पादित किया जाता है।

यदि किसी कंपाउंड कमांड या शेल फ़ंक्शन को उस संदर्भ में निष्पादित किया जाता है जहां -e को अनदेखा किया जा रहा है, तो कंपाउंड कमांड या फ़ंक्शन बॉडी के भीतर निष्पादित कमांड में से कोई भी -e सेटिंग से प्रभावित नहीं होगा, भले ही -e सेट हो और एक कमांड वापस आए विफलता की स्थिति। यदि एक कंपाउंड कमांड या शेल फंक्शन सेट करता है-जहाँ एक संदर्भ में निष्पादित किया जाता है, जहां-पर ध्यान नहीं दिया जाता है, तो कंपाउंड कमांड या कमांड कॉल फंक्शन कॉल पूरा होने तक उस सेटिंग का कोई प्रभाव नहीं पड़ेगा।


exec "$@"आमतौर पर इसका इस्तेमाल एंट्रीपॉइंट के माध्यम से पास बनाने के लिए किया जाता है और फिर docker कमांड चलाता है। यह वर्तमान रनिंग शेल को उस कमांड से बदल देगा जो "$@"इंगित कर रहा है। डिफ़ॉल्ट रूप से, वह चर कमांड लाइन के तर्कों की ओर इशारा करता है।

यदि आपके पास एंट्रीपॉइंट की ओर इशारा करते हुए एक एंट्रीपॉइंट के साथ एक छवि है। और आप अपने कंटेनर को docker run my_image server startउसी रूप में चलाते हैं , जो कंटेनर में चलने के लिए अनुवाद करेगा entrypoint.sh server start। निष्पादन लाइन पर entrypoint.sh, पीड 1 के रूप में चलने वाला शेल खुद को कमांड से बदल देगा server start

यह सिग्नल हैंडलिंग के लिए महत्वपूर्ण है। उपयोग किए बिना exec, server startऊपर के उदाहरण में एक और पिड के रूप में चलेगा, और इसके बाहर निकलने के बाद, आप अपनी शेल स्क्रिप्ट पर लौट आएंगे। Pid 1 में एक शेल के साथ, एक SIGTERM को डिफ़ॉल्ट रूप से अनदेखा किया जाएगा। इसका मतलब है कि सुशोभित स्टॉप सिग्नल जो docker stopआपके कंटेनर को भेजता है, serverप्रक्रिया द्वारा कभी भी प्राप्त नहीं होगा । 10 सेकंड के बाद (डिफ़ॉल्ट रूप से), docker stopसुंदर शटडाउन को छोड़ देगा और एक SIGKILL भेजेगा जो आपके ऐप को बाहर निकलने के लिए मजबूर करेगा, लेकिन संभावित डेटा हानि या बंद नेटवर्क कनेक्शन के साथ, ऐप डेवलपर्स को सिग्नल प्राप्त होने पर आसपास कोडित किया जा सकता था। इसका मतलब यह भी है कि आपके कंटेनर को बंद होने में हमेशा 10 सेकंड का समय लगेगा।

ध्यान दें कि शेल कमांड जैसे shiftऔर set --, आप के मान को बदल सकते हैं "$@"। उदाहरण के लिए यहां एक स्क्रिप्ट का एक छोटा हिस्सा है जो उस /bin/sh -c "..."कमांड से हटाता है जो दिखाई दे सकता है यदि आप इसके लिए डॉकर के शेल सिंटैक्स का उपयोग करते हैं 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 "$@"

1
POSIX testयुक्ति देखें , जो कि अशुभ को चिह्नित करता है -a[ "$#" -gt 1 ] && [ "$1" = /bin/sh ]सही प्रतिस्थापन है ( x"$1"केवल अप्रचलित सिंटैक्स का उपयोग करते समय हैकरी की कोई आवश्यकता नहीं है )।
चार्ल्स डफी

इसके अलावा, shift 2; set -- $1यह बिल्कुल भी नहीं है evalकि स्ट्रिंग को पार्स कैसे किया जाएगा। गौर करें /bin/sh -c 'printf "%s\n" "hello world" "goodbye world"', यदि आप एक ठोस परीक्षण का मामला चाहते हैं, और देखें कि स्ट्रिंग को तर्क में परिवर्तित करते समय बैश को उद्धरण नहीं देते हैं
चार्ल्स डफी

@CharlesDuffy अडॉप्टिव ऑप्शन पर टिप के लिए धन्यवाद, मुझे यकीन है कि मैं फिर से यह गलती करूंगा, पुरानी आदतें मुश्किल से मरती हैं। के साथ eval, मेरा मानना ​​है कि मैं अभी भी चाहता हूं कि /bin/sh -cस्ट्रिंग पर व्यवहार को प्रतिबिंबित करने के लिए , लेकिन कृपया मुझे बताएं कि क्या मुझे कुछ याद आ रहा है।
BMitch

30

set -e - यदि कोई भी कमांड विफल हो (गैर-शून्य मान) से बाहर निकलें स्क्रिप्ट

exec "$@"- इनपुट चर को रीडायरेक्ट करेगा, यहां और देखें


"इनपुट चर को पुनर्निर्देशित करेंगे"? एह? execनिश्चित रूप से एक उपयोग मोड है जहां यह पुनर्निर्देशन कर रहा है, लेकिन यह वह मोड नहीं है।
चार्ल्स डफी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.