mevcut kabuğu belirlemenin checkbashism uyumlu yöntemi


18

Benim .profile, Bash ile ilgili takma adların ve fonksiyonların sadece giriş kabuğu aslında Bash ise kaynaklı olduğundan emin olmak için aşağıdaki kodu kullanıyorum :

# If the current (login) shell is Bash, then
if [ "${BASH_VERSION:-}" ]; then
  # source ~/.bashrc if it exists.
  if [ -f "$HOME/.bashrc" ]; then
    . "$HOME/.bashrc"
  fi
fi

Şu anda kabuk yapılandırma dosyalarımı, komut dosyalarını ve işlevlerini sürüm denetimi altına alma sürecindeyim. Ben de son zamanlarda değiştirilmesi, örneğin Bash özgü özelliklerinden fayda görmeyen kabuk komut, gelen gündelik Bashisms kaldırma işlemini başlattık function funcname()ile funcname().

Kabuk dosyaları havuzum için, yanlışlıkla Bash'e özel sözdizimini tanıtmamamı sağlamak için , Debian'ın devscripts paketindeki yardımcı programı havuzdaki her dosyada çalıştıran bir ön işleme kanca yapılandırdım . Ancak, bu benim için bir hata oluşturur :checkbashismssh.profile

possible bashism in .profile line 51 ($BASH_SOMETHING):
if [ "${BASH_VERSION:-}" ]; then

Hangi merminin çalıştığını kontrol etmenin bir uyarı olup olmadığını kontrol etmenin bir yolu olup olmadığını merak ediyordum checkbashisms.

POSIX tarafından listelenen kabukla ilgili değişkenlerin listesini , bunlardan birinin geçerli kabuğu göstermek için kullanılabileceğini umarak kontrol ettim . Ayrıca etkileşimli bir Dash kabuğunda ayarlanan değişkenlere de baktım ancak yine uygun bir aday bulamadım.

Şu anda, .profiletarafından işlenmekten dışlandım checkbashisms; küçük bir dosya olduğundan manuel olarak kontrol etmek zor değildir. Ancak, sorunu araştırdıktan sonra, hangi kabuğun çalıştığını belirlemek için POSIX uyumlu bir yöntem olup olmadığını bilmek istiyorum (veya en azından checkbashismsbaşarısızlığa neden olmayan bir yol ).


Daha fazla arka plan / açıklama

