Ini adalah pertanyaan yang akan saya posting di sini beberapa minggu yang lalu. Seperti terdon , saya mengerti bahwa a .bashrchanya bersumber untuk shell Bash interaktif sehingga tidak perlu untuk .bashrcmemeriksa 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 ~/.bashrcperintah 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 --norcpilihan dapat digunakan untuk menghambat perilaku ini, dan --rcfilepilihan dapat digunakan untuk memaksa file lain untuk dibaca, tetapi tidak rshdjuga sshdumumnya memohon shell dengan orang-orang pilihan atau memungkinkan mereka untuk ditentukan.
Contoh
Masukkan yang berikut ini di awal remote .bashrc. (Jika .bashrcdipasok oleh .profileatau .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
idalam $-menunjukkan bahwa shell itu non-interaktif .
- Tidak ada terkemuka
-di $0menunjukkan bahwa shell tidak shell login .
Fungsi-fungsi Shell yang didefinisikan di remote .bashrcjuga dapat dijalankan:
$ ssh remote_host fun
bashrc
functions work
Saya melihat bahwa ~/.bashrcini hanya bersumber ketika perintah ditetapkan sebagai argumen untuk ssh. Ini masuk akal: ketika sshdigunakan untuk memulai shell login biasa, .profileatau .bash_profiledijalankan (dan .bashrchanya bersumber jika dilakukan secara eksplisit oleh salah satu file ini).
Manfaat utama yang bisa saya lihat .bashrcberasal dari menjalankan perintah remote (non-interaktif) adalah bahwa fungsi shell dapat dijalankan. Namun, sebagian besar perintah dalam tipikal .bashrchanya relevan dalam shell interaktif, misalnya, alias tidak diperluas kecuali shell tersebut interaktif.
Transfer file jarak jauh bisa gagal
Ini biasanya bukan masalah ketika rshatau sshdigunakan untuk memulai shell login interaktif atau ketika shell non-interaktif digunakan untuk menjalankan perintah. Namun, ini bisa menjadi masalah untuk program seperti rcp, scpdan sftpyang menggunakan kerang remote untuk mentransfer data.
Ternyata shell default pengguna jarak jauh (seperti Bash) secara implisit dimulai ketika menggunakan scpperintah. Tidak disebutkan tentang ini di halaman manual - hanya menyebutkan yang scpdigunakan sshuntuk transfer datanya. Ini memiliki konsekuensi bahwa jika .bashrcberisi 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 scpdan sftpgagal
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
ttyinput 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/ sftpdan 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 scpdalam 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 scphanya tinggal dalam satu lingkaran, diblokir read(2). Sementara itu, setelah profil shell diproses pada sisi jarak jauh, scpdalam mode sink dimulai, yang juga memblokir read(2), menunggu nol biner yang menunjukkan dimulainya transfer data.
Kesimpulan / TLDR
Sebagian besar pernyataan dalam tipikal .bashrchanya berguna untuk shell interaktif - bukan ketika menjalankan perintah jarak jauh dengan rshatau 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 scpatau sftp. Keluar setelah memverifikasi bahwa shell saat ini adalah non-interaktif adalah perilaku paling aman untuk .bashrc.