এই বাইনারি ফাইলটি কেন "ssh -t" এর উপর স্থানান্তরিত হচ্ছে?


29

আমি এসএসএইচে ফাইলগুলি অনুলিপি করার চেষ্টা করছি , তবে scpআমার সঠিক ফাইল নামটি না জানার কারণে ব্যবহার করতে পারছি না। যদিও ছোট বাইনারি ফাইল এবং পাঠ্য ফাইলগুলি সূক্ষ্ম স্থানান্তর করে, বড় বাইনারি ফাইলগুলি পরিবর্তিত হয়। সার্ভারে ফাইলটি এখানে:

remote$ ls -la
-rw-rw-r--  1 user user 244970907 Aug 24 11:11 foo.gz
remote$ md5sum foo.gz 
9b5a44dad9d129bab52cbc6d806e7fda foo.gz

ফাইলটি সরানোর পরে এখানে দেওয়া হয়েছে:

local$ time ssh me@server.com -t 'cat /path/to/foo.gz' > latest.gz

real    1m52.098s
user    0m2.608s
sys     0m4.370s
local$ md5sum latest.gz
76fae9d6a4711bad1560092b539d034b  latest.gz

local$ ls -la
-rw-rw-r--  1 dotancohen dotancohen 245849912 Aug 24 18:26 latest.gz

নোট করুন যে ডাউনলোড করা ফাইলটি সার্ভারে থাকা ফাইলের চেয়ে বড় ! তবে, আমি যদি খুব ছোট ফাইল দিয়েও একই কাজ করি, তবে সবকিছু প্রত্যাশার মতো কাজ করে:

remote$ echo "Hello" | gzip -c > hello.txt.gz
remote$ md5sum hello.txt.gz
08bf5080733d46a47d339520176b9211  hello.txt.gz

local$ time ssh me@server.com -t 'cat /path/to/hello.txt.gz' > hi.txt.gz

আসল 0m3.041 গুলি ব্যবহারকারীর 0m0.013 গুলি 0 মি0.005 এস

local$ md5sum hi.txt.gz
08bf5080733d46a47d339520176b9211  hi.txt.gz

উভয় ফাইলের আকার এই ক্ষেত্রে 26 বাইট।

ছোট ফাইলগুলি কেন সূক্ষ্ম স্থানান্তর করতে পারে, তবে বড় ফাইলগুলি এতে কিছু বাইট যুক্ত করতে পারে?


10
এটি -tবিকল্প, যা স্থানান্তরকে ভেঙে দেয়। আপনার কোনও নির্দিষ্ট কারণে প্রয়োজন না হলে ব্যবহার করবেন না -tবা -T। ডিফল্ট বিস্তৃত ক্ষেত্রে কাজ করে, সুতরাং এই বিকল্পগুলি খুব কমই প্রয়োজন হয়।
ক্যাস্পারড

3
কখনও ভাবিনি যে আমি এই শতাব্দীতে এটি বলব, তবে আপনি ssh -t catফাইল স্থানান্তর করার একমাত্র উপায় যদি আপনি ইউনকোড এবং ইউডিকোড চেষ্টা করতে পারেন ।
মার্ক প্লটনিক নিকট

1
@ মারকপ্লটনিক ইউনকোড / ইউডিকোডের আধুনিক সংস্করণটির নাম এখন বেস 64 /
বেস64

উত্তর:


60

টি এল; ডিআর

ব্যবহার করবেন না -t-tদূরবর্তী হোস্টে সিউডো-টার্মিনাল জড়িত এবং কেবলমাত্র টার্মিনাল থেকে ভিজ্যুয়াল অ্যাপ্লিকেশন চালানোর জন্য ব্যবহার করা উচিত।

ব্যাখ্যা

লাইনফিড অক্ষর (নিউলাইন হিসাবেও পরিচিত বা \n) টার্মিনালে প্রেরণ করা হলে টার্মিনালটিকে তার কার্সারটি নামিয়ে আনতে বলে।

তবুও, আপনি যখন seq 3কোনও টার্মিনালে চালান , seqসেইখানেই 1\n2\n3\nএমন /dev/pts/0কোনও কিছু লেখেন , আপনি দেখতে পাবেন না:

1
 2
  3

কিন্তু

1
2
3

তা কেন?

প্রকৃতপক্ষে, যখন seq 3(বা ssh host seq 3সেই বিষয়টির জন্য) লেখেন 1\n2\n3\n, টার্মিনালটি দেখে 1\r\n2\r\n3\r\n। এটি হ'ল লাইন-ফিডগুলি ক্যারিজ-রিটার্নে অনুবাদ করা হয়েছে (যার উপরে টার্মিনালগুলি তাদের কার্সারটিকে স্ক্রিনের বাম দিকে ফিরিয়ে দেয়) এবং লাইন-ফিডে।

