Jawaban:
Ini memeriksa apakah shell itu interaktif atau tidak. Dalam hal ini, hanya sumber ~/.bash_profilefile 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 ikarakter, yang merupakan pendekatan yang lebih baik untuk masalah ini.)
bashunsets 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 yashjuga menetapkan PS1ke 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, PS1sudah diatur (kecuali jika pengguna .bashrctelah 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 PS1saat 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 varadalah PS1?). Tetapi semua versi bash hingga dan termasuk 4.4 (versi terbaru saat saya menulis) melakukan ini.
Banyak sistem mengekspor PS1ke lingkungan. Ini adalah ide yang buruk, karena banyak shell yang berbeda digunakan PS1tetapi dengan sintaks yang berbeda (mis. Esk cepat prompt bash benar-benar berbeda dari eskut cepat zsh ). Tetapi cukup luas bahwa dalam praktiknya, melihat yang PS1diatur bukanlah indikator yang dapat diandalkan bahwa shell bersifat interaktif. Shell mungkin telah diwarisi PS1dari lingkungan.
.bashrcadalah file yang dibaca bash pada saat startup ketika bersifat interaktif. Fakta yang kurang terkenal adalah bahwa bash juga membaca .bashrcadalah shell login dan heuristik bash menyimpulkan bahwa ini adalah sesi jarak jauh (bash memeriksa apakah induknya adalah rshdatau sshd). Dalam kasus kedua ini, sepertinya tidak PS1akan diatur di lingkungan, karena belum ada file dot yang berjalan.
Namun, cara kode menggunakan informasi ini kontraproduktif.
.bash_profiledi shell itu. Tetapi .bash_profileskrip 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_profiledi shell non-login mengganggu..bash_profile. Tapi ini adalah kasus di mana memuat .bash_profilebisa bermanfaat, karena shell login non-interaktif tidak otomatis memuat /etc/profiledan ~/.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_profiledaripada .profile. Sebagian besar mekanisme login GUI dipanggil .profiletetapi tidak .bash_profile(membaca .bash_profileakan 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 .profilealih-alih .bash_profilemengatur variabel lingkungan. Menambahkan jembatan di antara .bashrcdan .bash_profilemenciptakan lebih banyak masalah daripada menyelesaikannya.
Ada cara mudah dan mudah untuk menguji apakah shell saat ini interaktif: uji apakah opsi -idiaktifkan.
case $- in
*i*) echo "This shell is interactive";;
*) echo "This shell is not interactive";;
esac
Ini berguna .bashrcuntuk membaca .profilehanya jika shell tidak interaktif - yaitu kebalikan dari apa yang dilakukan oleh kode! Baca .profilejika 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)
PS1jika 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 $PS1diatur dalam file startup bash Anda (itu tidak akan mencetak string "cuckoo").
$-berisi idengan 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 bashtidak dimulai sebagai klon shell POSIX tetapi sebagai Bourne Shellklon.
Akibatnya, perilaku interaktif POSIX ( $ENVdipanggil untuk kerang interaktif) telah ditambahkan kemudian bashdan tidak diketahui secara luas.
Ada satu shell yang memberikan perilaku serupa. Ini cshdan hibah csh yang $promptmemiliki 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 -iberfungsi, juga yang $-mengandung ishell interaktif. POSIX hanya mengharuskan sh -ishell diterapkan ke mode interaktif.
Karena variabel $PS1dapat diimpor dari lingkungan, ia mungkin memiliki nilai bahkan dalam mode non-interaktif. Fakta bahwa bash unsets PS1dalam 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/profiledi 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.bashrcdi 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/.bashrcadalah 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, ~/.profiledan 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 ~/.profileuntuk sebagian besar shell dan ~/.bashrc(hampir setara dengan ~/.bash_profile), khusus untuk bash saja.
Oleh karena itu salah untuk sumber ~/.bashrcdi ~/.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 .bashrcjika itu yang terjadi.
Ini adalah keputusan hulu yang berasal dari Debian. Alasannya dijelaskan di sini .
Bahkan, kebalikannya, sumber ~/.profiledalam ~/.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 ~/.bashrcdimuat, 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.