Bashrc'de [-n “$ PS1”] 'in amacı


10

Hangi amaca yapar [ -n "$PS1" ]içinde [ -n "$PS1" ] && source ~/.bash_profile;hizmet? Bu satır dahildir .bashrcbir dotfiles ait repo .

Yanıtlar:


20

Bu, kabuğun etkileşimli olup olmadığını kontrol eder. Bu durumda, yalnızca ~/.bash_profilekabuk etkileşimli olduğunda dosyanın kaynağı .

Bkz. "Bu Kabuk Etkileşimli mi?" belirli bir deyimden bahseden bash kılavuzunda. (Ayrıca, $-özel değişkenin ikarakteri içerip içermediğini test ederek kabuğun etkileşimli olup olmadığını kontrol etmenizi önerir , bu da bu soruna daha iyi bir yaklaşımdır.)


bash, kabuk etkileşimli ise en azından PS1 ve PS2'yi ayarlayamaz . Bunu kendiniz için, ( export PS1='abc$ '; bash -c 'echo "[$PS1]"' )sadece basan ile görebilirsiniz []. Herhangi bir durumda ... en azından bir deneyden aynı yapmaz zsh, görünüyor niyeti ait [ -n "$PS1" ]kabuk etkileşimli olup olmadığını kontrol etmektir.
filbranden

3
Bu bashetkileşimli olmayan (önceki yorumunda yazım hatası) bir hata IMO olduğunu unsets PS1, PS1 onu unsetting işi yok, bir bash özgü değişken değildir. Bunu yapan tek kabuk ( etkileşimli olmasa bile varsayılan bir değere yashayarlanmış olsa da PS1).
Stéphane Chazelas

1
Söz konusu kod bash'e özgü bir dosyada olduğundan, bu makul bir yanıt gibi görünüyor. Diğer cevaplar daha genel POSIX özellikleri veya diğer mermilerle ilgilidir. “Bunun amacı nedir?” Yanıtı verdiniz. geri kalanını uygun bir şekilde bir kenara bırakarak Sorunun amacı. Bash'in ne yaptığını bilmek iyi ve muhtemelen hedefe ulaşmak için daha iyi yollar.
Jeff Schaller

Daha güvenilir bir alternatif önerirse bu cevabı daha eksiksiz olarak değerlendiririm (diyelim ki [[ $- = *i* ]] && source ~/.bash_profile).
Charles Duffy

@CharlesDuffy Açıkçası çok fazla yanlış olduğunu düşünmüyorum [ -n "${PS1}" ], ancak yine de bash kılavuzunun $-kabuğun etkileşimli olup olmadığını kontrol etmeyi önerdiğini / önerdiğini vurgulamak için güncelledim , umarım cevabı geliştirirsiniz. Şerefe!
filbranden

19

Bu ne yapar

Bu, kabuğun etkileşimli olup olmadığını test etmenin yaygın bir yoludur. Sadece bash'da çalıştığını, diğer kabuklarla çalışmadığını unutmayın. Bu yüzden (aptalsa) .bashrcsorun değil, ama işe yaramaz .profile(sh tarafından okunur ve bash sh'ın olası uygulamalarından sadece biridir ve en yaygın olanı değildir).

Neden çalışıyor (sadece bash!)

Etkileşimli kabuk, kabuk değişkeniniPS1 varsayılan bilgi istemi dizesine ayarlar . Kabuk etkileşimli ise PS1, ayarlanır (kullanıcı .bashrconu kaldırmamışsa, bu henüz üstünde .bashrcolamaz ve yine de bunun aptalca bir şey olduğunu düşünebilirsiniz).

Tersi bash için geçerlidir: interaktif olmayan bash unset örnekleri PS1başladığında. Bu davranışın bash'a özgü olduğunu ve muhtemelen bir hata olduğunu unutmayın (neden olduğu bash -c '… do stuff with $var…'zaman işe yaramaz ?). Ancak 4.4'e (yazdığım en son sürüm) kadar olan tüm bash sürümleri bunu yapar.varPS1

Birçok sistem PS1çevreye ihracat yapar. Birçok farklı kabuklar kullanmak, çünkü kötü bir fikir PS1ama farklı bir sözdizimi ile (örneğin bash en istemi kaçar tamamen farklıdır zsh en istemi kaçar ). Ancak pratikte, bunun PS1ayarlandığını görmek kabuğun etkileşimli olduğuna dair güvenilir bir gösterge olmadığı kadar yaygındır . Kabuk PS1çevreden miras almış olabilir .

Neden burada (yanlış) kullanılıyor

.bashrcbash etkileşimli olduğunda başlangıçta okuyan dosyadır. Daha az bilinen bir gerçektir bash da okur olmasıdır .bashrcbir giriş kabuğu ve bash en buluşsal (üst ise bash kontrolleri bu uzak bir oturumda olduğu sonucuna rshdya sshd). Bu ikinci durumda, PS1henüz nokta dosyası çalışmadığından, ortam içinde ayarlanması pek olası değildir .