এটি টার্মিনাল ডিভাইস ড্রাইভার দ্বারা সম্পন্ন হয়। ঠিক ঠিক, টার্মিনাল (বা সিউডো-টার্মিনাল) ডিভাইসের লাইন-শৃঙ্খলা দ্বারা, একটি সফ্টওয়্যার মডিউল যা কার্নেলের মধ্যে থাকে।

আপনি sttyকমান্ডের সাহায্যে লাইন শৃঙ্খলার আচরণ নিয়ন্ত্রণ করতে পারেন । LF-> এর অনুবাদটি CRLFচালু হয়

stty onlcr

(যা সাধারণত ডিফল্টরূপে সক্ষম হয়)। আপনি এটি দিয়ে এটি বন্ধ করতে পারেন:

stty -onlcr

অথবা আপনি এর সাথে সমস্ত আউটপুট প্রসেসিং বন্ধ করতে পারেন:

stty -opost

আপনি যদি এটি করেন এবং চালনা করেন seq 3তবে আপনি দেখতে পাবেন:

$ stty -onlcr; seq 3
1
 2
  3

প্রত্যাশিত.

এখন, আপনি যখন করবেন:

seq 3 > some-file

seqএটি এখন টার্মিনালে লেখা হচ্ছে না, এটি একটি ফাইলে লেখা হচ্ছে, কোনও অনুবাদ করা হচ্ছে না। তাই some-fileধারণ করে 1\n2\n3\n। অনুবাদ কেবলমাত্র টার্মিনাল ডিভাইসে লেখার সময় করা হয়। এবং এটি কেবল প্রদর্শনের জন্যই করা হয়েছে।

একইভাবে, আপনি যখন করবেন:

ssh host seq 3

sshআউটপুট যা যায় 1\n2\n3\nতা নির্বিশেষে লিখছেন ssh

আসলে যা ঘটে তা হ'ল seq 3কমান্ডটি hostতার স্টাইডআউটটি পাইপের দিকে পুনঃনির্দেশিত করে চালানো হয় । sshহোস্ট সার্ভার পাইপের অন্য প্রান্তে পড়ে এবং এটি উপর আপনার টু এনক্রিপটেড চ্যানেলের পাঠাতে sshক্লায়েন্ট এবং sshক্লায়েন্ট এটা তার stdout- এ সম্মুখের দিকে একটি সিউডো-টার্মিনাল ডিভাইস, যেখানে লিখছেন, আপনার ক্ষেত্রে LFগুলি অনুবাদ করা হয় CRLFপ্রদর্শনের জন্য।

অনেকগুলি ইন্টারেক্টিভ অ্যাপ্লিকেশনগুলি তাদের স্টাডআউটটি টার্মিনাল না হলে আলাদা আচরণ করে। উদাহরণস্বরূপ, আপনি যদি চালান:

ssh host vi

viএটি পছন্দ করে না, এটি পাইপতে যাওয়ার ফলাফল পছন্দ করে না। এটি মনে করে যে এটি এমন কোনও ডিভাইসের সাথে কথা বলছে না যা উদাহরণস্বরূপ কার্সার পজিশনিং এস্কেপ সিকোয়েন্সগুলি বুঝতে সক্ষম।

সুতরাং যে জন্য বিকল্প sshআছে -t। এই বিকল্পের সাহায্যে, হোস্টের ssh সার্ভারটি সিউডো-টার্মিনাল ডিভাইস তৈরি করে এবং এর স্টাডআউট (এবং স্টিডিন এবং স্টডার) তৈরি করে vi। কি viযে টার্মিনাল ডিভাইসে লিখেছেন যে দূরবর্তী সিউডো-টার্মিনাল লাইন শৃঙ্খলা মাধ্যমে যায় এবং দ্বারা পড়া হয় sshসার্ভার এবং এনক্রিপ্ট পথের মাধ্যমে পাঠানো sshক্লায়েন্ট। এটি পাইপের ব্যবহারের পরিবর্তে পূর্বের মতোই , sshসার্ভারটি সিউডো-টার্মিনাল ব্যবহার করে

অন্য পার্থক্যটি হ'ল ক্লায়েন্টের পাশে sshক্লায়েন্টটি টার্মিনালটি rawমোডে সেট করে । এর অর্থ হ'ল সেখানে কোনও অনুবাদ করা হয়নি ( opostঅক্ষম এবং অন্যান্য ইনপুট-পার্শ্ব আচরণ)। উদাহরণস্বরূপ, আপনি টাইপ Ctrl-Cকরার সময়, বাধা দেওয়ার পরিবর্তে ssh, সেই ^Cঅক্ষরটি দূরবর্তী দিকে প্রেরণ করা হয়, যেখানে দূরবর্তী সিউডো-টার্মিনালের লাইন শৃঙ্খলাটি রিমোট কমান্ডটিতে বাধা প্রেরণ করে ।

