Ne zaman #! / Bin / bash ve ne zaman #! / Bin / sh kullanmalıyım?


99

Ne zaman #!/bin/bash daha uygun #!/bin/sh Bir kabuk komut dosyasında?


54
Kullanırken bash işlevler ve sözdizimi yerine sh fonksiyonlar ve sözdizimi.
Mokubai


3
Kimseye yardım ederse, bunu farkettim. vim vurgulayacak bash -isms senaryonuz varsa #!/bin/sh shebang. Sadece onu değiştirdim bash işler bash özelliklerine ihtiyaç duymaya başlayacak kadar kıllıysa.
SeldomNeedy

@SeldomNeedy Varsayılan olarak vurguladığı şeylerden bazıları, herhangi bir POSIX kabuğunda işe yarar. $(...) özellikle iğrençtir. Ayrıca, bazıları ince [ <(...) ve cmd >& file vurgulama hatası almazlar, örneğin, sadece ne de ne de ne demek istedikleri için özel bir vurgulama yapmazlar. g:is_bash ]
Random832

@ Random832, bu konuyla ilgili olarak son zamanlarda bazı faaliyetler olmuş gibi görünüyor. vim’in sorunu izleyen .
SeldomNeedy

Yanıtlar:


145

Kısacası:

  • Bir süperset uygulayan birkaç mermi vardır POSIX sh özelliği . Farklı sistemlerde /bin/sh kül, bash, çizgi, ksh, zsh, & c'ye bir bağlantı olabilir. (Her zaman olsa sh sh uyumlu olacak - asla csh veya balık.)

  • Yaptığın sürece sh yalnızca özellikleri kullanabilirsiniz, (ve muhtemelen kullanmalısınız) #!/bin/sh ve hangi kabuk olursa olsun, senaryo düzgün çalışmalıdır.

  • Basa özgü özellikleri kullanmaya başlarsanız (örneğin, diziler), özellikle bash istemeniz gerekir, çünkü /bin/sh çoktan bash çağırdı sizin sistem açık olmayabilir herkesin sistemi ve komut dosyası orada çalışmaz. (Tabii aynı zsh ve ksh için de geçerlidir.) shellcheck temelleri tanımlamak için.

  • Komut dosyası yalnızca kişisel kullanım için olsa bile, bazı işletim sistemlerinin değiştiğini fark edebilirsiniz. /bin/sh yükseltme sırasında - örneğin Debian'da bash olarak kullanılırdı, ancak daha sonra çok az bir çizgi ile değiştirildi. Temelleri kullanan, ancak olan komut dosyaları #!/bin/sh aniden kırdı.

Ancak:

  • Üstelik #!/bin/bash çok doğru değil. Farklı sistemlerde bash yaşayabilir /usr/bin veya /usr/pkg/bin veya /usr/local/bin.

  • Daha güvenilir bir seçenek #!/usr/bin/env bash, $ PATH kullanır. (Rağmen env aracın kendisi de kesinlikle garanti edilmez, /usr/bin/env hala daha fazla sistemde çalışıyor /bin/bash yapar.)


10
Güzel cevap Bunu CW yapmak mı istediniz?
Mokubai

3
Bash çalıştırılırsa sadece bir açıklama /bin/sh sonra taklit etmeye çalışacak sh özellikler (bkz. man sayfa ), bash özel özelliklerinin bu modda mevcut olduğundan emin değilsiniz. env aracı bir posix aracıdır çoğu dağıtımda bulunmalı, ancak bazılarının posix'e saygı gösteremeyeceğinden emin değilim.
Brice

8
Hayır, aslında POSIX özellikle belirtiyor içinde olduğu varsayılamaz /bin: " Başvurular, kabuktaki standart PATH'in ya / bin / sh ya da / usr / bin / sh olarak kabul edilemeyeceğini ve getconf PATH tarafından döndürülen PATH'in sorgulanmasıyla belirlenerek, iade edilen yol adının mutlak olmasını sağlamak gerektiğini belirtmelidir yol adı ve bir kabuk yerleşik değil "Ayrıca bakınız bu soru ve özellikle bu cevap .
terdon

12
Hmm, peki, demek ki POSIX aslında sahip olmak için taşınabilir bir yol tanımlamıyor. #! senaryolar işe yarıyor mu?
grawity

4
POSIX sh değil Bourne: Bourne'un doğrudan soyundan daha erken bir ksh türevidir. Onları ayırt etmek kolaydır: echo foo ^ cat yayar foo ^ cat POSIX sh’de yalnızca foo Bourne'da (olarak) ^ orada bir boru karakteridir).
Charles Duffy

18

Komut dosyanızı geliştirmek ve hata ayıklamak için gerçekten kullandığınız kabuğa karşılık gelen shebang'ı kullanın. Yani eğer giriş kabuğunuz bashkomut dosyasını terminalinizde yürütülebilir olarak çalıştırıyorsanız, #!/bin/bash. Bunu sadece dizileri kullanmadığınızdan (ya da her neyse bash (bildiğiniz özellik), istediğiniz kabuğu seçmenizde güvenlidir. Kabuklar arasında birçok ince fark vardır ( echo, uygun sınamalar olmadan keşfedilemeyen işlevler, döngüler, onu adlandırın).