Kabuk yapılandırma dosyalarımı sürüm denetimi altına almamın nedenlerinden biri, ortamımı şu anda düzenli olarak oturum açtığım tüm sistemlerde yapılandırmaktır: Cygwin, Ubuntu ve CentOS (hem 5 hem de 7, Active Directory'yi kullanıcı için kullanma) doğrulama). Çoğunlukla X Windows / masaüstü ortamları ve uzak ana bilgisayarlar için SSH ile oturum açıyorum. Bununla birlikte, bunun gelecekteki kanıt olmasını ve sistem bağımlılıklarına ve diğer araçlara mümkün olan en az güven duymasını istiyorum.

checkbashismsKabuğumla ilgili dosyalarımın sözdizimi için basit, otomatik bir sağlık kontrolü olarak kullanıyorum . Mükemmel bir araç değil, örneğin, command -vsenaryolarımın kullanımından şikayet etmemesi için zaten bir yama uyguladım . Araştırma yaparken, programın asıl amacının, anladığım kadarıyla 2008'den (veya 2013 revizyonundan) POSIX 2004'e dayanan Debian politikasına uymak olduğunu öğrendim.


Yaptığınız şey, POSIX uyumlu ortamlarda bütün mesele farklı bir şekilde çalışmak olduğunda olabildiğince POSIX uyumludur. Sığır etiniz checkbashism ile.
Gilles 'SO

Bu arada, yapılandırmamın taşınabilirliğini kontrol etmek için hiçbir zaman checkbashism kullanmadım. Farklı sistemlerde kullanarak kontrol ediyorum.
Gilles 'SO

2
Ve bu arada, burada yaptığınız belirli bir şey için, .bash_profilehem .profileve hem de (koşullu olarak) kaynakları yazın .bashrc.
Gilles 'SO

@Gilles görüşleriniz için teşekkür ederiz. Bu konu için çok zarif bir çözüm.
Anthony G - Monica

Yanıtlar:


16

Sizin

# If the current (login) shell is Bash, then
if [ "${BASH_VERSION:-}" ]; then
  # source ~/.bashrc if it exists.
  if [ -f "$HOME/.bashrc" ]; then
    . "$HOME/.bashrc"
  fi
fi

kodu tamamen POSIX uyumludur ve şu anda çalıştığınızı kontrol etmenin en iyi yoludur bash. Elbette $BASH_VERSIONdeğişken bash'a özgüdür, ancak özellikle bu yüzden kullanıyorsunuz! Koştuğunuzu kontrol etmek için bash!

Veya olarak çağrılırsa $BASH_VERSIONayarlanacağını unutmayın . Çalıştığınızı iddia ettikten sonra , kabuğun çağrıldığının bir göstergesi olarak kullanabilirsiniz (bu seçenek, POSIXLY_CORRECT ortamdayken veya ortamla veya SHELLOPTS = posix ile çağrıldığında da ayarlanır . Ancak tüm bu durumlarda, sanki denir gibi davranacaktır .bashbashshbash[ -o posix ]shbash-o posixbashsh


Başka değişken, yerine kullanabilirsiniz $BASH_VERSIONve o checkbashismgeçti sürece şikayet görünmüyor -xseçenektir $BASH. Bu aynı zamanda özeldir, bashböylece çalışıp çalışmadığınızı belirlemek için de kullanabilmeniz gerekir bash.


Ayrıca bunun gerçekten uygun bir kullanımı olmadığını da iddia ediyorum checkbashisms. checkbashismstaşınabilir shkomut dosyaları yazmanıza yardımcı olacak bir araçtır ( shDebian ilkesindeki belirtime göre, POSIX'in bir üst kümesidir), shbir simge bağlantısı olan sistemlerde komut dosyaları yazan kişilerin tanıdığı standart olmayan sözdiziminin belirlenmesine yardımcı olur bash.

A .profile, çoğu POSIX uyumlu olmayan farklı kabuklar tarafından yorumlanır. Genellikle, kullanmadığınız shgiriş kabuğu olarak değil kabukları gibi zsh, fishya da bashdaha gelişmiş interaktif özellikleri ile.

bashve zsholarak adlandırılmadığında shve ilgili profil oturum dosyası ( .bash_profile, .zprofile) POSIX uyumlu (özellikle zsh) değil, yine de okunuyorsa .profile.

Bu, istediğiniz POSIX sözdizimi değil, POSIX .profileile uyumlu bir sözdizimidir (for sh) bashve zshbu kabukları kullanacaksanız (Bourne kabuğunun da okuduğu gibi Bourne bile, .profileancak Linux tabanlı sistemlerde yaygın olarak bulunmazsa) ).

checkbashismskesinlikle bashisms bulmanıza yardımcı olur, ancak zshveya ile uyumlu olmayan POSIX sözdizimini göstermeyebilir bash.

Burada, bash-spesifik kod kullanmak istiyorsanız ( etkileşimli giriş kabuklarında bashokunmayan bu hatanın etrafındaki çalışma gibi ~/.bashrc), ~/.bash_profilebunu yapmak için daha iyi bir yaklaşım olacaktır ( ~/.profileortak oturumunuzu nereye koyduğunuzdan önce veya sonra alıştırmalarını).


checkbashismsKullanılan değişken nedeniyle bu geçmiyor .
Thomas Dickey

2
@ThomasDickey, evet ama bu checkbashism raporunun göz ardı edilmesi gereken bir durum. Şimdiye kadar verilen diğer tüm çözümler oldukça kötüdür.
Stéphane Chazelas

@ StéphaneChazelas Diğer tüm çözümlerin daha kötü olduğunu söylüyorsunuz. $0Bu özel durum için kullanmanın nesi yanlış olurdu ?
Anthony G - Monica

2
@AnthonyGeoghegan Bu, olarak adlandırılan bash shve olarak adlandırılan başka bir kabuk arasında ayrım yapmaz sh.
Gilles 'SO

Ayrıca, dashbaşka bir bash olmayan kabuk yanlış çağrılırsa, yanlış bir pozitif verir argv[0] == "bash", bu da olası değilse tamamen yasaldır.
Kevin

17

Genellikle $0bu amaç için kullanılır. Bağladığınız sitede:

0
   (Zero.) Expands to the name of the shell or shell script.

Çok basit! Ben $0bir kabuk komut dosyası adı için kullanmaya alışkın oldum , ben de geçerli kabuk da başvurabileceğini unuttum temiz. Teşekkürler!
Anthony G - Monica

1
Her zaman olduğu gibi, bu kurala tüm iyi davranan programlar tarafından saygı duyulur, ancak kötü niyetli bir program execaileden çeşitli sistem çağrıları kullanarak sizinle uğraşabilir, çünkü çağrı programının ikili programı tanımlamak için dizeden ayrı olarak çalıştırılmasını tanımasına izin verir 0.
dmckee

Bu .profile :) sevimli için işe yarıyor
Rob

5

Genellikle SHELL ortam değişkeni size varsayılan kabuğu bildirir. .Bashrc dosyasını el ile kaynaklamanız gerekmez (doğru değil bkz. Güncelleme feryat), bash bunu otomatik olarak yapmalıdır, sadece $ HOME dizininde olduğundan emin olun.

Diğer seçenek şunun gibi bir şey yapmaktır:

 ps -o cmd= $$

geçerli işlemin komutunu (bağımsız değişkenler olmadan, = değeri olmayan sütun başlıkları görüntülemez) söyleyecektir. Örnek çıktı:

 $ps -o cmd= $$
 bash
 $sh
 $ps -o cmd= $$
 sh

GÜNCELLEME:

Ben düzeltilmiş duruyorum! :)

.Bashrc her zaman aşağıdaki yorumlarda belirtildiği gibi kaynaklanmamaktadır ve /programming/415403/whats-the-difference-between-bashrc-bash-profile-and-environment