যখন তুমি কর:

ssh -t host seq 3

seq 31\n2\n3\nতার স্টডআউটে লিখেছে , যা সিউডো-টার্মিনাল ডিভাইস। কারণ onlcrঅনূদিত পরার যে হোস্ট করার জন্য 1\r\n2\r\n3\r\nএবং এনক্রিপ্ট করা চ্যানেল উপরে পাঠানো হয়েছে। আপনার পক্ষে কোনও অনুবাদ নেই ( onlcrঅক্ষম), সুতরাং 1\r\n2\r\n3\r\nঅচ্ছুত ( rawমোডের কারণে ) এবং সঠিকভাবে আপনার টার্মিনাল এমুলেটরের স্ক্রিনে প্রদর্শিত হবে।

এখন, আপনি যদি:

ssh -t host seq 3 > some-file

উপরে থেকে কোনও পার্থক্য নেই। ssh: একই জিনিস লিখতে হবে 1\r\n2\r\n3\r\n, কিন্তু এই সময় some-file

সুতরাং মূলত সমস্ত LFআউটপুট এর মধ্যে seqঅনুবাদ করা CRLFহয়েছে some-file

আপনি যদি করেন তবে এটি একই রকম:

ssh -t host cat remote-file > local-file

সমস্ত LFঅক্ষর (0x0a বাইট) সিআরএলএফ (0x0d 0x0a) তে অনুবাদ করা হচ্ছে।

এটি সম্ভবত আপনার ফাইলটিতে দুর্নীতির কারণ। দ্বিতীয় ছোট ফাইলের ক্ষেত্রে এটি ঠিক ঘটে যে ফাইলটিতে 0x0a বাইট নেই, তাই কোনও দুর্নীতি নেই।

নোট করুন যে আপনি বিভিন্ন টাইটি সেটিংস সহ বিভিন্ন ধরণের দুর্নীতি পেতে পারেন। এর সাথে যুক্ত আরও একটি সম্ভাব্য ধরণের দুর্নীতি -tহ'ল যদি আপনার স্টার্টআপ ফাইলগুলি host( ~/.bashrc, ~/.ssh/rc...) তাদের স্টাডারকে কিছু লিখতে দেয় কারণ -tদূরবর্তী শেলটির স্টাডআউট এবং স্টাডার দিয়ে স্টেডআউটে একত্রিত হয়ে যায় ssh(তারা উভয়ই সিউডোতে যান -টার্মিনাল ডিভাইস)।

আপনি catকোনও টার্মিনাল ডিভাইসে রিমোটটি আউটপুট দিতে চান না ।

তুমি চাও:

ssh host cat remote-file > local-file

আপনি করতে পারেন:

ssh -t host 'stty -opost; cat remote-file` > local-file

এটি কাজ করবে ( উপরে আলোচিত স্ট্ডার দুর্নীতি মামলার লিখন ব্যতীত ) তবে এটি উপ-অনুকূল হবে কারণ আপনার অযৌক্তিক সিউডো-টার্মিনাল স্তরটি চলমান থাকে host


আরও কিছু মজা:

$ ssh localhost echo | od -tx1
0000000 0a
0000001

ঠিক আছে.

$ ssh -t localhost echo | od -tx1
0000000 0d 0a
0000002

LF অনুবাদ CRLF

$ ssh -t localhost 'stty -opost; echo' | od -tx1
0000000 0a
0000001

আবার ঠিক আছে।

$ ssh -t localhost 'stty olcuc; echo x'
X

এটি আউটপুট পোস্ট-প্রসেসিংয়ের অন্য রূপ যা টার্মিনাল লাইন শৃঙ্খলা দ্বারা করা যেতে পারে।

$ 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

sshসার্ভারকে সিউডো-টার্মিনালটি ব্যবহার করতে অস্বীকার করে যখন তার নিজস্ব ইনপুট টার্মিনাল নয়। আপনি -ttযদিও এটি দিয়ে জোর করতে পারেন :

$ echo x | ssh -tt localhost 'stty -opost; echo' | od -tx1
0000000   x  \r  \n  \n
0000004

লাইন শৃঙ্খলা ইনপুট দিকে আরও অনেক কিছু করে।

