Apa manfaat tidak mengalokasikan terminal di ssh?

66

Sesekali saya akan melakukan sesuatu seperti

ssh user@host sudo thing

dan saya diingatkan bahwa ssh tidak mengalokasikan pseudo-tty secara default. Kenapa tidak? Apa manfaat yang akan hilang jika saya tidak sshmau ssh -t?

Chas. Owens
sumber
1
> Saya diingatkan bahwa ssh tidak mengalokasikan psuedo-tty Apa yang terjadi? Itu akan memperkaya pertanyaan untuk memahami apa masalahnya.
Air
5
@ Air Tidak ada masalah yang saya coba perbaiki. Ada pilihan dalam bagaimana ssh diimplementasikan yang saya coba pahami. Pertanyaannya sangat jelas dan jawaban oleh Andrew B menjawab pertanyaan itu dengan baik. Jawabannya dapat diringkas seperti ini: menjalankan ssh -tselalu buruk karena dapat menyebabkan beberapa perintah rusak dengan cara yang aneh. Sedangkan, menjalankan perintah yang membutuhkan PTY tanpa satu menghasilkan pesan kesalahan yang jelas bahwa Anda memerlukan terminal.
Chas. Owens

Jawaban:

73

Perbedaan utama adalah konsep interaktivitas . Ini mirip dengan menjalankan perintah secara lokal di dalam skrip, vs. mengetiknya sendiri. Ini berbeda karena perintah jarak jauh harus memilih default, dan non-interaktif paling aman. (dan biasanya paling jujur)

STDIN

  • Jika PTY dialokasikan, aplikasi dapat mendeteksi ini dan tahu bahwa aman untuk meminta pengguna untuk input tambahan tanpa merusak barang-barang. Ada banyak program yang akan melewatkan langkah meminta pengguna untuk input jika tidak ada terminal, dan itu hal yang baik. Itu akan menyebabkan skrip hang yang tidak perlu jika tidak.
  • Input Anda akan dikirim ke server jarak jauh selama durasi perintah. Ini termasuk urutan kontrol. Sementara Ctrl-cistirahat biasanya akan menyebabkan perulangan pada perintah ssh untuk segera rusak, urutan kontrol Anda akan dikirim ke server jauh. Ini menghasilkan kebutuhan untuk "memalu" keystroke untuk memastikan bahwa itu tiba ketika kontrol meninggalkan perintah ssh, tetapi sebelum perintah ssh berikutnya dimulai.

Saya akan memperingatkan agar tidak menggunakan ssh -tskrip yang tidak dijaga, seperti crons. Shell non-interaktif yang meminta perintah jarak jauh untuk bertindak secara interaktif untuk input meminta semua jenis masalah.

Anda juga dapat menguji keberadaan terminal di skrip shell Anda sendiri. Untuk menguji STDIN dengan versi bash yang lebih baru:

# fd 0 is STDIN
[ -t 0 ]; echo $?

STDOUT

  • Ketika aliasing sshto ssh -t, Anda dapat mengharapkan untuk mendapatkan carriage return tambahan di jalur Anda. Mungkin tidak terlihat oleh Anda, tetapi ada di sana; itu akan muncul seperti ^Mketika disalurkan ke cat -e. Anda kemudian harus mengeluarkan upaya tambahan untuk memastikan bahwa kode kontrol ini tidak ditugaskan untuk variabel Anda, terutama jika Anda akan memasukkan output itu ke dalam database.
  • Ada juga risiko bahwa program akan menganggap mereka dapat membuat output yang tidak ramah untuk pengalihan file. Biasanya jika Anda mengarahkan ulang STDOUT ke file, program akan mengenali bahwa STDOUT Anda bukan terminal dan menghilangkan kode warna apa pun. Jika pengalihan STDOUT berasal dari output klien ssh dan ada PTY yang terkait dengan ujung jarak jauh klien, program jarak jauh tidak dapat membuat perbedaan seperti itu dan Anda akan berakhir dengan sampah terminal di file output Anda. Mengarahkan output ke file di ujung koneksi yang jauh harus tetap berfungsi seperti yang diharapkan.

Berikut ini adalah tes bash yang sama seperti sebelumnya, tetapi untuk STDOUT:

# fd 1 is STDOUT
[ -t 1 ]; echo $?

