Gunakan .bashrc tanpa merusak sftp

20

Masalah saya adalah bahwa saya perlu mengatur beberapa variabel, dan menampilkan beberapa baris setiap kali saya masuk ke ssh shell, dan pada saat yang sama saya harus dapat menggunakan sftp untuk tarnsfer file melalui Filezilla.

Sekarang, sesuai dengan FAQ openssh di http://www.openssh.org/faq.html , jika skrip startup Anda menggemakan segala jenis output, itu kacau dengan sftp. Jadi itu tertunda tanpa batas waktu, atau kesalahan dengan "Koneksi ditutup oleh server dengan kode keluar 128".

Saya telah mencoba solusi seperti memindahkan .bashrc ke .bash_profile, atau menggunakan kode berikut di .bashrc:

if [ "$TERM" != "dumb" ]
then
   source .bashc_real
fi

Dan:

if [ "$TERM" = "xterm" ]
then
   source .bashc_real
fi

Namun, tidak ada yang berhasil. Terminal shell saya adalah bash, dan saya terhubung ke sftp dengan filezilla.

Joel G Mathew
sumber

Jawaban:

23

Coba lakukan ini sebagai gantinya

if [ "$SSH_TTY" ]
then
   source .bashc_real
fi
Mike
sumber
17

Jawaban Mike mungkin akan berhasil. Tetapi perlu menunjukkan bahwa Anda dapat melakukannya dengan hati-hati memilih file startup mana yang akan dimasukkan. Dari halaman bash man:

Ketika bash dipanggil sebagai shell login interaktif, atau sebagai shell non-interaktif dengan opsi --login, ia pertama kali membaca dan mengeksekusi perintah dari file / etc / profile, jika file itu ada. Setelah membaca file itu, ia mencari ~ / .bash_profile, ~ / .bash_login, dan ~ / .profile, dalam urutan itu, dan membaca serta mengeksekusi perintah dari yang pertama yang ada dan dapat dibaca. Opsi --noprofile dapat digunakan ketika shell mulai menghambat perilaku ini.

Ketika shell interaktif yang bukan shell login dimulai, bash membaca dan mengeksekusi perintah dari ~ / .bashrc, jika file itu ada. Ini dapat dihambat dengan menggunakan opsi --norc. Opsi file --rcfile akan memaksa bash untuk membaca dan menjalankan perintah dari file daripada ~ / .bashrc.

Alat sftp / scp memulai shell non-login interaktif, sehingga .bashrc akan bersumber. Banyak distribusi .bashrc dari .bash_profile atau sebaliknya, sehingga bisa membingungkan. Trik yang baik untuk menguji kebersihan lingkungan login Anda adalah ssh in dengan perintah, yang mensimulasikan cara yang sama scp / sftp terhubung. Sebagai contoh: ssh myhost /bin/trueakan menunjukkan kepada Anda apa yang scp / sftp lihat ketika mereka terhubung.

Demo sederhana:

insyte@mazer:~$ echo "echo Hello from .profile" > .profile
insyte@mazer:~$ echo "echo Hello from .bashrc" > .bashrc

sazerac:~ insyte$ ssh mazer /bin/true
Hello from .bashrc
sazerac:~ insyte$

insyte@mazer:~$ rm .bashrc

sazerac:~ insyte$ ssh mazer /bin/true
sazerac:~ insyte$

Tes pertama akan menyebabkan scp / sftp / rsync dll rusak. Versi kedua akan berfungsi dengan baik.

Insyte
sumber
Saya tidak setuju bahwa "Alat sftp / scp memulai shell non-login interaktif " karena kita tidak dapat benar-benar berinteraksi dengan shell. Tapi saya tidak mengerti mengapa .bashrcakan sumber scpatau ssh host command.
pynexj
2
Istilah "interaktif" tidak subyektif. Ini adalah istilah yang digunakan oleh bash untuk menggambarkan salah satu mode startup-nya. Ini adalah fakta bahwa sftp / scp memulai "shell non-login interaktif". Jangan ragu untuk berdebat dengan pengembang tentang apakah sumber .bashrc sesuai dalam kasus ini; Saya hanya memberi tahu Anda apa fungsinya.
Insyte
2
Bashdipanggil oleh scpatau ssh host commandmemang non-interaktif . Saya baru saja menemukan ini di manual bash: "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 shell aman daemon sshd . Jika bash menentukan sedang dijalankan dengan cara ini, ia membaca dan mengeksekusi perintah dari ~/.bashrc, jika file itu ada dan dapat dibaca. " Inilah sejarah yang menarik .
pynexj
1
Juga lihat bagian Remote non login non shells interaktif di halaman wiki ini .
pynexj
3

