#! / Usr / bin / env bash neden #! / Bin / bash 'den daha iyi?


212

Tercihen kullanmak için bu sitede ( Tercih edilen Bash shebang nedir? ) Öneriler de dahil olmak üzere bir dizi yerde gördüm . Hatta bir girişimci birey gördüğüm kullanılmasını öneriyorum oldu yanlış ve bash işlevselliği böyle yaparak kaybolacaktır.#!/usr/bin/env bash#!/bin/bash#!/bin/bash

Tüm bunlar, dolaşımdaki her sürücünün aslında tek bir ana sürücünün bir klonu olduğu sıkı kontrollü bir test ortamında bash kullanıyorum. Taşınabilirlik argümanını anlıyorum, ancak benim durumumda geçerli olmayabilir. #!/usr/bin/env bashAlternatifleri tercih etmek için başka bir neden var mı ve taşınabilirliğin bir endişe olduğunu varsaymak, onu kullanmanın işlevselliği bozması için herhangi bir neden var mı?


7
Mutlaka daha iyi değil. Bkz bu soruyu ve benim cevap unix.stackexchange.com üzerinde. (Bunu bir kopya olarak kapatmak için oy vereceğim, ancak bunu siteler arasında yapabileceğinizi düşünmüyorum.)
Keith Thompson

2
@ Zigg cevabı yanı sıra, envyer olmayabilir /usr/bin. Shebang yorum IMHO tamamen kötü bir fikirdir. Varsayılan kod yorumcunuz gizli yorumları ele almıyorsa, bu sadece bir yorumdur. Bununla birlikte, komut dosyası yorumlayıcısının shebang yorumlarını işleyebileceğini ve bash yolunu biliyorsanız, yol çok uzun (olası) olmadığı sürece mutlak yolunu kullanarak çağırmamak için bir neden yoktur veya komut dosyasını muhtemelen taşıyabilirsiniz. / bin içinde bash bulunmayan bir sisteme. Daha sonra, daha önce bahsettiğim uyarılar taşınabilirlik içerdiği için bu durumda geçerlidir.

1
@ KeithThompson, bağlantı için teşekkürler. Belki de soruyu göndermeden önce bir cevap arayışım biraz dardı. Bütün bunlardan alıp götürmem: (1) linux / unix / posix / etc ... gridir ve (2) kesinlikle doğru cevaba sahip olduğunu iddia eden herkesin kendi senaryosu için kesinlikle doğru cevabı vardır.
spugm1r3

3
POSIX / Unix'teki birçok şeyin davranışı iyi tanımlanmıştır. Mekanlar her zaman çok net değil. Bazı şeyler var olmak zorunda /etcya da /bin/sh. bashUnix benzeri sistemlerin çoğu için bir eklentidir. Sadece Linux'ta olduğu bashgaranti edilen /binve büyük olasılıkla olarak bağlantılı olduğu Linux'tur /bin/sh. Linux birçok insan için modern fiili Unix haline geldiği için Linux dışındaki sistemlerin var olabileceği unutuldu. Aşağıdaki kendi cevabımda Linux dedim çünkü dedin bash. Birlikte çalıştığım BSD kutularının birçoğu yüklü bile değildi.
Sean Perry