এখানে, echoএর ইনপুটটি পড়েন না বা আউটপুট জিজ্ঞাসা করা হয়নি x\r\n\nতবে তা কোথা থেকে আসে? echoএটি দূরবর্তী সিউডো-টার্মিনালের স্থানীয় ( stty echo)। sshসার্ভার খাওয়ানো হয় x\nএটি দূরবর্তী সিউডো-টার্মিনাল মালিক পাশ থেকে ক্লায়েন্ট থেকে পড়ুন। এবং এর লাইন শৃঙ্খলা এটি আবার প্রতিধ্বনিত করে (আগে stty opostচালানো হয় যার কারণে আমরা একটি দেখতে পাই CRLFএবং না LF)। এটি রিমোট অ্যাপ্লিকেশন স্টিডিনের কাছ থেকে কিছু পড়ে কিনা তা থেকে স্বাধীন।

$ (sleep 1; printf '\03') | ssh -tt localhost 'trap "echo ouch" INT; sleep 2'
^Couch

0x3চরিত্র হিসাবে আবার প্রতিধ্বনিত হয় ^C( ^এবং C) কারণ stty echoctlএবং শেল এবং ঘুম কারণ একটি SIGINT গ্রহণ stty isig

তাই যখন:

ssh -t host cat remote-file > local-file

যথেষ্ট খারাপ, কিন্তু

ssh -tt host 'cat > remote-file' < local-file

অন্যভাবে ফাইলগুলি স্থানান্তর করা অনেক খারাপ। > এলএফ অনুবাদ, বরং অন্যান্য সকল বিশেষ অক্ষর সঙ্গে সমস্যা (- আপনি কিছু সি আর কিনবো ^C, ^Z, ^D, ^?, ^S...) এবং দূরবর্তী catফাইলের শেষে দেখতে পাবেন না শেষে যখন local-fileএসে যাবে, শুধুমাত্র যখন ^Dপরে পাঠানো হয় \r, \nবা আপনার টার্মিনাল ^Dকরার সময় অন্য কিছু cat > file


5

ফাইলটি অনুলিপি করতে এই পদ্ধতিটি ব্যবহার করার সময় ফাইলগুলি পৃথক পৃথক বলে মনে হয়।

রিমোট সার্ভার

ls -l | grep vim_cfg
-rw-rw-r--.  1 slm slm 9783257 Aug  5 16:51 vim_cfg.tgz

স্থানীয় সার্ভার

আপনার ssh ... catআদেশ চলছে :

$ ssh dufresne -t 'cat ~/vim_cfg.tgz' > vim_cfg.tgz

স্থানীয় সার্ভারে এই ফাইলে ফলাফল:

$ ls -l | grep vim_cfg.tgz 
-rw-rw-r--. 1 saml saml 9820481 Aug 24 12:13 vim_cfg.tgz

তদন্ত কেন?

স্থানীয় পক্ষের ফলস্বরূপ ফাইলটি অনুসন্ধান করে দেখা যায় যে এটি দূষিত হয়েছে। আপনি যদি -tআপনার sshকমান্ড থেকে স্যুইচ আউট নেন তবে এটি প্রত্যাশার মতো কাজ করে।

$ ssh dufresne 'cat ~/vim_cfg.tgz' > vim_cfg.tgz

$ ls -l | grep vim_cfg.tgz
-rw-rw-r--. 1 saml saml 9783257 Aug 24 12:17 vim_cfg.tgz

চেকসাম এখন খুব কার্যকর:

# remote server
$ ssh dufresne "md5sum ~/vim_cfg.tgz"
9e70b036836dfdf2871e76b3636a72c6  /home/slm/vim_cfg.tgz

# local server
$ md5sum vim_cfg.tgz 
9e70b036836dfdf2871e76b3636a72c6  vim_cfg.tgz

ধন্যবাদ সিম। যদিও আপনি প্রথম সঠিক উত্তর পোস্ট করেছেন, তার ব্যাখ্যাটির গভীরতার কারণে আমি নির্বাচিত উত্তরের জন্য স্টাফেনকে নির্বাচন করেছি। চিন্তা করার দরকার নেই, আপনার কাছ থেকে আমি একটি দীর্ঘ পোস্টের ইতিহাস পেয়েছি যা থেকে শিখছি এবং অবশ্যই আমি যে পোস্টগুলি থেকে শিখেছি সেগুলিকে উজ্জীবিত করেছি। ধন্যবাদ.
ডটানকোচেন

@ ডটানকোহেন - কোনও উদ্বেগ নেই, আপনি কখনই এটির মত অনুভব করেন যা আপনাকে সবচেয়ে বেশি 8- ওপি হিসাবে সাহায্য করে)) গিলস ব্যতীত কেন ঘটনা ঘটে তা ব্যাখ্যা করার জন্য তাঁর ক্ষমতা অপ্রতিরোধ্য।
slm
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.