Temiz ortama sahip bir komut dosyası nasıl başlatılır?


15

Aşağıdakileri denedim ama işe yaramıyor gibi görünüyor:

$ cat script.sh
#!/bin/env -i /bin/sh

/bin/env
$ script.sh
/bin/env: invalid option -- ' '
Try `/bin/env --help' for more information.

Benzer sorular bulundu ancak shebang dan nasıl yapılacağını göstermez: unix.stackexchange.com/questions/48994/...
Balki

5
Bunu shebang'dan yapamazsın. Mesele sadece bir argümanı kabul edebilir.
jordanm

Yanıtlar:


7

Bunun işe yaramamasının nedeni -i /bin/sh, tek bir argüman olarak görmesidir env. Genellikle bu 2 argüman olur -ive /bin/sh. Bu sadece mesele sınırlamasıdır. Kaçış yok.


Ancak bu görevi hala farklı bir yolla gerçekleştirebilirsiniz.

Bu görevin komut dosyasının kendisi tarafından gerçekleştirilmesini istiyorsanız ve bunun gibi bir şey env -i script.shyapmanız gerekmiyorsa, komut dosyasının kendisini yeniden çalıştırmasını sağlayabilirsiniz.

#!/bin/sh
[ -z "$CLEANED" ] && exec /bin/env -i CLEANED=1 /bin/sh "$0" "$@"

Bu, CLEANEDortam değişkeni ayarlanmamışsa komut dosyasının kendini yeniden yürütmesine neden olur . Sonra yeniden yürütme, bir döngüye girmemesini sağlamak için değişkeni ayarlar.


envGNU coreutils'in artık buna -Sbenzer ancak tam olarak aynı olmayan sorunları çözme seçeneği var . Örneğin #!/usr/bin/env -S perl -T.
Weijun Zhou

Denedim. Orijinal soru için de çalışır. Sadece kullan #!/usr/bin/env -S -i /bin/sh. Taşınabilirlik sorunlarının farkında olun.
Weijun Zhou

3

Komut dosyanızı şununla çalıştırın env -i:

env -i script.sh

Ve senaryo her zamanki gibi:

#!/bin/sh
# ... your code here

Temiz bir ortamla koşmak istiyorsan, açıkça çalıştırdığın zaman. Eduardo Ivanec bu cevapta bazı fikirler veriyor exec, ortam temiz olmadığında betiğinizi yinelemeli olarak çağırabilirsiniz (örn. $ HOME tanımlanır):

[ "$HOME" != "" ] && exec -c $0

Güzel. Yaptığım gibi env -i bash yapmayın ve sonra env değişkenlerinizin neden hala ayarlandığını merak edin (elbette bash kaynakları .bashrc ve arkadaşları 8)
Neil McGill

2

Bash ile şu şekilde yapabilirsiniz:

#!/usr/bin/bash

set -e
set -u

[ -v HOME ] && exec -c "$0" "$@"

# continue with the rest of the script
# e.g. print the cleaned environment:
export

set -eVe set -u komutlar kesinlikle gerekli değildir, ancak ben onları bu yaklaşım (örneğin olarak tanımsız değişkenler erişen dayanmaz olduğunu göstermek için dahil [ "$HOME" != "" ]olur) ve uyumlu set -ebir ortamda.

HOMEDeğişkenin test edilmesi güvenli olmalıdır, çünkü bash komut dosyalarını etkileşimli olmayan modda yürütür, yani ~/.bashrcbaşlatma sırasında (ortam değişkenlerinin ayarlanabileceği) gibi yapılandırma dosyaları kaynaklanmaz.

Örnek çıktı:

declare -x OLDPWD
declare -x PWD="/home/juser"
declare -x SHLVL="1"

0

$ cat script.sh

#!/bin/env -i /bin/sh

Ne yazık ki, bu şekilde çalışmaz - Linux, -i /bin/shaktarılacak bir argüman olarak düşünürenv (bkz. Shebang ).


0

Linux 2 argümanlı sapma sınırlaması (yorumlayıcı + tek argüman) çoğu cevapta belirtilmiştir, ancak bunun yapılamayacağını söylemek yanlıştır - tek bir argümanla yararlı bir şey yapabilen bir tercümana geçmeniz gerekir:

#!/usr/bin/perl -we%ENV=();exec "/bin/sh " . join " ", map "'$_'", @ARGV;
# your sh script here

Bunun yaptığı, bağımsız değişkenleri doğru bir şekilde tırnak içine alan (daha ucuz ) ve çağıran perltek satırlı bir script ( -e) ile çağırmaktır . Gerekirse daha fazla mantık eklenebilir ( karakterlerle sınırlı olduğunuz için Linux'ta çok fazla olmasa da, muhtemelen 128)%ENVenv -iexec /bin/shperlBINPRM_BUF_SIZE

Ne yazık ki, bu Linux'a özgüdür, çoklu shebang argümanlarına izin veren bir sistemde çalışmaz: - /

perlo oluyor böylece, tek bir argüman olarak bu dizeyi işler alıntı değil normalde ile yapacağı gibi yukarıdaki perl -e ...bu korunur tırnak eklemeniz durumunda (komut satırından, perl bir işe yaramaz şikayet edecek Üzerinde uyarılarıyla, sadece bir hazır dize görür sabit).

Ayrıca, bu şekilde kullanıldığında davranışta küçük bir değişiklik olduğunu, @ARGVnormalde sadece argümanları $0içerdiğini ve komut dosyasını içerdiğini unutmayın, ancak bu shebang $ARGV[0]ile komut dosyasının adı (ve $0is -e) biraz daha kolaylaşır.

Bunu -c, eski AT&T'nin komut satırını (ekstra bir argüman olmadan ) "yeniden işleyen" bir tercümanla da çözebilirsiniz ksh93:

#!/bin/ksh /usr/bin/env -i /bin/sh

ama belki de kshgünümüzde yaygın değil ;-)

( bashile benzer bir özelliğe sahiptir --wordexp, ancak çalıştığı sürümlerde "belgesizdir" ve belgelendiği sürümlerde derleme zamanında etkinleştirilmez: - / İki bağımsız değişkene ihtiyaç duyduğundan bunun için de kullanılamaz. ..)

Ayrıca, @Patrick ve @ maxschlepzig'in cevaplarında etkili bir varyasyon:

#!/bin/bash
[ "$_" != bash ] && exec -c -a "bash" /bin/bash "$0" "$@"
# your script here

Aksine yeni değişken kullanımı daha bu kullanımları özel " _bash" tam olarak ayarlı değilse değişken "" daha sonra senaryoyu değiştirmek execkullanarak -ayapmak için ARGV[0](ve dolayısıyla $_"Bash ve kullanarak) sadece" -cçevreyi temizlemek için.

Alternatif olarak, betiğin başında ortamı temizlemek kabul edilebilirse (yalnızca bash):

#!/bin/sh
unset $(compgen -e)
# your script here

Bu compgen, dışa aktarılan tüm ortam değişkenlerinin adlarını listelemek ve unsetbunları tek seferde kullanmak için (tamamlama yardımcısı) kullanır .

Ayrıca , shebang davranışının genel sorunu hakkında daha fazla bilgi için shebang'daki çoklu argümanlar bölümüne bakınız .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.