2
@Keith - Bash söz konusu olduğunda (diğer sorularda Python'un aksine) ... OpenBSD'de bir /bin/bash. Bash varsayılan olarak kurulmaz. Eğer istersen, zorundasın pkg install bash. Kurulduktan sonra adresinde bulunur /usr/local/bin/bash. /bin/bashOpenBSD'de yüklü hiçbir şey yok . Bir #!/bin/bashhata irade hatası ve #!/usr/bin/env bashbaşarılı olacak.
jww

Yanıtlar:


229

#!/usr/bin/envaramalar PATHiçin bash, ve bashher zaman değil /binözellikle Linux olmayan sistemlerde,. Örneğin, OpenBSD sistemimde, /usr/local/binisteğe bağlı bir paket olarak kurulduğundan beri.

Kesinlikle değilseniz emin basholduğunu /binve her zaman olacaktır, hiçbir zarar sizin doğrudan koyarak içinde var shebang-ama komut dosyaları ve programlar tüm başlangıçta sahip oldukları inanıyoruz ötesinde hayat var çünkü buna karşı öneriyoruz.


29
envkonum ne olacak ? POSIX zorlamaz.
Julio Guerra

1
@JulioGuerra Posta işlemek için /usr/lib/sendmail(veya daha yakın zamanda /usr/sbin/sendmail) bir ikili dosyaya sahip olmak gibi , Unix benzeri bir sistemin sahip /usr/bin/envolması da en iyisidir çünkü env shebang çok yaygın bir uygulamadır. Bu fiili standart bir arayüzdür.
zigg

8
@zigg Bu kadar UN * X ... <-: Yani, standart bir konuma sahip olmak en iyi çıkarları için env, ama bir şekilde (sadece yumuşak bir bağlantı olabilir) standart bir konuma sahip olmamak bash. Bahsetmiyorum, neden hashbang sadece kabul etmiyor #!bashve PATHyerine tam olarak aynı şeyi yapıyoruz env. Çaylaklar için yeterince kafa karıştırıcı değil sanırım.
ddekany

1
@ VikioGuerra Vikipedi göre doğru: "garantili" değil. Bunun yerine "daha muhtemel" görünüyor. Wikipedia This mostly works because the path /usr/bin/env is commonly used for the env utilityburada en.wikipedia.org/wiki/Shebang_(Unix) diyor - envTüm sistemlerde "muhtemelen" olmaktan emin olmalıyız .
Xavi Montero

2
@XaviMontero: Bulunduğum yerde env, içinde /binolmayan bir sistem kullandım /usr/bin(hangisinden emin değilim, muhtemelen SunOS 4). Bu günlerde /usr/bin/env, sadece #!/usr/bin/envhack'in popülaritesi nedeniyle mevcut olacak .
Keith Thompson

39

Standart bash konumu /binve tüm sistemlerde bunun doğru olduğundan şüpheleniyorum. Ancak, bu bash versiyonunu beğenmezseniz ne olur? Örneğin, bash 4.2 kullanmak istiyorum, ancak Mac'imdeki bash 3.2.5'te.

Bash'ı yeniden yüklemeyi deneyebilirim /binama bu kötü bir fikir olabilir. İşletim sistemimi güncellersem üzerine yazılır.

Ancak, bash'ı kurabilir /usr/local/bin/bashve PATH'ımı şu şekilde ayarlayabilirim:

PATH="/usr/local/bin:/bin:/usr/bin:$HOME/bin"

Şimdi, eğer belirtirsem bash, eski kıvrımlı olanı /bin/bashdeğil, daha parlak olanı alırım /usr/local/bin. Güzel!

Kabuk scriptlerim dışında bu !# /bin/bashmesele var. Bu nedenle, kabuk komut dosyalarımı çalıştırdığımda, ilişkilendirilebilir dizileri bile olmayan eski ve berbat bash sürümünü alıyorum.

Bunu kullanarak /usr/bin/env bashPATH'ımda bulunan bash sürümünü kullanacağım. PATH'ımı kurarsam, /usr/local/bin/bashyürütülürse, komut dosyalarımın kullanacağı bash budur.

Bunu bash ile görmek nadirdir, ancak Perl ve Python ile çok daha yaygındır:

  • İstikrara odaklanan bazı Unix / Linux sürümleri , bu iki kodlama dilinin yayınlanmasıyla bazen geride kalmaktadır. Çok uzun zaman önce, RHEL'in Perl'i 5.8.8'di - Perl'in sekiz yaşında bir versiyonu! Birisi daha modern özellikler kullanmak isterse, kendi sürümünüzü yüklemeniz gerekiyordu.
  • Perlbrew ve Pythonbrew gibi programlar, bu dillerin birden fazla sürümünü kurmanıza izin verir. Bunlar, istediğiniz sürümü almak için PATH'inizi manipüle eden komut dosyalarına bağlıdır. Yolu kodlamak zor benim senaryo altında çalıştıramam anlamına gelir demleme .
  • Perl ve Python'un çoğu Unix sisteminde yer alan standart paketler o kadar uzun zaman önce değildi (tamam, uzun zaman önceydi). Bu, bu iki programın nereye kurulduğunu bilmediğiniz anlamına geliyordu. Altında mıydı /bin? /usr/bin? /opt/bin? Kim bilir? Kullanmak #! /usr/bin/env perldemek zorunda değildim demekti.

Ve Şimdi Neden Kullanmamalısınız #! /usr/bin/env bash

Patikada yol kodlandığında, bu tercümanla koşmam gerekiyor. Böylece, #! /bin/bashbeni varsayılan kurulu bash sürümünü kullanmaya zorlar. Bash özellikleri çok kararlı olduğundan (Python 3.x altında bir Python betiğinin 2.x sürümünü çalıştırmayı deneyin), belirli BASH betiğimin çalışmaması pek olası değildir ve bash betiğimin muhtemelen bu sistem ve diğer sistemler tarafından kullanılması , standart olmayan bir bash sürümü kullanmanın istenmeyen etkileri olabilir. Muhtemelen bash'ın kararlı standart versiyonunun benim kabuk betiğimle kullanıldığından emin olmak istiyorum. Böylece, muhtemelen zor benim shebang yolu kodlamak istiyorum.


5
Bu doğru değil: "bash'ın standart konumu / bin," (bir standartlar belgesini gösteremezseniz), çoğu Linux dağıtımında ve macos'taki "olağan" konum olması belki de daha doğrudur, ancak genel olarak unix sistemlerinde standarttır (ve özellikle * bsds'ın çoğunda konum değildir).
tesch1

