Apa tujuan melakukan [ -n "$PS1" ]
di [ -n "$PS1" ] && source ~/.bash_profile;
layani? Baris ini termasuk dalam repo.bashrc
dotfiles .
10
Ini memeriksa apakah shell itu interaktif atau tidak. Dalam hal ini, hanya sumber ~/.bash_profile
file jika shell bersifat interaktif.
Lihat "Apakah Shell ini Interaktif?" dalam manual bash, yang mengutip ungkapan spesifik itu. (Ini juga merekomendasikan memeriksa apakah shell bersifat interaktif dengan menguji apakah $-
variabel khusus berisi i
karakter, yang merupakan pendekatan yang lebih baik untuk masalah ini.)
( export PS1='abc$ '; bash -c 'echo "[$PS1]"' )
, yang hanya dicetak[]
. Tampaknya zsh tidak melakukan hal yang sama, setidaknya dari percobaan ... Dalam kasus apa pun, maksud dari[ -n "$PS1" ]
adalah untuk memeriksa apakah shell itu interaktif atau tidak.bash
unsets PS1 ketika non-interaktif (typo dalam komentar sebelumnya) adalah bug IMO, PS1 bukanlah variabel bash tertentu, tidak memiliki bisnis unsetting itu. Ini satu-satunya shell yang melakukan itu (meskipunyash
juga menetapkanPS1
ke nilai default bahkan ketika non-interaktif).[[ $- = *i* ]] && source ~/.bash_profile
).[ -n "${PS1}" ]
, tapi saya masih memperbarui jawaban saya untuk menyoroti bahwa manual bash juga menyarankan / merekomendasikan memeriksa$-
untuk menentukan apakah shell itu interaktif, saya harap Anda menemukan yang meningkatkan jawabannya. Bersulang!Apa ini?
Ini adalah cara yang luas untuk menguji apakah shell itu interaktif. Berhati-hatilah karena itu hanya bekerja di bash, tidak bekerja dengan shell lain. Jadi tidak apa-apa (jika konyol) untuk
.bashrc
, tetapi tidak akan bekerja di.profile
(yang dibaca oleh sh, dan bash hanya salah satu dari implementasi yang mungkin dari sh, dan bukan yang paling umum).Mengapa ini bekerja (hanya di bash!)
Shell interaktif mengatur variabel shell
PS1
ke string prompt default. Jadi jika shell itu interaktif,PS1
sudah diatur (kecuali jika pengguna.bashrc
telah menghapusnya, yang belum bisa terjadi di atas.bashrc
, dan Anda bisa menganggap itu adalah hal yang konyol untuk dilakukan).Kebalikannya benar di bash: contoh non-interaktif bash tidak disetel
PS1
saat mereka mulai. Perhatikan bahwa perilaku ini adalah khusus untuk bash, dan ini bisa dibilang bug (mengapabash -c '… do stuff with $var…'
tidak bekerja ketikavar
adalahPS1
?). Tetapi semua versi bash hingga dan termasuk 4.4 (versi terbaru saat saya menulis) melakukan ini.Banyak sistem mengekspor
PS1
ke lingkungan. Ini adalah ide yang buruk, karena banyak shell yang berbeda digunakanPS1
tetapi dengan sintaks yang berbeda (mis. Esk cepat prompt bash benar-benar berbeda dari eskut cepat zsh ). Tetapi cukup luas bahwa dalam praktiknya, melihat yangPS1
diatur bukanlah indikator yang dapat diandalkan bahwa shell bersifat interaktif. Shell mungkin telah diwarisiPS1
dari lingkungan.Mengapa (salah) digunakan di sini
.bashrc
adalah file yang dibaca bash pada saat startup ketika bersifat interaktif. Fakta yang kurang terkenal adalah bahwa bash juga membaca.bashrc
adalah shell login dan heuristik bash menyimpulkan bahwa ini adalah sesi jarak jauh (bash memeriksa apakah induknya adalahrshd
atausshd
). Dalam kasus kedua ini, sepertinya tidakPS1
akan diatur di lingkungan, karena belum ada file dot yang berjalan.Namun, cara kode menggunakan informasi ini kontraproduktif.
.bash_profile
di shell itu. Tetapi.bash_profile
skrip waktu masuk. Mungkin menjalankan beberapa program yang dimaksudkan untuk dijalankan hanya sekali per sesi. Ini mungkin menimpa beberapa variabel lingkungan yang sengaja ditetapkan pengguna ke nilai yang berbeda sebelum menjalankan shell itu. Menjalankan.bash_profile
di shell non-login mengganggu..bash_profile
. Tapi ini adalah kasus di mana memuat.bash_profile
bisa bermanfaat, karena shell login non-interaktif tidak otomatis memuat/etc/profile
dan~/.profile
.Saya pikir alasan orang melakukan ini adalah untuk pengguna yang masuk melalui GUI (kasus yang sangat umum) dan yang menempatkan pengaturan variabel lingkungan mereka
.bash_profile
daripada.profile
. Sebagian besar mekanisme login GUI dipanggil.profile
tetapi tidak.bash_profile
(membaca.bash_profile
akan membutuhkan menjalankan bash sebagai bagian dari sesi startup, bukan sh). Dengan konfigurasi ini, ketika pengguna membuka terminal, mereka akan mendapatkan variabel lingkungannya. Namun, pengguna tidak akan mendapatkan variabel lingkungan mereka dalam aplikasi GUI, yang merupakan sumber kebingungan yang sangat umum. Solusinya di sini adalah menggunakan.profile
alih-alih.bash_profile
mengatur variabel lingkungan. Menambahkan jembatan di antara.bashrc
dan.bash_profile
menciptakan lebih banyak masalah daripada menyelesaikannya.Apa yang harus dilakukan
Ada cara mudah dan mudah untuk menguji apakah shell saat ini interaktif: uji apakah opsi
-i
diaktifkan.Ini berguna
.bashrc
untuk membaca.profile
hanya jika shell tidak interaktif - yaitu kebalikan dari apa yang dilakukan oleh kode! Baca.profile
jika bash adalah shell login (non-interaktif), dan jangan membacanya jika itu shell interaktif.sumber
[[ -o interactive ]]
(ksh, bash, zsh) ataucase $- in (*i*) ...; esac
(POSIX)PS1
jika tidak dijalankan secara interaktif. Cukup mudah untuk diuji:PS1=cuckoo bash -c '[ -n "${PS1}" ] && echo "PS1=[${PS1}]"'
tidak akan mencetak apa pun, sambilPS1=cuckoo bash -i -c '[ -n "${PS1}" ] && echo "PS1=[${PS1}]"'
mencetak nilai yang$PS1
diatur dalam file startup bash Anda (itu tidak akan mencetak string "cuckoo").$-
berisii
dengan shell interaktif.[ -n "${PS1}" ]
salah agak terlalu jauh, setelah semua itu hanya rusak ketika seseorang mengekspor PS1 (yang dalam jawaban Anda, Anda mengatakan itu adalah ide yang buruk dan bahkan masuk ke alasan mengapa) dan itu tidak mempengaruhi bash anyways (karena PS1 dan PS2 tidak terhapus jika shellnya tidak interaktif.) Mungkin menggunakan kata seperti "tidak disarankan" atau berbicara tentang "keterbatasan" dari pendekatan akan lebih baik. Saya tidak berpikir itu "salah" sama sekali. Jika ada yang salah mengekspor PS1, itu pasti! Ngomong-ngomong, terima kasih sudah membahas detail ini.Tampaknya konsep aneh ini adalah hasil dari fakta yang
bash
tidak dimulai sebagai klon shell POSIX tetapi sebagaiBourne Shell
klon.Akibatnya, perilaku interaktif POSIX (
$ENV
dipanggil untuk kerang interaktif) telah ditambahkan kemudianbash
dan tidak diketahui secara luas.Ada satu shell yang memberikan perilaku serupa. Ini
csh
dan hibah csh yang$prompt
memiliki nilai spesifik:Tapi ini tidak berlaku untuk Shell Bourne atau untuk shell POSIX.
Untuk shell POSIX, satu-satunya metode yang diberikan adalah memasukkan kode untuk shell interaktif ke dalam file:
yang memiliki nama spesifik shell. Itu misalnya
Orang lain menyebutkan flag shell
-i
, tetapi ini tidak dapat digunakan untuk pemrograman yang andal. POSIX tidak mensyaratkan ituset -i
berfungsi, juga yang$-
mengandungi
shell interaktif. POSIX hanya mengharuskansh -i
shell diterapkan ke mode interaktif.Karena variabel
$PS1
dapat diimpor dari lingkungan, ia mungkin memiliki nilai bahkan dalam mode non-interaktif. Fakta bahwabash
unset
sPS1
dalam setiap shell non-interaktif tidak diberikan oleh standar dan tidak dilakukan oleh shell lain.Jadi pemrograman bersih (bahkan dengan
bash
) adalah untuk menempatkan perintah untuk shell interaktif$HOME/.bashrc
.sumber
Saya akan berbicara terlebih dahulu tentang apa yang Debian, dan sebagian besar waktu juga Ubuntu ditetapkan untuk bash. Dan sentuhan terakhir pada sistem lain.
Dalam pengaturan file mulai shell ada banyak pendapat.
Saya juga memiliki pendapat saya tetapi saya akan mencoba menunjukkan contoh pengaturan yang benar.
Saya akan menggunakan debuan karena cukup mudah untuk menemukan contoh file-nya.
Dan debian banyak digunakan, sehingga pengaturan telah diuji dengan baik,
Apa tujuan memeriksa apakah PS1 diatur?
Hanya untuk mengetahui apakah shell itu interaktif.
The standar
/etc/profile
di debian dan ubuntu (dari / usr / share / base-file / profile):The if's read: if interactive (PS1 default set) dan ini merupakan bash shell (tetapi tidak bertindak sebagai default
sh
) kemudian ubah PS1 ke yang baru (bukan yang default).The standar
/etc/bash.bashrc
di debian juga berisi:Yang cukup jelas dalam fungsinya: Jika interaktif tidak sumber (sisanya).
Namun, in
/etc/skel/.bashrc
adalah contoh cara yang benar untuk menguji shell interaktif (menggunakan$-
):Itu harus menunjukkan dengan jelas mengapa PS1 dan satu alternatif.
Urutan yang benar
Pengaturan yang Anda laporkan harus dihindari.
Urutan (dari pengaturan sistem untuk pengaturan pengguna yang lebih spesifik (untuk bash)) adalah
/etc/profile
,/etc/bash.bashrc
,~/.profile
dan akhirnya~/.bashrc
. Itu menempatkan efek paling luas (dan untuk lebih banyak kerang) di/etc/profile
(yang dimiliki oleh root) diikuti oleh/etc/bash.bashrc
(yang juga dimiliki oleh root) tetapi hanya memengaruhi bash. Kemudian datang pengaturan pribadi$HOME
, yang pertama adalah~/.profile
untuk sebagian besar shell dan~/.bashrc
(hampir setara dengan~/.bash_profile
), khusus untuk bash saja.Oleh karena itu salah untuk sumber
~/.bashrc
di~/.profile
, itu mengubah sebuah pengguna tertentu pengaturan untuk bash ke yang lebih umum yang mempengaruhi lebih kerang . Kecuali jika dilakukan dengan cara ini :Ia memeriksa bahwa bash sedang berjalan dan hanya memuat
.bashrc
jika itu yang terjadi.Ini adalah keputusan hulu yang berasal dari Debian. Alasannya dijelaskan di sini .
Bahkan, kebalikannya, sumber
~/.profile
dalam~/.bash_profile
(atau~/.bashrc
) hanya menerapkan kembali aturan umum yang seharusnya sudah dimuat ke kasus penggunaan tertentu, dan karena itu "tidak terlalu buruk" (saya tidak mengatakan "baik"). Dan saya tidak mengatakan baik karena dapat menyebabkan sumber file berulang. Seperti ketika sub-direktori memuat orangtua, itu adalah loop direktori.Dan dalam lintas sumber inilah pemeriksaan shell interaktif masuk akal. Hanya ketika shell interaktif
~/.bashrc
dimuat, tetapi pada gilirannya dapat memuat~/.profile
(atau sebaliknya) dan dalam hal ini memeriksa shell interaktif dapat digunakan.sumber