Meskipun mungkin untuk mengatasi masalah ini, Anda pasti akan lupa untuk merancang skrip di sekitar mereka. Kita semua melakukannya pada titik tertentu. Anggota tim Anda mungkin juga tidak menyadari / ingat bahwa alias ini sudah ada, yang pada gilirannya akan menimbulkan masalah bagi Anda ketika mereka menulis skrip yang menggunakan alias Anda.

Mengasingkan sshdiri ssh -tmerupakan kasus dimana Anda akan melanggar prinsip desain yang paling tidak mengejutkan ; orang akan menghadapi masalah yang tidak mereka harapkan dan mungkin tidak mengerti apa yang menyebabkannya.

Andrew B
sumber
9
Seseorang hampir mendapat kesan bahwa saya telah bekerja di tim yang telah melakukan ini ...
Andrew B
Pada ruang lingkup yang dicakup oleh jawaban ini, ini luar biasa. Tetapi pertanyaan itu memiliki ruang lingkup yang lebih luas, pada dasarnya ingin mengetahui SEMUA perbedaan (apa yang diharapkan). Info tambahan: Pada tingkat proses, -t akan PERTAMA mengalokasikan tty dan MAKA menjalankan shell (sepanjang jalan, sumber / etc / profile dan ~ / .bash_profile) dan KEMUDIAN jalankan perintah. Tanpa -t, ssh akan MENGINSTAL sumber file env yang berbeda (/etc/bash.bashrc, lalu ~ / .bashrc) dan MAKA menjalankan perintah Anda. Ini berarti Anda dapat melihat perilaku yang sangat berbeda di masing-masing: $ PATH lebih pendek, mungkin kesalahan 'unary' bash karena ENV var Anda berasumsi tidak ada ...
Scott Prive
@Crossfit Kami membahas topik shell login vs. non dalam komentar jawaban lain, tetapi kami tidak membahas secara mendalam perbedaan lingkungan karena OP telah mempertimbangkan pertanyaan yang dijawab untuk kebutuhan khusus mereka. Jangan ragu untuk menambahkan detail di mana Anda melihat ruang untuk melakukannya karena dapat membantu orang lain yang menemukan Q&A ini.
Andrew B
33

SSH melepaskan karakter dan mentransfer file biner

Salah satu keuntungan yang belum disebutkan dalam jawaban yang lain adalah bahwa ketika beroperasi tanpa pseudo-terminal , SSH yang melarikan diri karakter seperti ~Cyang tidak didukung ; ini membuatnya aman bagi program untuk mentransfer file biner yang mungkin mengandung urutan ini.

Bukti dari konsep

Salin file biner menggunakan terminal semu:

$ ssh -t anthony@remote_host 'cat /usr/bin/free' > ~/free
Connection to remote_host closed.

Salin file biner tanpa menggunakan pseudo-terminal:

$ ssh anthony@remote_host 'cat /usr/bin/free' > ~/free2

Kedua file tidak sama:

$ diff ~/free*
Binary files /home/anthony/free and /home/anthony/free2 differ

Yang disalin dengan terminal semu rusak:

$ chmod +x ~/free*
$ ./free
Segmentation fault

sementara yang lain tidak:

$ ./free2
             total       used       free     shared    buffers     cached
Mem:       2065496    1980876      84620          0      48264    1502444
-/+ buffers/cache:     430168    1635328
Swap:      4128760        112    4128648

Mentransfer file melalui SSH

Ini sangat penting untuk program seperti scpatau rsyncyang menggunakan SSH untuk transfer data. Ini penjelasan rinci tentang bagaimana protokol SCP bekerja menjelaskan bagaimana protokol SCP terdiri dari campuran pesan protokol tekstual dan data file biner.


OpenSSH membantu melindungi Anda dari diri sendiri

Perlu dicatat bahwa meskipun -tflag digunakan, sshklien OpenSSH akan menolak untuk mengalokasikan pseudo-terminal jika mendeteksi bahwa stdinalirannya bukan terminal:

$ echo testing | ssh -t anthony@remote_host 'echo $TERM'
Pseudo-terminal will not be allocated because stdin is not a terminal.
dumb

Anda masih dapat memaksa klien OpenSSH untuk mengalokasikan pseudo-terminal dengan -tt:

