Jawaban:
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.)
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 (meskipun yash
juga menetapkan PS1
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!
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).
Shell interaktif mengatur variabel shellPS1
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 (mengapa bash -c '… do stuff with $var…'
tidak bekerja ketika var
adalah PS1
?). 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 digunakan PS1
tetapi dengan sintaks yang berbeda (mis. Esk cepat prompt bash benar-benar berbeda dari eskut cepat zsh ). Tetapi cukup luas bahwa dalam praktiknya, melihat yang PS1
diatur bukanlah indikator yang dapat diandalkan bahwa shell bersifat interaktif. Shell mungkin telah diwarisi PS1
dari lingkungan.
.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 adalah rshd
atau sshd
). Dalam kasus kedua ini, sepertinya tidak PS1
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.
Ada cara mudah dan mudah untuk menguji apakah shell saat ini interaktif: uji apakah opsi -i
diaktifkan.
case $- in
*i*) echo "This shell is interactive";;
*) echo "This shell is not interactive";;
esac
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.
if [[ $- != *i* && -r ~/.profile ]]; then . ~/.profile; fi
[[ -o interactive ]]
(ksh, bash, zsh) atau case $- 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, sambil PS1=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").
$-
berisi i
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 sebagai Bourne Shell
klon.
Akibatnya, perilaku interaktif POSIX ( $ENV
dipanggil untuk kerang interaktif) telah ditambahkan kemudian bash
dan tidak diketahui secara luas.
Ada satu shell yang memberikan perilaku serupa. Ini csh
dan hibah csh yang $prompt
memiliki nilai spesifik:
$prompt not set non-interactive shell, test $?prompt.
$prompt set but == "" .cshrc called by the which(1) command.
$prompt set and != "" normal interactive shell.
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:
$ENV
yang memiliki nama spesifik shell. Itu misalnya
$HOME/.kshrc for the korn shell
$HOME/.bashrc for bash
$HOME/.mkshrc for mksh
$HOME/.shrc for the POSIX Bourne Shell
Orang lain menyebutkan flag shell -i
, tetapi ini tidak dapat digunakan untuk pemrograman yang andal. POSIX tidak mensyaratkan itu set -i
berfungsi, juga yang $-
mengandung i
shell interaktif. POSIX hanya mengharuskan sh -i
shell diterapkan ke mode interaktif.
Karena variabel $PS1
dapat diimpor dari lingkungan, ia mungkin memiliki nilai bahkan dalam mode non-interaktif. Fakta bahwa bash
unset
s PS1
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
.
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,
Hanya untuk mengetahui apakah shell itu interaktif.
The standar /etc/profile
di debian dan ubuntu (dari / usr / share / base-file / profile):
if [ "${PS1-}" ]; then
if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then
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:
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
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 $-
):
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
Itu harus menunjukkan dengan jelas mengapa PS1 dan satu alternatif.
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 :
# ~/.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
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.
( 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.