Böylece .bashrc'nizi .bash_profile dosyasına taşıyabilir ve testi yapmak zorunda kalmadan çalışıp çalışmadığını görebilirsiniz. Değilse yukarıdaki teste sahipsiniz.


1
.bashrcaslında bir giriş kabuğu tarafından değil, .profile(varsa) veya .bash_profilevardır. SHELLPOSIX tarafından belirtilmez ve ne yazık ki, cmdbiçimlendirme seçeneği de yoktur ps.
Anthony G - Monica

1
Kullanacağım şey bu, ancak kötü niyetli manipülasyona da tabi.
dmckee

İken Not ps -o cmd= $$hemen hemen her yerde çalışmalı, $SHELLdeğişken tamamen alakasız. Bu, kullanıcının varsayılan kabuğudur ve şu anda hangi kabuğun çalıştırıldığını veya hangi kabuğun bir kabuk komut dosyasını çalıştırdığını etkilemez.
terdon

2
Gerçekten değil, hayır. ~/.profilegiriş kabukları olarak başlatıldığında birçok kabuk okunacaktır . Örneğin, $SHELLolabilirsiniz cshve koşarsınız bash -l. Bu, bash'ı bir giriş kabuğu olarak başlatacaktır, bu yüzden okuyacaktır ~/.profile, ancak $SHELLyine de göstereceksiniz csh. Ayrıca, .profilebaşka bir komut dosyası tarafından açıkça kaynaklanmış olabilir. OP maksimum sağlamlık göstereceğinden, her türlü durum dikkate alınmalıdır. Her durumda, $SHELLşu anda çalışan kabuk hakkında yararlı bilgiler sağlamaz.
terdon

2
FWIW, ben de düzeltilmiş duruyorum - SHELLPOSIX tarafından belirtilmemesi hakkında : pubs.opengroup.org/onlinepubs/9699919799/basedefs/…
Anthony G - Monica

4

Soru, kullanıcının oturum açma kabuğunun yanı sıra geçerli kabuğu da uygun bir şekilde sorar checkbashisms. Bu kullanıcının oturum açtığı kabuk olması gerekiyorsa /etc/passwd, örneğin,

MY_UID=$(id -u)
MYSHELL=$(awk -F: '$3 == '$MY_UID'{ print $7; }' </etc/passwd )

Kullanıcılar, giriş yaptıktan sonra elbette yeni bir kabuk başlatabilirler. Elbette, biri bash diğeri değilse, bash ortam değişkenlerinin testleri yardımcı olmayabilir.

Bazıları getentsadece passwddosyadan ziyade kullanmak isteyebilir (ancak bu sorunun kapsamına girmez).

LDAP hakkındaki açıklamaya ve önerisine dayanarak logname, bu alternatif form kullanılabilir:

MY_NAME=$(logname)
MYSHELL=$(getent passwd | awk -F: '$1 ~ /^'$MY_NAME'$/ {print $7;}' )

Test ederken logname, girişinin yeniden yönlendirilmesini sevmediğini fark ettim (bu yüzden ifadeyi ayrıldım). Hızlı bir kontrol şovları getentbelirtilen platformlarda çalışmalıdır (orijinal soruda verilmelidir)


1
Kullanıcı veritabanının / etc / passwd (LDAP / NIS / mysql ... değil) içinde olduğunu ve her kullanıcı kimliği için yalnızca bir kullanıcı adı olduğunu varsayarsak. (ilk sütunu kontrol etmek daha iyi olur $(logname)).
Stéphane Chazelas

iirc, POSIX gerekli yardımcı programı tanımlamıyor (ya da cevabımda kullanacaktım). Kullanılabilir idveya kullanıcı tarafından değiştirilebilir bir değişkenin kullanılması farklı bir seçimdir.
Thomas Dickey

1
Söylediğimi $(logname)not et, değil $LOGNAME. Kullanıcı kimliği ve oturum açma kabuğunun her ikisi de oturum açmada kullanılan kullanıcı adından türetilir. Kullanıcı kimliği başına yalnızca bir kullanıcı adının bulunduğu sistemler dışında, kullanıcı kimliğinden oturum açma kabuğuna geri dönemezsiniz. Veya IOW, kullanıcı veritabanındaki birincil anahtar uid değil kullanıcı adıdır.
Stéphane Chazelas

Farklı bir bakış açısıyla gelen bir cevap için @ThomasDickey'e teşekkürler. Ancak, düşündüğümden biraz daha karmaşık ( jimmij ve Stéphane'nin cevapları gibi). Kabuk yapılandırma dosyalarımı sürüm denetimi altına almamın nedenlerinden biri, ortamımı şu anda düzenli olarak oturum açtığım tüm sistemlerde yapılandırmaktır: Cygwin, Ubuntu ve CentOS (hem 5 hem de 7, Active Directory'yi kullanıcı için kullanma) doğrulama). Bu nedenle, mantığı olabildiğince basit tutmayı tercih ederim.
Anthony G - Monica
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.