Ssh'ye bir terminal tahsis etmemenin faydası nedir?


66

Arada bir olurum gibi bir şey yapacağım

ssh user@host sudo thing

ve ssh'nin varsayılan olarak sahte bir tty ayırmadığını hatırlattı. Neden yapmıyor Ben diğer ad ne faydalar ı kaybetme olacağını sshhiç ssh -t?


1
> Ssh'nin bir sualtı tahsis etmediği hatırlatıldı Ne olur? Sorunun ne olduğunu anlamak, soruyu zenginleştirir.
Hava

5
@Hava Düzeltmeye çalıştığım bir sorun yok. Ssh'ın nasıl uygulandığının, anlamaya çalıştığım bir seçenek vardı. Soru çok açık ve Andrew B'nin cevabı bu soruyu güzel bir şekilde ele alıyor. Cevap şöyle özetlenebilir: Koşmak ssh -ther zaman kötüdür, çünkü bazı komutların garip şekillerde kırılmasına neden olabilir. Oysa bir tane olmadan PTY gerektiren bir komutu çalıştırmak, bir terminale ihtiyacınız olduğu konusunda net bir hata mesajı verir.
Chas. Owens

Yanıtlar:


73

Birincil fark, etkileşim kavramıdır . Komut dosyası içinde yerel olarak komutları çalıştırmak, bunları kendiniz yazmak gibi. Uzak bir komutun varsayılanı seçmesi gerekir ve etkileşimli olmayan en güvenli yöntemdir. (ve genellikle en dürüst)

STDIN

  • Bir PTY tahsis edilmişse, uygulamalar bunu algılayabilir ve kullanıcıdan herhangi bir şeyi bozmadan ek giriş talep etmesinin güvenli olduğunu bilir. Terminal yok ise, kullanıcının giriş yapmasını isteme adımını atlayacak birçok program vardır ve bu iyi bir şeydir. Aksi takdirde komut dosyalarının gereksiz yere asılmasına neden olur.
  • Girişiniz, komut süresince uzak sunucuya gönderilecektir. Bu kontrol dizileri içerir. Bir Ctrl-cmola normalde ssh komutundaki bir döngünün hemen kırılmasına neden olsa da , kontrol dizileriniz bunun yerine uzak sunucuya gönderilir. Bu, kontrol ssh komutunu bıraktığında , ancak bir sonraki ssh komutunun başlamasından önce geldiğinden emin olmak için tuş vuruşunu "çekiçlemeye" ihtiyaç duyar .

ssh -tCrons gibi katılımsız betiklerde kullanmamaya dikkat ederdim . Uzak bir komutun girdi için etkileşimli davranmasını isteyen etkileşimli olmayan bir kabuk, her türlü sorunu soruyor.

Ayrıca kendi kabuk komut dosyalarınızda bir terminalin varlığını test edebilirsiniz. STDIN'i bash'ın yeni sürümleriyle test etmek için:

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

STDOUT

  • Aliasing zaman sshiçin ssh -t, kendi çizgi biter fazladan satırbaşı almak için bekleyebilirsiniz. Size görünmeyebilir, ama orada; ^Mborulandığı zaman görünecek cat -e. Ardından, bu kontrol kodunun değişkenlerinize atanmamasını sağlama çabalarını harcamalısınız, özellikle de bu çıkışı bir veritabanına ekleyecekseniz.
  • Programların, dosya yeniden yönlendirmesi için uygun olmayan çıktılar üretebileceklerini varsayma riski de vardır. Normalde STDOUT'u bir dosyaya yönlendirmek isteseniz, program STDOUT'nuzun bir terminal olmadığını ve herhangi bir renk kodunu çıkardığını fark eder. STDOUT yönlendirmesi, ssh istemcisinin çıktısından geliyorsa ve istemcinin uzak ucuyla ilişkili bir PTY varsa, uzak programlar böyle bir ayrım yapamaz ve çıktı dosyanızda terminal çöpüyle sonuçlanır. Çıktıyı bağlantının uzak ucundaki bir dosyaya yeniden yönlendirmek beklendiği gibi çalışmalıdır.

İşte önceki ile aynı bash testi, ancak STDOUT için:

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

Bu sorunların üstesinden gelmek mümkün olsa da, kaçınılmaz olarak, etraflarındaki komut dosyalarını tasarlamayı unutacaksınız. Hepimiz bir noktada yapıyoruz. Ekibiniz üyeleri de / fark bu takma adı zaman da sizin için sorun yaratacak olan yerde olduğunu unutmayın olmayabilir onlar sizin takma ad kullanmak komut yazmak.

Aliasing , en azından sürpriz tasarım ilkesini ihlal sshedeceğiniz ssh -tbir durum ; insanlar beklemeyecekleri sorunlarla karşılaşacaklar ve onlara neyin neden olduğunu anlayamayabilirler.


9
Neredeyse bunu yapan bir takım üzerinde çalıştığım izlenimi
Andrew B

Bu cevap kapsamında kapsamda, bu harika. Fakat sorunun daha geniş bir kapsamı vardı, temel olarak TÜM farkları (ne bekleyeceğinizi) bilmek istiyordu. Ek bilgi: İşlem düzeyinde, -T İLK bir tty tahsis eder ve sonra bir kabuk çalıştırır (yol boyunca, kaynak / etc / profile ve ~ / .bash_profile kaynaklanıyor) ve THEN komutu çalıştırır. -T olmadan, ssh kaynak farklı env dosyalarını (/etc/bash.bashrc, sonra ~ / .bashrc) INSTEAD ve sonra da komutunuzu çalıştırır. Bu, her biri için çok farklı davranışlar görebileceğiniz anlamına gelir: kısaltılmış $ PATH, belki de bir bash 'unary' hatası çünkü varsayalım ENV var yok ...
Scott Prive