Ancak, kodun bu bilgileri kullanma şekli verimsizdir.

  • Kabuk etkileşimli bir kabuksa, .bash_profilebu kabukta çalışır . Ancak .bash_profilebir oturum açma zamanı betiğidir. Oturum başına yalnızca bir kez çalıştırılması amaçlanan bazı programları çalıştırabilir. Kullanıcının bu kabuğu çalıştırmadan önce kasıtlı olarak farklı bir değere ayarlamış olduğu bazı ortam değişkenlerini geçersiz kılabilir. .bash_profileGiriş yapmayan bir kabukta çalıştırmak yıkıcıdır.
  • Kabuk etkileşimli olmayan bir uzaktan oturum açma kabuğuysa yüklenmez .bash_profile. Ancak bu, yüklemenin .bash_profileyararlı olabileceği bir durumdur , çünkü etkileşimli olmayan bir giriş kabuğu otomatik olarak yüklenmez /etc/profileve ~/.profile.

İnsanların bunu yapmasının nedeni, GUI (çok yaygın bir durum) aracılığıyla giriş yapan ve ortam değişken ayarlarını .bash_profileyerine yerleştiren kullanıcılar içindir .profile. Çoğu GUI oturum açma mekanizması çağrılır, .profileancak çağrılmaz .bash_profile(okuma .bash_profile, oturum başlatma işleminin bir parçası olarak sh yerine çalıştırmayı gerektirir). Bu yapılandırmada, kullanıcı bir terminal açtığında, ortam değişkenlerini alırlar. Bununla birlikte, kullanıcı, çok yaygın bir karışıklık kaynağı olan GUI uygulamalarında ortam değişkenlerini alamayacaktır. Buradaki çözüm, ortam değişkenlerini ayarlamak .profileyerine kullanmaktır .bash_profile. Arasına bir köprü eklemek .bashrcve .bash_profileçözdüğünden daha fazla sorun yaratır.

Bunun yerine ne yapmalı

Geçerli kabuğun etkileşimli olup olmadığını test etmenin basit ve taşınabilir bir yolu vardır: seçeneğin -ietkin olup olmadığını test edin .

case $- in
  *i*) echo "This shell is interactive";;
  *) echo "This shell is not interactive";;
esac

Bu, yalnızca kabuk etkileşimli değilse, yani kodun tersi .bashrcolduğunda okumak .profileiçin yararlıdır ! Oku .profilebash bir (etkileşimli olmayan) giriş kabuğu ve etkileşimli bir kabuk varsa okumak yoksa.

if [[ $- != *i* && -r ~/.profile ]]; then . ~/.profile; fi

4
Bir kabuğun etkileşimli olup olmadığını test etmenin daha iyi bir yolunun [[ -o interactive ]](ksh, bash, zsh) veya case $- in (*i*) ...; esac(POSIX) olduğunu
belirtmek gerekir

2
Benim bash (sürüm 4.4.12) PS1etkileşimli olarak çalıştırılmazsa aslında ayarlanmamış görünüyor . Test etmek yeterince kolaydır: bash başlangıç ​​dosyalarınızda set değerini yazdırırken ( PS1=cuckoo bash -c '[ -n "${PS1}" ] && echo "PS1=[${PS1}]"'hiçbir şey "guguk kuşu" yazmaz). PS1=cuckoo bash -i -c '[ -n "${PS1}" ] && echo "PS1=[${PS1}]"'$PS1
FooF

1
Stéphane Chazelas @: POSIX gerektirmez $-içeren iinteraktif bir kabuk ile.
schily

1
Bosh bunu 2012'den beri ksh ile uyumlu olmak için yapıyor. Yönettiğiniz değişiklik geçerli hale gelinceye kadar POSIX tarafından gerekli değildi.
schily

1
Açıkçası, [ -n "${PS1}" ] yanlış çağırmanın biraz ileri gittiğini söyleyebilirim , sonuçta sadece bir kişi PS1'i dışa aktardığında (bu cevabınızda kötü bir fikir olduğunu ve hatta nedenlerine girdiğinizde) kırıldığını söyler ve bu etkilemez bash neyse (eğer kabuk etkileşimli değilse PS1 ve PS2'yi kaldırdığı için.) Belki "cesareti kırılmış" gibi bir kelimeyi kullanmak ya da yaklaşımın "sınırlamaları" hakkında konuşmak daha iyi olurdu. Bunun tamamen "yanlış" olduğunu düşünmüyorum. Şey ise yanlış kesin PS1, ihraç! Her neyse, bunun ayrıntılarına girdiğiniz için teşekkürler.
filbranden

1

Bu garip kavram, bashbir POSIX kabuk klonu olarak değil, bir Bourne Shellklon olarak başlamasından kaynaklanıyor gibi görünüyor .

Sonuç olarak, POSIX etkileşimli davranışı ( $ENVetkileşimli kabuklar için çağrılır) daha sonra eklenmiştir bashve yaygın olarak bilinmemektedir.

Benzer davranış veren bir kabuk var. Bu cshve $promptbelirli değerlere sahip csh hibeleri :

$prompt not set          non-interactive shell, test $?prompt.
$prompt set but == ""    .cshrc called by the which(1) command.
$prompt set and != ""    normal interactive shell.