Şunu düşünün: eğer ayrılırsanız #!/bin/bash ve kullanıcılarınız buna sahip değil, açık bir hata mesajı görecekler

Error: /bin/bash not found

Çoğu kullanıcı uygun paketi yükleyerek bunu bir dakikadan az bir sürede düzeltebilir. Diğer taraftan, eğer shebang'ı değiştirirseniz #!/bin/sh ve bir sistemde test edin /bin/sh bir bağlantıdır /bin/bash, sahip olmayan kullanıcılarınız bash başı dertte olacak. Muhtemelen aşağıdaki gibi şifreli bir hata mesajı göreceklerdir:

Error in script.sh line 123: error parsing token xyz

Bunun düzeltilmesi saatler alabilir ve hangi kabuğun kullanılması gerektiği hakkında hiçbir ipucu olmayacaktır.

Shebang'da farklı bir kabuk kullanmak istemeniz için pek çok neden yok. Bunun bir nedeni, kullandığınız kabuğun yaygın olmamasıdır. Bir diğeri ile performans kazanmak. sh Bu, bazı sistemlerde çok daha hızlıdır, VE betiğiniz performans darboğazı olacaktır. Bu durumda, betiğinizi hedef kabuk ile iyice test edin, ardından shebang'ı değiştirin.


@Hastur Yorumunuzu alamadım. Shebang, betiği çalıştırmak için hangi kabuğun kullanılacağını kesinlikle tanımlayacaktır, sence cevabım başka türlü mı ima ediyor?
Dmitry Grigoryev

1
Unut gitsin. Kısmı yanlış anladım "neden kullanmak istersin" ...
Hastur

6

Sadece hiç kullanmalısın #! /bin/sh.

Hiç bir kabuk betiğinde bash (veya zsh, ya da balık, ya da ...) eklentilerini kullanmamalısınız.

Sadece birlikte çalışan kabuk scriptleri yazmalısınız. herhangi Kabuk dilinin uygulanması (kabuğun kendisi ile birlikte gelen tüm "yardımcı program" programları dahil). Bu günlerde yapabilirsin muhtemelen almak POSIX.1-2001 ( değil -2008) kabuğun ve araçların neler yapabildiğine dair yetkili bir makam olarak, ancak bir gün senaryosunu, kabukları ve yardımcı programları 1992'de dondurulmuş olan eski bir sisteme (örneğin, Solaris veya AIX) aktarmak için çağrılabileceğinizi unutmayın.

Ne, cidden mi?

Evet cidden.

İşte bir şey var: Shell bir korkunç Programlama dili. Bunun için gidebileceği tek şey /bin/sh tek ve tek script tercümanı olan her Unix kurulumunun olması garantilidir.