@Crossfit Oturum açma kabukları konusunu başka bir cevabın yorumlarında yer almayan konulara dahil ettik, ancak OP zaten kendi ihtiyaçları için sorulan soruyu çoktan ele almıştı, çünkü çevresel farklılıkların kapsamlı bir dağılımına girmedik. Lütfen, bu soru-Cevap bölümüne katılan diğer kişilere yardımcı olabileceğinden, odanın nerede olduğunu görmek için ayrıntı eklemek için çekinmeyin.
Andrew B,

33

SSH çıkış karakterleri ve ikili dosya aktarımı

Diğer yanıtlar söz edilmemiştir bir avantajı, işletim sırasında yani bir psödo-terminal olmadan , SSH çıkış karakterleri gibi ~Cedilir desteklenmez ; bu, programların bu dizileri içerebilecek ikili dosyaları aktarmasını güvenli kılar.

Kavramın ispatı

Bir sözde terminal kullanarak bir ikili dosya kopyalayın:

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

Sözde-terminal kullanmadan bir ikili dosyayı kopyala:

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

İki dosya aynı değil:

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

Bir sözde terminal ile kopyalanan biri bozuk:

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

diğeri değil:

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

SSH üzerinden dosya aktarma

Bu gibi programlar için özellikle önemlidir scpveya rsyncveri aktarımı için SSH kullanmak. SCP protokolünün nasıl çalıştığının bu ayrıntılı açıklaması, SCP protokolünün bir metinsel protokol mesajı ve ikili dosya verisi karışımından oluştuğunu açıklar.


OpenSSH sizi kendinizden korumanıza yardımcı olur

-tBayrak kullanılsa bile , OpenSSH sshistemcisinin, stdinakışının bir terminal olmadığını tespit ederse sahte terminal tahsis etmeyi reddetmesi dikkat çekicidir :

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

OpenSSH istemcisini, sözde bir terminali aşağıdakilerle ayırması için zorlayabilirsiniz -tt:

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

Her iki durumda da, bu (makul) eğer umursamıyor stdoutya stderryönlendirildi şunlardır:

$ ssh -t anthony@remote_host 'echo $TERM' >| ssh_output
Connection to remote_host closed.

2
Bu cevabı eklediğim için çok ilginç bir nokta oldu!
Jenny D

4

Uzaktaki ana makinede bu ayar ile yapmak zorundayız:

/etc/sudoers
...
Defaults requiretty

Sudo olmadan

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

Ve sudo ile

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

Sudo ile ekstra taşıma iadesi alıyoruz

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

Çözüm, yeni satır çevirisini satır başı satırsonuna ile devre dışı bırakmaktır.stty -onlcr

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

1
Güzel ama çıktı girintili /: Otomatik araba geri getirip getiremeyeceğinizi biliyor musunuz (unix benzeri)?
Boop

1

Geriye dönük uyumluluk hakkında düşünün.

2 birincil ssh modu, tty ile etkileşimli oturum açma ve tty olmadan belirtilen komuttur, çünkü bunlar tam yetenekleridir rloginve rshsırasıyla. Yedeklemenin başarılı olması için rlogin/ rshözelliklerinin bir üst kümesi / özelliklerinin sağlanması gerekiyor.

Böylece ssh doğmadan önce varsayılanlara karar verildi. "Bir komut belirtmek ve bir tty almak istiyorum" gibi kombinasyonlara yeni seçeneklerle erişilmesi gerekiyordu. En azından şimdi kullandığımızın aksine bu seçeneğe sahip olduğumuz için mutlu olun rsh. Şifreli bağlantılar elde etmek için kullanışlı özellikleri takas etmedik. Bonus özelliklerimiz var!


0

Kimden 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.

Bu, uzak sunucuya bir "kabuk" türü almanızı sağlar. Do sunucuları için değil SSH kabuk erişim izni ancak izin bu bayrağı kullanarak neden olacaktır bağlantınızı reddetmek için sunucu (yani Github SFTP erişimi için bilinen bir örneğidir).

Bu kabuk aynı zamanda tüm çevresel değişkenlerinize de sahiptir ( $PATHbu nedenle), komut dosyalarını çalıştırmak genellikle çalışmak için bir tty'ye ihtiyaç duyar.


1
Bu soruya cevap vermiyor. Sahte bir tty nasıl tahsis edileceğini zaten biliyorum. Neden her zaman bir tane ayırmamam gerektiğini bilmek istiyorum.
Chas. Owens

1
@ Ben cevap belirttiği gibi Chas.Owens Çünkü bazı SSH sunucuları do not tty erişime izin ve sunucudan bir talep varsa o bağlantıyı kesmek gerekir.
Nathan C

5
Sanırım terminolojinizden bazılarının kafasını karıştırıyor olabilirsiniz. Bu bir kabuk değil çünkü PTY onunla ilişkilendirilmiş. Orada kabuk Üç tür genel şunlardır: non-interactive, interactiveve login. logindiğer iki kabuk tipinin ek bir özelliğidir. Bu üçünün izinleri, oturum açtıklarında hangi dosyaların kaynaklandığını belirler, bu da ortamın nasıl başlatılacağını etkiler. (bahsettiğiniz gibi değişkenler)
Andrew B,

3
@AndrewB Haklısın ... Ben de bu sorudan bir şey öğrendim. :)
Nathan C
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.