13

Çağırmak bashiçin biraz fazlalık. bash~ / Bin içinde kendi gibi birden fazla ikili program yoksa, aynı zamanda kodunuzun doğru şeylere sahip $ PATH'a bağlı olduğu anlamına gelmez.

Yine de böyle şeyler için kullanışlıdır python. Alternatiflere yol açan sargı komut dosyaları ve ortamlar vardırpython ikili dosyaların kullanılmasına .

Ama gerçekten istediğiniz ikili olduğundan emin olduğunuz sürece, ikilinin tam yolunu kullanarak hiçbir şey kaybolmaz.


İçin spot on python. pythonBulunan yerlerin sayısını kaybettim 😀
zigg

2
/usr/bin/envÖzellikle virtualenv kullanıyorsanız, Python için daha yararlı olduğu kabul edildi .
Dennis

10

/binSadece birkaçını belirtmek için Bash , FreeBSD ve OpenBSD içermeyen birçok sistem var . Komut dosyanız birçok farklı Unices'e taşınabilirse, #!/usr/bin/env bashbunun yerine kullanmak isteyebilirsiniz #!/bin/bash.

Bunun için geçerli olmadığını unutmayın sh; Bourne uyumlu komut dosyaları için ben münhasıran kullanma #!/bin/shı vardır varlığına hemen hemen her Unix düşünüyorum beri shiçinde /bin.


Ubuntu 18.04 dir'de /bingörüyorum sh -> dash. Sembolik olarak bağlantılı dash, Ubuntu'nun Debian doğasını ortaya koyuyor. : O tüm bireysel tercihi aşağı kaynar gerçekleştirmek için bu üç komut dizeleri çalıştırın which bashsonra which shsonra which dash.
noobninja

0

Ben bashsistemde mevcut tüm kontrol etmek için aşağıdaki gibi bir komut dosyası ana programı sarma tercih ederim . Kullandığı sürüm üzerinde daha fazla kontrole sahip olmak daha iyidir.

#! /usr/bin/env bash

# This script just chooses the appropriate bash
# installed in system and executes testcode.main

readonly DESIRED_VERSION="5"

declare all_bash_installed_on_this_system
declare bash

if [ "${BASH_VERSINFO}" -ne "${DESIRED_VERSION}" ]
then
    found=0

    all_bash_installed_on_this_system="$(\
        awk -F'/' '$NF == "bash"{print}' "/etc/shells"\
        )"

    for bash in $all_bash_installed_on_this_system
    do
        versinfo="$( $bash -c 'echo ${BASH_VERSINFO}' )"
        [ "${versinfo}" -eq "${DESIRED_VERSION}" ] && { found=1 ; break;}
    done
    if [ "${found}" -ne 1 ]
    then
        echo "${DESIRED_VERSION} not available"
        exit 1
    fi
fi

$bash main_program "$@"

0
 #!/usr/bin/env bash

sistem ortam değişkeninizden bash yürütülebilir yolunu bulduğu için kesinlikle daha iyidir.

Linux kabuğunuza gidin ve yazın

env

Tüm ortam değişkenlerinizi basacaktır.

Kabuk betiğinize gidin ve yazın

echo $BASH

Komut dosyanızda doğru shebang yolunuzu oluşturmak için kullanmanız gereken bash yolunuzu (ortam değişkeni listesine göre) yazdıracaktır.

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.