Di Arch saya pasang, /etc/bash.bashrc
dan /etc/skel/.bashrc
mengandung baris-baris ini:
# If not running interactively, don't do anything
[[ $- != *i* ]] && return
Di Debian, /etc/bash.bashrc
memiliki:
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
Dan /etc/skel/.bashrc
:
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
Menurut man bash
, namun, kerang non-interaktif bahkan tidak membaca file-file ini:
When bash is started non-interactively, to run a shell script, for
example, it looks for the variable BASH_ENV in the environment, expands
its value if it appears there, and uses the expanded value as the name
of a file to read and execute. Bash behaves as if the following com‐
mand were executed:
if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi
but the value of the PATH variable is not used to search for the file‐
name.
Jika saya mengerti dengan benar, *.bashrc
file hanya akan dibaca jika BASH_ENV
diatur untuk mengarahkannya. Ini adalah sesuatu yang tidak dapat terjadi secara kebetulan dan hanya akan terjadi jika seseorang telah secara eksplisit mengatur variabel yang sesuai.
Itu tampaknya mematahkan kemungkinan memiliki skrip sumber pengguna .bashrc
secara otomatis dengan menetapkan BASH_ENV
, sesuatu yang bisa berguna. Mengingat bahwa bash tidak akan pernah membaca file-file ini ketika dijalankan secara non-interaktif kecuali secara eksplisit disuruh melakukannya, mengapa *bashrc
file-file default tidak memperbolehkannya?
Jawaban:
Ini adalah pertanyaan yang akan saya posting di sini beberapa minggu yang lalu. Seperti terdon , saya mengerti bahwa a
.bashrc
hanya bersumber untuk shell Bash interaktif sehingga tidak perlu untuk.bashrc
memeriksa apakah itu berjalan dalam shell interaktif. Yang membingungkan, semua distribusi yang saya gunakan (Ubuntu, RHEL dan Cygwin) memiliki beberapa jenis pemeriksaan (pengujian$-
atau$PS1
) untuk memastikan shell saat ini bersifat interaktif. Saya tidak suka pemrograman pemujaan kargo, jadi saya mulai memahami tujuan kode ini di blog saya.bashrc
.Bash memiliki kasing khusus untuk kerang jarak jauh
Setelah meneliti masalah ini, saya menemukan bahwa shell jarak jauh diperlakukan secara berbeda. Sementara shell Bash non-interaktif biasanya tidak menjalankan
~/.bashrc
perintah saat start-up, sebuah kasus khusus dibuat ketika shell dipanggil oleh daemon shell jarak jauh :Contoh
Masukkan yang berikut ini di awal remote
.bashrc
. (Jika.bashrc
dipasok oleh.profile
atau.bash_profile
, nonaktifkan sementara ini saat pengujian):Jalankan perintah berikut secara lokal:
i
dalam$-
menunjukkan bahwa shell itu non-interaktif .-
di$0
menunjukkan bahwa shell tidak shell login .Fungsi-fungsi Shell yang didefinisikan di remote
.bashrc
juga dapat dijalankan:Saya melihat bahwa
~/.bashrc
ini hanya bersumber ketika perintah ditetapkan sebagai argumen untukssh
. Ini masuk akal: ketikassh
digunakan untuk memulai shell login biasa,.profile
atau.bash_profile
dijalankan (dan.bashrc
hanya bersumber jika dilakukan secara eksplisit oleh salah satu file ini).Manfaat utama yang bisa saya lihat
.bashrc
berasal dari menjalankan perintah remote (non-interaktif) adalah bahwa fungsi shell dapat dijalankan. Namun, sebagian besar perintah dalam tipikal.bashrc
hanya relevan dalam shell interaktif, misalnya, alias tidak diperluas kecuali shell tersebut interaktif.Transfer file jarak jauh bisa gagal
Ini biasanya bukan masalah ketika
rsh
ataussh
digunakan untuk memulai shell login interaktif atau ketika shell non-interaktif digunakan untuk menjalankan perintah. Namun, ini bisa menjadi masalah untuk program sepertircp
,scp
dansftp
yang menggunakan kerang remote untuk mentransfer data.Ternyata shell default pengguna jarak jauh (seperti Bash) secara implisit dimulai ketika menggunakan
scp
perintah. Tidak disebutkan tentang ini di halaman manual - hanya menyebutkan yangscp
digunakanssh
untuk transfer datanya. Ini memiliki konsekuensi bahwa jika.bashrc
berisi perintah yang mencetak ke output standar, transfer file akan gagal , misalnya, scp gagal tanpa kesalahan .Lihat juga laporan bug Red Hat terkait ini dari 15 tahun yang lalu, scp rusak ketika ada perintah echo di / etc / bashrc (yang akhirnya ditutup sebagai
WONTFIX
).Kenapa
scp
dansftp
gagalSCP (Secure copy) dan SFTP (Secure File Transfer Protocol) memiliki protokol sendiri untuk tujuan lokal dan jarak jauh untuk bertukar informasi tentang file yang sedang ditransfer. Teks yang tidak terduga dari ujung jarak jauh (salah) ditafsirkan sebagai bagian dari protokol dan transfer gagal. Menurut sebuah FAQ dari Snail Book
Detail protokol SCP
Bagi mereka yang tertarik dengan detail tentang cara kerja SCP, saya menemukan informasi menarik di Bagaimana protokol SCP bekerja yang mencakup detail tentang Menjalankan scp dengan profil shell latah di sisi jarak jauh? :
Kesimpulan / TLDR
Sebagian besar pernyataan dalam tipikal
.bashrc
hanya berguna untuk shell interaktif - bukan ketika menjalankan perintah jarak jauh denganrsh
ataussh
. Dalam sebagian besar situasi seperti itu, pengaturan variabel shell, alias dan fungsi mendefinisikan tidak diinginkan - dan mencetak teks apa pun ke standar keluar secara aktif berbahaya jika mentransfer file menggunakan program sepertiscp
atausftp
. Keluar setelah memverifikasi bahwa shell saat ini adalah non-interaktif adalah perilaku paling aman untuk.bashrc
.sumber
Halaman manual lupa menyebutkan bahwa
bash
juga sumber.bashrc
untuk shell remote non-interaktif, seperti padahttp://git.savannah.gnu.org/cgit/bash.git/tree/shell.c#n1010
http://git.savannah.gnu.org/cgit/bash.git/tree/shell.c#n1050
sumber
.bash_profile
akan menunjukkan perilaku yang sama.rsh
(yang saya tidak pernah menggunakan) sumber~/.bashrc
? Dan itu, dengan ekstensi, distro Linux memblokirnya untukbash
berjaga-jaga kalau-kalau ada yang mencoba menjalankan skrip denganrsh
?ssh server
tidak boleh disentuh.bashrc
karena itu adalah shell login. Tidak, kecuali jika sistem Anda adalah salah satu dari yang sumber ~ / .bashrc` dari~/.profile
. Danssh server command
seharusnya tidak melakukan itu. Tentu tidak di sistem saya.bash
sumbernya, bukanrsh
sumbernya. :) Komentar berlakussh
juga, itu baru saja ditulis sejak lama. Lihat jawaban yang diperbarui dengan lebih banyak sumber.echo
di bagian paling atas/etc/bash.bashrc
dan~/.bashrc
(sebelum tes shell interaktif) dan kemudian ssh ke mesin target denganssh server hostname
dan saathostname
dijalankan, saya tidak melihat salah satu gema saya. Apakah sayashell_level
(apa pun itu) bukan saya<2
?Dengan konvensi,
.bashrc
adalah tempat di mana pengguna menyimpan konfigurasi khusus untuk shell.Konfigurasi penyesuaian ini dapat berupa variabel lingkungan, alias, perintah cepat. Dengan shell non-interaktif, kekurangan itu tidak ada artinya. Selain itu, shell non-interaktif dapat dipanggil dalam banyak konteks, Anda tidak yakin variabel lingkungan tersebut dapat mengarah ke kasus negatif palsu, atau bahkan rentan terhadap keamanan.
Contoh terdekat adalah alias seperti:
Kemudian menggantung shell non-interaktif Anda selamanya.
Jadi, periksa dilakukan di atas
.bashrc
untuk memastikan bahwa kami tidak akan mendapatkan masalah.Karena shell dapat disebut sebagai shell login non-interaktif , jadi secara eksplisit memblokir sumber
*bashrc
tidak masuk akal.Ketika shell itu disebut sebagai shell login non-interaktif , itu sumber
/etc/profile
, maka sumber yang pertama ditemukan di~/.bash_profile
,~/.bash_login
, dan~/.profile
:Tidak ada yang mencegah file-file itu dari sumber
.bashrc
itu sendiri, jadi melakukan pemeriksaan di dalam.bashrc
lebih aman dan membuat hal-hal sederhana.sumber
*bashrc
file sama sekali. Pertanyaan saya adalah mengapa berbagai vendor Linux menghadapi masalah dengan secara eksplisit memblokir cangkang non-interaktif dari membaca file-file ini jika file-file ini tidak dibaca oleh cangkang non-interaktif..bash_profile
, yang dapat menjadi sumber.bashrc
.$BASH_ENV
. Keduanya*profile
dan*bashrc
diabaikan. Atau, setidaknya, itulah yang dikatakan halaman manual. Namun, seperti yang Mikel tunjukkan, halaman manual itu mungkin bohong.bash -l -c :
menggunakan shell login non-interaktif?--login
100 kali tetapi, tampaknya, itu tidak pernah terdaftar. Terima kasih!