Jika Anda menggunakan csh:

if ($?prompt)
  ... interactive stuff ...

Dan jika bash:

if [[ $- == *i* ]]; then
  ... interactive stuff ...
fi

atau sebagai alternatif menggunakan bash regular expressions:

if [[ $- =~ i ]]; then
  ... interactive stuff ...
fi

Garis-garis ini harus mendahului garis-garis di mana Anda ouput / echo sesuatu kembali.

pengguna163384
sumber
Hai, tolong jelaskan kodenya. Saya tahu $ itu? adalah tingkat pengembalian dari perintah sebelumnya. Saya tidak mengerti $? Prompt dan $ -. Atau spesifik csh?
Joel G Mathew
1
@Droidzone: $?vardalam cshpengembalian 1 jika vardidefinisikan dan 0 sebaliknya. $-in bashakan memiliki ichar dalam nilainya jika shell bersifat interaktif.
pynexj
Sebaiknya perbarui jawaban untuk menjelaskan $ - adalah variabel khusus opsi shell. lihat stackoverflow.com/questions/5163144/…
maninvan
1

Solusi Mike juga bekerja untuk saya. Tetapi karena shell default saya adalah TCSH, saya harus sedikit mengedit perbaikannya sebagai berikut (dalam .tcshrc):

if ( $?SSH_TTY ) then
    exec /bin/bash
endif

Saya pikir saya akan berbagi untuk keuntungan semua orang.

Vijay Padiyar
sumber
0

Saya suka beberapa solusi lain yang disebutkan di sini lebih baik, tapi saya pikir saya membuang solusi yang saat ini saya gunakan pada bash dan csh VMs untuk mencegah SFTP terputus karena perintah gema dalam skrip startup saya, kalau-kalau ada yang menemukan informasi bermanfaat .

Dalam BASH:

if [ $TERM == "xterm" ] || [ $TERM == "xterm-256color" ]; then
  echo "Xterm display identified: echo enabled"
  echo_disable="0"
else
  echo_disable="1"
fi

# Use the following for all subsequent echo commands
if [ $echo_disable == 0 ]; then
 echo "Safe to display on Xterm"
fi

Dalam csh:

if ($TERM == "xterm") then
  echo "Xterm display identified: echo enabled"
  set echo_disable = "0"
else
  set echo_disable = "1"
endif

# Use the following for all subsequent echo commands
if !( "$echo_disable" ) echo "Safe to display on Xterm"

Ini kekuatan yang agak kasar, tetapi berhasil.

Bob Noonan
sumber
Saya mencoba menggunakan kode ["$ SSH_TTY"] di atas dan ternyata hanya berfungsi untuk program klien sederhana seperti dempul. Ketika saya menggunakan NoMachine itu tidak memberikan output apa pun. Inilah sebabnya saya perlu memasukkan "xterm-256color" dalam kode di atas.
Bob Noonan
Cukup menarik, menggunakan "if ($? SSH_TTY) maka" juga tidak bekerja untuk VM csh saya. Saya memeriksa dan tidak ada variabel lingkungan SSH_TTY yang ditentukan. Jadi kode saya di atas mungkin bermanfaat bagi orang lain yang memiliki situasi serupa.
Bob Noonan
0

Inilah baris pertama dari .bashrcfile (default) saya :

# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

Pemeriksaan untuk sesi interaktif menghindari mengacaukan SCP, SFTP atau ssh remote-host commandmode.

Tanpa ini, jika file Anda .bashrcmenggunakan echoatau beberapa hal lain mencetak di stdout, Anda mungkin mendapatkan kesalahan seperti ini:

  • SFTP: Received message too long 168435779
  • SCP: protocol error: unexpected <newline>
Totor
sumber