$ echo testing | ssh -tt anthony@remote_host 'echo $TERM'
xterm

Dalam kedua kasus, itu (masuk akal) tidak peduli jika stdoutatau stderrdiarahkan:

$ ssh -t anthony@remote_host 'echo $TERM' >| ssh_output
Connection to remote_host closed.
Anthony G - keadilan untuk Monica
sumber
2
Itu adalah hal yang sangat menarik yang tidak saya pertimbangkan, terima kasih telah menambahkan jawaban ini!
Jenny D mengatakan Reinstate Monica
4

Pada host jarak jauh kita harus lakukan dengan pengaturan ini:

/etc/sudoers
...
Defaults requiretty

Tanpa sudo

$ ssh -T user@host echo -e 'foo\\nbar' | cat -e
foo$
bar$

Dan dengan sudo

$ ssh -T user@host sudo echo -e 'foo\\nbar' | cat -e
sudo: sorry, you must have a tty to run sudo

Dengan sudo kita mendapatkan kereta ekstra

$ ssh -t user@host sudo echo -e 'foo\\nbar' | cat -e
foo^M$
      bar^M$
            Connection to localhost closed.

Solusinya adalah dengan menonaktifkan terjemahan baris baru ke carriage return-newline withstty -onlcr

$ ssh -t user@host stty -onlcr\; sudo echo -e 'foo\\nbar' | cat -e
foo$
    bar$
        Connection to localhost closed.
Christophe Morio
sumber
1
Bagus tapi hasilnya indentasi /: Apakah Anda tahu kalau Anda bisa mengembalikan otomatis (seperti unix)?
Boop
1

Pikirkan tentang kompatibilitas ke belakang.

2 mode utama ssh adalah login interaktif dengan tty, dan perintah khusus tanpa tty, karena itu adalah kemampuan yang tepat dari rlogindan rshmasing - masing. ssh diperlukan untuk menyediakan superset rlogin/ rshfitur agar berhasil sebagai pengganti.

Jadi defaultnya diputuskan sebelum ssh lahir. Kombinasi seperti "Saya ingin menentukan perintah dan mendapatkan tty" harus diakses dengan opsi baru. Bersyukurlah bahwa setidaknya kita memiliki opsi itu sekarang, tidak seperti ketika kita menggunakan rsh. Kami tidak menukar fitur yang berguna untuk mendapatkan koneksi terenkripsi. Kami mendapat fitur bonus!


sumber
0

Dari man ssh:

 -t      Force pseudo-tty allocation.  This can be used to execute arbi-
         trary screen-based programs on a remote machine, which can be
         very useful, e.g. when implementing menu services.  Multiple -t
         options force tty allocation, even if ssh has no local tty.

Ini memungkinkan Anda mendapatkan semacam "shell" ke server jarak jauh. Untuk server yang tidak memberikan akses shell tetapi mengizinkan SSH (yaitu, Github adalah contoh yang dikenal untuk akses SFTP), menggunakan flag ini akan menyebabkan server menolak koneksi Anda.

Shell juga memiliki semua variabel lingkungan Anda (seperti $PATH) sehingga mengeksekusi skrip umumnya membutuhkan tty untuk bekerja.

Nathan C
sumber
1
Ini tidak menjawab pertanyaan. Saya sudah tahu bagaimana cara mengalokasikan pseudo-tty. Saya ingin tahu mengapa saya tidak selalu mengalokasikannya.
Chas. Owens
1
@ Chas.Owens Karena, seperti yang saya tunjukkan dalam jawaban beberapa server SSH tidak mengizinkan akses tty dan itu akan menjatuhkan koneksi jika Anda meminta satu dari server.
Nathan C
5
Saya pikir Anda mungkin membuat beberapa terminologi Anda bingung. Ini bukan shell hanya karena PTY dikaitkan dengannya. Pada umumnya ada tiga jenis shell: non-interactive, interactive, dan login. loginadalah karakteristik tambahan dari dua jenis shell lainnya. Permutasi dari ketiga menentukan file mana yang bersumber pada login, yang pada gilirannya mempengaruhi bagaimana lingkungan akan diinisialisasi. (variabel, seperti yang Anda sebutkan)
Andrew B
3
@AndrewB Anda benar ... Saya belajar sesuatu dari pertanyaan ini juga. :)
Nathan C