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 :
Bash mencoba untuk menentukan kapan sedang dijalankan dengan input standar yang terhubung ke koneksi jaringan, seperti ketika dieksekusi oleh daemon shell jarak jauh, biasanya rshd
, atau daemon shell aman sshd
. Jika Bash menentukan sedang dijalankan dengan cara ini, ia membaca dan mengeksekusi perintah dari ~ / .bashrc, jika file itu ada dan dapat dibaca. Ini tidak akan melakukan ini jika dipanggil sebagai sh
. The --norc
pilihan dapat digunakan untuk menghambat perilaku ini, dan --rcfile
pilihan dapat digunakan untuk memaksa file lain untuk dibaca, tetapi tidak rshd
juga sshd
umumnya memohon shell dengan orang-orang pilihan atau memungkinkan mereka untuk ditentukan.
Contoh
Masukkan yang berikut ini di awal remote .bashrc
. (Jika .bashrc
dipasok oleh .profile
atau .bash_profile
, nonaktifkan sementara ini saat pengujian):
echo bashrc
fun()
{
echo functions work
}
Jalankan perintah berikut secara lokal:
$ ssh remote_host 'echo $- $0'
bashrc
hBc bash
- Tidak
i
dalam $-
menunjukkan bahwa shell itu non-interaktif .
- Tidak ada terkemuka
-
di $0
menunjukkan bahwa shell tidak shell login .
Fungsi-fungsi Shell yang didefinisikan di remote .bashrc
juga dapat dijalankan:
$ ssh remote_host fun
bashrc
functions work
Saya melihat bahwa ~/.bashrc
ini hanya bersumber ketika perintah ditetapkan sebagai argumen untuk ssh
. Ini masuk akal: ketika ssh
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
atau ssh
digunakan untuk memulai shell login interaktif atau ketika shell non-interaktif digunakan untuk menjalankan perintah. Namun, ini bisa menjadi masalah untuk program seperti rcp
, scp
dan sftp
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 yang scp
digunakan ssh
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
dan sftp
gagal
SCP (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
Yang sering terjadi, meskipun, adalah bahwa ada pernyataan dalam baik sistem atau file shell startup per-user di server ( .bashrc
, .profile
,
/etc/csh.cshrc
, .login
, dll) yang keluaran pesan teks pada login, dimaksudkan untuk dibaca oleh manusia (seperti fortune
, echo "Hi there!"
, dll.)
Kode tersebut hanya akan menghasilkan output pada login interaktif, ketika ada
tty
input standar yang dilampirkan. Jika tidak melakukan tes ini, itu akan menyisipkan pesan teks ini di mana mereka tidak termasuk: dalam hal ini, mencemari aliran protokol antara scp2
/ sftp
dan sftp-server
.
Alasan mengapa file startup shell relevan sama sekali, adalah karena sshd
mempekerjakan shell pengguna ketika memulai program apa pun atas nama pengguna
(menggunakan mis. / Bin / sh -c "command"). Ini adalah tradisi Unix, dan memiliki kelebihan:
- Pengaturan biasa pengguna (alias perintah, variabel lingkungan, umask, dll.) Berlaku ketika perintah jarak jauh dijalankan.
- Praktik umum pengaturan shell akun ke / bin / false untuk menonaktifkannya akan mencegah pemilik menjalankan perintah apa pun, seandainya otentikasi secara tidak sengaja berhasil karena suatu alasan.
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? :
Misalnya, ini bisa terjadi jika Anda menambahkan ini ke profil shell Anda di sistem jarak jauh:
gema ""
Kenapa hanya hang? Itu datang dari cara bagaimana scp
dalam mode sumber menunggu konfirmasi pesan protokol pertama. Jika bukan biner 0, ia mengharapkan pemberitahuan masalah jarak jauh dan menunggu lebih banyak karakter untuk membentuk pesan kesalahan hingga baris baru tiba. Karena Anda tidak mencetak baris baru setelah yang pertama, lokal Anda scp
hanya tinggal dalam satu lingkaran, diblokir read(2)
. Sementara itu, setelah profil shell diproses pada sisi jarak jauh, scp
dalam mode sink dimulai, yang juga memblokir read(2)
, menunggu nol biner yang menunjukkan dimulainya transfer data.
Kesimpulan / TLDR
Sebagian besar pernyataan dalam tipikal .bashrc
hanya berguna untuk shell interaktif - bukan ketika menjalankan perintah jarak jauh dengan rsh
atau ssh
. 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 seperti scp
atau sftp
. Keluar setelah memverifikasi bahwa shell saat ini adalah non-interaktif adalah perilaku paling aman untuk .bashrc
.