TL; DR
Kullanmayın -t. -tUzak ana bilgisayarda bir sözde terminal içerir ve yalnızca görsel uygulamaları bir terminalden çalıştırmak için kullanılmalıdır.
açıklama
Satır besleme karakteri (aynı zamanda newline olarak da bilinir \n) veya terminale gönderildiğinde terminale imlecini aşağı doğru hareket ettirmesini söyleyen karakterdir.
Yine de, seq 3bir terminalde koşarken , seqşöyle bir 1\n2\n3\nşeye yazdığı yer /dev/pts/0:
1
2
3
fakat
1
2
3
Neden?
Aslında seq 3(veya ssh host seq 3bu konuda) yazdığında 1\n2\n3\n, terminal görür 1\r\n2\r\n3\r\n. Yani, satır akışları satırbaşına (ki bu sırada terminaller imlecini ekranın soluna taşır) ve satır akışına çevrilmiştir.
Bu terminal aygıt sürücüsü tarafından yapılır. Daha doğrusu, terminalde (veya sözde terminal) cihazın hat disiplini, çekirdeğin içinde bulunan bir yazılım modülüdür.
Bu çizgi disiplininin davranışını sttykomutla kontrol edebilirsiniz . LF-> çevirisi ile CRLFaçıldı
stty onlcr
(genellikle varsayılan olarak etkindir). Şununla kapatabilirsiniz:
stty -onlcr
Veya tüm çıktı işlemlerini şu yöntemlerle kapatabilirsiniz:
stty -opost
Bunu yapar ve koşarsanız seq 3, göreceksiniz:
$ stty -onlcr; seq 3
1
2
3
beklenildiği gibi.
Şimdi, ne zaman:
seq 3 > some-file
seqartık bir terminale yazmıyor, bir dosyaya yazıyor, çeviri yapılmadı. Yani some-fileiçermiyor 1\n2\n3\n. Çeviri sadece bir terminal cihaza yazarken yapılır. Ve sadece gösterim için yapıldı.
Benzer şekilde, ne zaman:
ssh host seq 3
ssh1\n2\n3\nne sshçıktısı olursa olsun ne yazıyor .
Aslında olan, seq 3komutun hoststdout ile bir boruya yönlendirilmiş olarak çalıştırılmasıdır . Ana sshbilgisayardaki sunucu borunun diğer ucunu okur ve şifreli kanal üzerinden sshistemcinize gönderir ve sshmüşteri bu durumda stdout'una yazar, bu durumda, ekrana LFçevrildiği sahte terminal bir cihaz CRLF.
Birçok etkileşimli uygulama, stdout'ları bir terminal olmadığında farklı davranır. Örneğin, eğer çalıştırırsanız:
ssh host vi
vibeğenmedi, çıktısının bir boruya gitmesini sevmiyor. Örneğin imleç konumlandırma kaçış dizilerini anlayabilen bir cihazla konuşmadığını düşünüyor.
Yani sshbunun için bir -tseçenek var. Bu seçenekle, ana bilgisayardaki ssh sunucusu sahte terminal cihazı oluşturur ve bunun stdout (ve stdin ve stderr) olmasını sağlar vi. Ne vio, terminal cihazının yazdığı uzak uçbirimsi hat disiplin geçer ve tarafından okunur sshsunucu ve şifreli kanal üzerinden gönderilen sshistemci. Daha önce olduğu gibi aynı, bir boru kullanmak yerine , sshsunucunun sahte terminal kullanması dışında .
Diğer fark, müşteri tarafında, sshistemcinin terminali rawmoda ayarlamasıdır. Bu orada çeviri yapılmadığı anlamına gelir ( opostdevre dışı bırakılmış ve ayrıca giriş tarafı davranışları). Örneğin, yazarken Ctrl-C, kesmek yerine ssh, bu ^Ckarakter uzak tarafa gönderilir, burada uzak sözde terminalin çizgi disiplini, kesmeyi uzak komutuna gönderir .
Ne zaman yaparsın:
ssh -t host seq 3
seq 31\n2\n3\nBir sözde terminal aygıtı olan stdout'una yazar . Yüzünden onlcrtercüme olduğunu, ana bilgisayarda için 1\r\n2\r\n3\r\nve şifreli kanal üzerinden size gönderilen. Kendi tarafında çeviri ( onlcrdevre dışı) yoktur, bu yüzden 1\r\n2\r\n3\r\ndokunulmaz ( rawmod nedeniyle ) ve terminal emülatörünüzün ekranında doğru şekilde görüntülenir.
Şimdi, eğer yaparsan:
ssh -t host seq 3 > some-file
Yukarıdan fark yok. sshaynı şeyi yazacak:, 1\r\n2\r\n3\r\nama bu sefer içine some-file.
Yani temelde LF, çıktısının tümü girdi seqdiline CRLFçevrildi some-file.
Bunu yaparsanız aynı:
ssh -t host cat remote-file > local-file
Tüm LFkarakterler (0x0a bayt) CRLF'ye (0x0d 0x0a) çevrilmiştir.
Muhtemelen dosyanızdaki bozulmanın nedeni budur. İkinci daha küçük dosya durumunda, dosya 0x0a bayt içermez, bu nedenle bozulma olmaz.
Farklı tty ayarlarıyla farklı yolsuzluk türleri alabileceğinizi unutmayın. Başka bir olası yolsuzluk türü -t, eğer başlangıç dosyalarınız host( ~/.bashrc, ~/.ssh/rc...) 'ın stderr'lerine bir şeyler yazıyorsa, çünkü -tuzak kabuğun stdout ve stderr'leri stdout ile birleştirilir ssh(ikisi de sözde olurlar) -terminal cihaz).
Uzaktan kumandanın catorada bir terminal cihazına çıkış yapmasını istemezsiniz .
İstediğiniz:
ssh host cat remote-file > local-file
Yapabilirsin:
ssh -t host 'stty -opost; cat remote-file` > local-file
İşe yarayacak ( yukarıda tartışılan stderr yolsuzluk vakası dışında ), ancak bu gereksiz sözde terminal-terminal katmanını çalıştıracağınız için bile alt-optimal olacaktır host.
Biraz daha eğlenceli:
$ ssh localhost echo | od -tx1
0000000 0a
0000001
TAMAM.
$ ssh -t localhost echo | od -tx1
0000000 0d 0a
0000002
LF çevrildi CRLF
$ ssh -t localhost 'stty -opost; echo' | od -tx1
0000000 0a
0000001
Tekrar tamam.
$ ssh -t localhost 'stty olcuc; echo x'
X
Bu, terminal hattı disiplini tarafından yapılabilecek bir çıktı son işleme biçimidir.
$ echo x | ssh -t localhost 'stty -opost; echo' | od -tx1
Pseudo-terminal will not be allocated because stdin is not a terminal.
stty: standard input: Inappropriate ioctl for device
0000000 0a
0000001
sshSunucuya, kendi girişi bir terminal olmadığında sahte terminal kullanmasını reddetti. -ttBununla zorlayabilirsin :
$ echo x | ssh -tt localhost 'stty -opost; echo' | od -tx1
0000000 x \r \n \n
0000004
Çizgi disiplini giriş tarafında çok daha fazlasını yapar.
Burada, echogirişini okumuyor veya çıktısı istenmiyor x\r\n\n, peki bu nereden geliyor? Bu echo, uzak sözde terminalin ( stty echo) yerel adresidir . sshSunucu besleyen x\nuzak sözde-terminalinin ana yanına istemciden okuyun. Ve bunun çizgi disiplini onu geri yansıtıyor (daha önce stty opostçalıştırma, bu yüzden görüyoruz CRLFve görmüyoruz LF). Bu, uzak uygulamanın stdin'den bir şey okuyup okumamasından bağımsızdır.
$ (sleep 1; printf '\03') | ssh -tt localhost 'trap "echo ouch" INT; sleep 2'
^Couch
0x3Karakter geri yankılandı ^C( ^ve C) nedeniyle stty echoctlkabuk ve uyku nedeniyle SIGINT al stty isig.
Öyleyse:
ssh -t host cat remote-file > local-file
yeterince kötü ama
ssh -tt host 'cat > remote-file' < local-file
dosyaları diğer tarafa aktarmak için çok daha kötüdür. Tüm özel karakterleri ile> LF çeviri değil, aynı zamanda sorunları (- Bazı CR alırsınız ^C, ^Z, ^D, ^?, ^S...) ve ayrıca uzaktan catsonu ne zaman eof görmez local-fileulaşıldığında, sadece ^Dbir sonraki gönderilir \r, \nveya terminalinizde ^Dolduğu gibi başka cat > file.
-ttransferini kırar seçeneği. Çok özel bir sebepten gerekmedikçe-tveya kullanmayın-T. Varsayılan durum çoğu durumda işe yarar, bu seçeneklere çok nadir ihtiyaç duyulur.