İşte başka bir şey: çekirdek Perl 5 tercüman bazı yineleme ( /usr/bin/perl ) Daha rastgele seçilen bir Unix kurulumunda mevcut olması muhtemeldir. (/(usr|opt)(/(local|sfw|pkg)?)?/bin/bash olduğunu. Diğer iyi betik dilleri (Python, Ruby, node.js, vb. - Kabuk ile karşılaştırıldığında bu kategoriye PHP ve Tcl bile dahil edeceğim) kabaca bash ve diğer genişletilmiş kabukları kadar mevcuttur.

Bu nedenle, bir bash betiği yazma seçeneğiniz varsa, Bunun yerine korkunç olmayan bir programlama dili kullanma seçeneğiniz vardır.

Şimdi, basit kabuk komut dosyaları, bir cron işinden veya başka bir şeyden bir dizideki birkaç programı çalıştıran türden, onları kabuk komut dosyası olarak bırakmanın yanlış bir tarafı yoktur. Ancak basit kabuk komut dizileri veya işlevler gerekmez veya [[ Üstelik. Ve sadece yazmalısın karmaşık başka bir seçeneğiniz olmadığında kabuk komut dosyaları. Örneğin, Autoconf komut dosyaları hala düzgün şekilde kabuk komut dosyalarıdır. Fakat bu senaryoların üzerinde durulması gerekiyor. her enkarnasyonu /bin/sh Bu, yapılandırılmakta olan programla ilgilidir. ve bu, herhangi bir uzantı kullanamayacakları anlamına gelir. Muhtemelen bugünlerde eski patentli Unix'lerle ilgilenmek zorunda değilsiniz, ama muhtemelen meli bazıları kurulmayan mevcut açık kaynaklı BSD'lere özen göstermek bash Varsayılan olarak ve yalnızca en az kabuk veren katıştırılmış ortamlar busybox.

Sonuç olarak, kendini bulduğun an eksik taşınabilir kabuk dilinde bulunmayan bir özellik, komut dosyasının bir kabuk komut dosyası olarak kalmayacak kadar karmaşık hale geldiğinin bir işaretidir. Bunun yerine daha iyi bir dilde yeniden yazın.


3
Üzgünüm ama bu biraz saçma. Evet, i) dağıtılacak ve ii) farklı ortamlara yazacak bir şey yazıyorsanız, temel konuya bağlı kalmalısınız sh. Bununla birlikte, yapmanız gerektiğini bildirmekten çok uzak asla diğer mermileri kullan. Her gün binlerce (muhtemelen çok daha fazla) senaryo yazılmaktadır ve bunların büyük çoğunluğu sadece bir makinede çalışacaktır. Tavsiyeniz üretim kodunda anlamlıdır, ancak çoğu komut dosyasının yazıldığı günlük "sysdaminy" işleri için uygun değildir. Senaryomun sadece benim tarafımdan ve bir Linux makinede kullanılacağını biliyorsam, bash iyidir.
terdon

1
@ terdon Mesele şu ki, bir bash betiği yazma seçeneğiniz varsa, o zaman bir perl (veya her neyse) betiği yazma seçeneğiniz de vardır ve bu her zaman daha iyi bir seçim.
zwol

@ terdon Cevap kesinlikle saçma değil, yorumunuz bunun yerine saf. Shell scriptleri, Perl ile karşılaştırıldıklarında hata ayıklamak için korkunçtur; bunlardan biri grafiksel hata ayıklama ve diğer tüm IDE'leri kolayca kullanabilir. Ek olarak, her gün küçük bir şeyin yapılması için yazılan senaryoların çoğu tekrar tekrar değiştirilmeye ve değiştirilmeye, büyümeye, meslektaşlara veya ağa vb. Örnek olarak kopyalanır.
Thorsten Schöning

@ ThorstenSchöning dedim biraz saçma. Eğer bu olsaydı Unix ve amp; Linux ya da Yığın Taşması Katılıyorum bile. Genel en iyi uygulamalardan ya da profesyonel programcılardan bahsediyorsak, tabii ki temel POSIX sh'e bağlı kalmak en iyisidir. Ancak, bu Süper kullanıcı , son kullanıcıları hedefleyen ve insanlara kabuk betiği yazarken asla bash veya zsh kullanmamalarını söyleyen bir site, bence aşırıdır.
terdon

@ terdon Bu aslında Daha önemli, benim görüşüme göre, son kullanıcıları karmaşık kabuk komut dosyaları yazmaktan caydırmak. Profesyoneller ortalama olarak daha yüksek bir beceri seviyesine sahiptir (bu nedenle karmaşık kabuk komut dosyası yazmanın tuzaklarıyla başa çıkma olasılıkları daha yüksektir), hangi ortamlara taşınabilir olmaları gerektiği ve pes etmemeleri için para vermeleri gerektiği kesin olarak bilmeli hayal kırıklığı içinde.
zwol

4

Genel olarak, zaman işlevsellikten daha önemliyse, daha hızlı olan kabuğu kullanacaksınız. sh genellikle çizgi şeklinde takma ad alır ve her bir (nano) saniyenin önemli olduğu kök işlemlerinin cron görevleri veya toplu işlemleri için kullanılır.


2
Dosya sisteminden fazladan bir kabuk tercümanı yüklemek, böyle bir avantajı ortadan kaldırabilir ve nanosaniyelerin (gerçek bir makine çevrimi ile aynı büyüklükte olan) sayım yaptığı her şey, C ve assembly dili programcılarının alanıdır.
rackandboneman

Nanosaniyeler, yalnızca milyarlarca işiniz varsa cron işlerinde fark yaratır ve cron zaten bu kadar çok iş yapamaz.
Dmitry Grigoryev

1
Mckenzm biraz abartmış olsa bile, daha fazla performansa sahip olmanın daha iyi olduğunu inkar etmek mümkün değil! "Nano" kısmına takılma. (Gerçek zamanlı bir sistemde bir iç döngü olmadıkça Nanosaniye C bile sayılmaz!)
jpaugh

1
@jpaugh Belirli işlemlerin en azından belirli bir süre alacağını varsayan bir eski sistemle çalışmazsanız. Olur!
JAB

3

Daha da kısa olmak için kullanın sh çoğu sistemde taşınabilirlik en önemli ve bash eğer bash sürümü destekliyorsa, diziler gibi belirli özelliklerini kullanmak istiyorsanız.


1
  • sh (çoğu durumda), özellikle gerekliyse bash (veya ksh veya her neyse)

En güvenli yol. Sert kodlandığında / usr / bin / olur shellOfChoice fakat yeni bir kural her zaman şimdi kullanmaya çalışıyorum - bir PATH değişikliği ile 'varsayılan konumlar' değişebilir:

#! / usr / bin / env sh veya
#! / usr / bin / env bash
veya örneğin perl betikleri
#! / usr / bin / env perl -w

Elbette, bir betiğin ASLA otomatik olarak yeni bir PATH almaması için bir nedeniniz olduğunda, onu zor kodlamaya devam edin - ve / usr / bin / bir şeyler kullanmak için en muhtemel yol olmalıdı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.