Ancak bu ne Bourne Kabuğu veya POSIX mermileri için geçerli değildir.

POSIX kabuğu için, verilen tek yöntem, dosyaya etkileşimli kabuklar için kod koymaktır:

$ENV

Kabuğa özel bir adı vardır. Örneğin

$HOME/.kshrc    for the korn shell
$HOME/.bashrc   for bash
$HOME/.mkshrc   for mksh
$HOME/.shrc     for the POSIX Bourne Shell

Diğer insanlar kabuk bayrağından bahsetti -i, ancak bu güvenilir programlama için kullanılamaz. POSIX ne set -içalışır ne de interaktif mermiler için $-bir içerir i. POSIX sadece sh -ikabuğun etkileşimli moda zorlanmasını gerektirir .

Değişken $PS1ortamdan alınabileceğinden, etkileşimli olmayan modda bile bir değere sahip olabilir. Aslında bash unsetler PS1olmayan herhangi etkileşimli kabukta standardında verilmeyen ve diğer kabuk tarafından yapılmaz.

Yani temiz programlama (ile bile bash) interaktif mermiler için komutları koymaktır $HOME/.bashrc.


0

İlk olarak Debian'ın nelerden konuşacağım ve çoğu zaman Ubuntu'nun bash için ayarladığı şey. Ve diğer sistemlere ikinci dokunuş.

Kabuk başlangıç ​​dosyalarının ayarlanmasında çok fazla fikir vardır.
Benim de fikrim var ama doğru ayarların mevcut örneklerini göstermeye çalışacağım.
Dosyalarından örnekler bulmak oldukça kolay olduğundan debuan kullanacağım.
Ve debian yoğun bir şekilde kullanılıyor, bu yüzden ayarlar iyi test edildi,

PS1'in ayarlandığını kontrol etmenin amacı nedir?

Sadece kabuğun etkileşimli olup olmadığını öğrenmek için.

Varsayılan /etc/profiledebian ve ubuntu (gelen / usr / share / baz files / profil):

if [ "${PS1-}" ]; then
    if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then

İf okundu: etkileşimli ise (varsayılan PS1 seti) ve bir bash kabuğudur (ancak varsayılan olarak davranmaz sh), sonra PS1'i belirli bir yenisiyle değiştirin (varsayılan değil).

Varsayılan /etc/bash.bashrcdebian içinde de içerir:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

Bu, yaptığı işte oldukça açıktır: Etkileşimli ise kaynak yapmayın (geri kalanı).

Bununla birlikte, içinde /etc/skel/.bashrcbir örnektir (kullanarak etkileşimli kabuk test etmek için, doğru bir şekilde $-):

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

Bu PS1 ve bir alternatifin nedenini açıkça göstermelidir.

Doğru sipariş

Bildirdiğiniz ayarlardan kaçınılmalıdır.
(Sistem ayarlarından () partisi yüzünden daha spesifik kullanıcı ayarlarına) sipariş /etc/profile, /etc/bash.bashrc, ~/.profileve nihayet ~/.bashrc. Bu, en geniş etkileri (ve daha fazla kabuk için) /etc/profile(köke ait) ve ardından /etc/bash.bashrc(aynı zamanda köke de aittir) yerleştirir, ancak sadece bash'ı etkiler. Sonra kişisel ayarları girin $HOME, ilki ~/.profileçoğu kabuk için ve ~/.bashrc(neredeyse eşdeğer ~/.bash_profile), sadece bas için spesifiktir.

Bu nedenle kaynak ~/.bashrcyapmak yanlıştır ~/.profile, bash için belirli bir kullanıcı ayarını, daha fazla mermiyi etkileyen daha genel bir hale dönüştürüyor . Bu şekilde yapılması haricinde :

# ~/.profile: executed by the command interpreter for login shells
# if running bash
if [ -n "$BASH_VERSION" ]; then
    # include .bashrc if it exists
    if [ -f "$HOME/.bashrc" ]; then
    . "$HOME/.bashrc"
    fi
fi

Bash'ın çalışıp çalışmadığını kontrol eder ve yalnızca .bashrcbu durumda yükler .

Bu Debian'dan gelen yukarı yönlü bir karardır. Gerekçe burada açıklanmaktadır .

Aslında, tersten, kaynak olarak ~/.profileiçinde ~/.bash_profile(veya ~/.bashrc) sadece-re uygulayarak bu nedenle belirli bir kullanım alanına zaten yüklenmiş ve edilmişti gereken genel kurallar "değil kötü" (Ben "iyi" demiyorum) olduğu. Ve ben iyi demiyorum çünkü dosyaların kaynak döngüsüne neden olabilir. Bir alt dizin bir üst öğe yüklediğinde olduğu gibi, bu bir dizin döngüsüdür.

Ve bu çapraz kaynakta etkileşimli kabuk kontrolü mantıklı. Yalnızca bir kabuk etkileşimli olduğunda ~/.bashrcyüklenir, ancak sırayla yüklenebilir ~/.profile(veya başka bir şekilde) ve bu durumda etkileşimli bir kabuk olup olmadığı kontrol edilebilir.

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.