Docker için birçok entrypoint.sh betiğinin şöyle bir şey yaptığını fark ettim:
#!/bin/bash
set -e
... code ...
exec "$@"
Ne set -e
ve ne exec "$@"
için?
Yanıtlar:
Temelde, iletilen tüm komut satırı argümanlarını alır entrypoint.sh
ve bunları bir komut olarak çalıştırır. Niyet temelde "Bu .sh betiğindeki her şeyi yapın, ardından aynı kabukta kullanıcının komut satırından girdiği komutu çalıştırın".
Görmek:
exec "$@"
, şu anda çalışan işlemi, aktarılan bağımsız değişkenler için oluşturulan yeni işlemle değiştireceğini unutmayın . Docker sinyallemesi için önemli: stackoverflow.com/a/32261019/99717
set -e
çalıştırılan herhangi bir komut sıfır olmayan bir çıkış koduyla çıktığında hemen çıkacak bir kabuk seçeneği ayarlar. Komut dosyası, başarısız olan komutun çıkış koduyla geri dönecektir. Bash man sayfasından:
set -e:
Bir boru hattı (tek bir basit komuttan oluşabilir), bir liste veya bir bileşik komut (yukarıdaki SHELL GRAMMAR'a bakın), sıfır olmayan bir durumla çıkarsa hemen çıkın. Başarısız olan komut bir süre veya anahtar sözcüğünden hemen sonra komut listesinin bir parçasıysa, if veya elif ayrılmış sözcükleri izleyen testin parçası, && veya || ile çalıştırılan herhangi bir komutun parçasıysa, kabuk çıkmaz list, son && veya || 'den sonra gelen komut dışında, bir ardışık düzen içindeki herhangi bir komut ancak sonuncusu veya komutun dönüş değeri! ile ters çevriliyorsa. Alt kabuk dışındaki bir bileşik komut, -e yoksayılırken bir komut başarısız olduğu için sıfır olmayan bir durum döndürürse, kabuk çıkmaz. Eğer ayarlanmışsa, ERR üzerinde bir tuzak, kabuk çıkmadan önce yürütülür.
Bileşik bir komut veya kabuk işlevi -e'nin göz ardı edildiği bir bağlamda yürütülürse, bileşik komut veya işlev gövdesi içinde yürütülen komutların hiçbiri -e ayarından etkilenmez, -e ayarlanmış olsa ve bir komut bir arıza durumu. Bir bileşik komut veya kabuk işlevi, -e'nin göz ardı edildiği bir bağlamda yürütülürken -e'yi ayarlarsa, bu ayarın bileşik komut veya işlev çağrısını içeren komut tamamlanana kadar herhangi bir etkisi olmaz.
exec "$@"
genellikle giriş noktasını, ardından docker komutunu çalıştıran bir geçiş yapmak için kullanılır. Mevcut çalışan kabuğu "$@"
işaret eden komutla değiştirecektir. Varsayılan olarak, bu değişken komut satırı argümanlarına işaret eder.
Giriş noktası giriş noktası.sh'ye işaret eden bir görüntünüz varsa ve konteynerinizi olarak docker run my_image server start
çalıştırırsanız entrypoint.sh server start
, bu konteynerde çalışmaya dönüşür. Exec satırında entrypoint.sh
, pid 1 olarak çalışan kabuk, kendisini komutla değiştirecektir server start
.
Bu, sinyal işleme için kritiktir. Kullanmadan exec
, server start
yukarıdaki örnekte başka bir pid olarak çalışacak ve çıktıktan sonra kabuk betiğinize döneceksiniz. Pid 1'deki bir kabuk ile, bir SIGTERM varsayılan olarak göz ardı edilecektir. Bu docker stop
, konteynırınıza gönderilen zarif durdurma sinyalinin server
süreç tarafından asla alınmayacağı anlamına gelir . 10 saniye sonra (varsayılan olarak), docker stop
zarif kapatmadan vazgeçer ve uygulamanızı çıkmaya zorlayacak bir SIGKILL gönderir, ancak potansiyel veri kaybı veya kapalı ağ bağlantıları söz konusu olduğunda, uygulama geliştiricileri sinyali aldıysa etrafına kodlama yapmış olabilir. Aynı zamanda, konteynerinizin durması her zaman 10 saniye süreceği anlamına gelir.
shift
Ve gibi kabuk komutlarıyla set --
, değerinin değiştirilebileceğini unutmayın "$@"
. Örneğin /bin/sh -c "..."
, docker'in kabuk sözdizimini aşağıdakiler için kullanıyorsanız görünebilecek komuttan kaldıran bir komut dosyasının kısa bir kısmı 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 "$@"
test
işaret eden POSIX özelliklerine bakın -a
. [ "$#" -gt 1 ] && [ "$1" = /bin/sh ]
doğru x"$1"
değişimdir (yalnızca eski olmayan sözdizimini kullanırken bilgisayar korsanlığına gerek yoktur ).
shift 2; set -- $1
nasıl eval
ayrıştırılacağıyla aynı şey değildir . /bin/sh -c 'printf "%s\n" "hello world" "goodbye world"'
Somut bir test senaryosu istiyorsanız, düşünün ve Bash'in bir dizeyi bağımsız değişkenlere dönüştürürken tırnakları ayrıştırmadığını görün .
eval
yine /bin/sh -c
de bunun dizedeki davranışını yansıtmasını istediğime inanıyorum , ancak bir şeyi kaçırıyorsam lütfen bana bildirin.
set -e
- herhangi bir komut başarısız olursa komut dosyasından çık (sıfır olmayan değer)
exec "$@"
- giriş değişkenlerini yeniden yönlendirecek, burada daha fazlasını görün
exec
kesinlikle yeniden yönlendirmeler yaptığı bir kullanım moduna sahiptir, ancak bu o mod değildir.
set -e
, elle yazılmış hata işlemeden çok daha fazla hataya açık kabul edilir. (Aceleniz varsa, aşağıdaki alıştırmalar için üstteki analojiyi atlayın).