আমি মনে করি না যে কোনও প্রয়োগের ssh
শেলকে জড়িত না করে ক্লায়েন্ট থেকে সার্ভারে একটি আদেশ পাঠানোর স্থানীয় উপায় আছে।
এখন, বিষয়গুলি আরও সহজ হতে পারে যদি আপনি দূরবর্তী শেলটিকে কেবল একটি নির্দিষ্ট দোভাষী চালাতে (যেমন sh
আমরা প্রত্যাশিত বাক্য গঠন জানি) চালাতে এবং কোডটিকে অন্য মাধ্যমে কার্যকর করতে কোড দিতে পারি।
এটির অন্যান্য অর্থ উদাহরণ স্ট্যান্ডার্ড ইনপুট বা পরিবেশের পরিবর্তনশীল হতে পারে ।
যখন উভয়ই ব্যবহার করা যায় না, আমি নীচে একটি হ্যাকি তৃতীয় সমাধান প্রস্তাব করি।
স্টিডিন ব্যবহার করে
আপনার যদি কোনও ডেটা রিমোট কমান্ডে খাওয়ানোর প্রয়োজন না হয় তবে এটি সবচেয়ে সহজ সমাধান।
আপনি যদি জানেন যে রিমোট হোস্টের একটি xargs
কমান্ড রয়েছে যা -0
বিকল্পটি সমর্থন করে এবং কমান্ডটি খুব বড় নয়, আপনি এটি করতে পারেন:
printf '%s\0' "${cmd[@]}" | ssh user@host 'xargs -0 env --'
এই xargs -0 env --
কমান্ড লাইনটি সমস্ত শেল পরিবারের সাথে একই ব্যাখ্যা করা হয়। xargs
স্টিডিনে আর্গুমেন্টের নাল-সীমাবদ্ধ তালিকা পড়ে এবং সেগুলি আর্গুমেন্ট হিসাবে পাস করে env
। এটি ধরে নিয়েছে প্রথম আর্গুমেন্ট (কমান্ডের নাম) এর মধ্যে =
অক্ষর নেই।
অথবা আপনি sh
প্রতিটি উপাদান sh
উদ্ধৃত বাক্য গঠন ব্যবহার করে দূরবর্তী হোস্টে ব্যবহার করতে পারেন ।
shquote() {
LC_ALL=C awk -v q=\' '
BEGIN{
for (i=1; i<ARGC; i++) {
gsub(q, q "\\" q q, ARGV[i])
printf "%s ", q ARGV[i] q
}
print ""
}' "$@"
}
shquote "${cmd[@]}" | ssh user@host sh
পরিবেশের ভেরিয়েবল ব্যবহার করা
এখন, আপনার যদি ক্লায়েন্ট থেকে রিমোট কমান্ডের স্টিডিনে কিছু তথ্য খাওয়ানোর প্রয়োজন হয় তবে উপরের সমাধানটি কাজ করবে না।
কিছু ssh
সার্ভার মোতায়েন ক্লায়েন্ট থেকে সার্ভারে স্বেচ্ছাসেবী পরিবেশ পরিবর্তনশীল পাস করার অনুমতি দেয়। উদাহরণস্বরূপ, ডিবিয়ান ভিত্তিক সিস্টেমে অনেকগুলি ওপেনশ মোতায়েনগুলি যার নাম দিয়ে শুরু হয় ভেরিয়েবলগুলি পাস করার অনুমতি দেয় LC_
।
এই ক্ষেত্রে আপনি LC_CODE
উদাহরণ হিসাবে উদাহরণস্বরূপ শ্যুইট sh
কোড সহ একটি চলক থাকতে পারে এবং sh -c 'eval "$LC_CODE"'
আপনার ক্লায়েন্টকে সেই ভেরিয়েবলটি পাস করার পরে বলার পরে (আবার, এটি একটি কমান্ড-লাইন যা প্রতিটি শেলের মধ্যে একই ব্যাখ্যা করে):
LC_CODE=$(shquote "${cmd[@]}") ssh -o SendEnv=LC_CODE user@host '
sh -c '\''eval "$LC_CODE"'\'
সমস্ত শেল পরিবারের সাথে উপযুক্ত একটি কমান্ড লাইন তৈরি করা
যদি উপরের কোনও বিকল্প গ্রহণযোগ্য না হয় (কারণ আপনার স্টিডিন প্রয়োজন এবং এসএসডি কোনও পরিবর্তনশীল গ্রহণ করে না, বা আপনার জেনেরিক সমাধান প্রয়োজন বলে), তবে আপনাকে সকলের সাথে সামঞ্জস্যপূর্ণ দূরবর্তী হোস্টের জন্য একটি কমান্ড লাইন প্রস্তুত করতে হবে have সমর্থিত শাঁস
এটি বিশেষত জটিল কারণ কারণ all সমস্ত শেলগুলির (বোর্ন, সিএসএস, আরসি, এস, ফিশ) আলাদা আলাদা বাক্য গঠন রয়েছে এবং বিশেষত বিভিন্ন উদ্ধৃতিপ্রক্রিয়া এবং এর মধ্যে কয়েকটি সীমাবদ্ধতা রয়েছে যার চারপাশে কাজ করা শক্ত।
আমি এখানে এসেছি এমন একটি সমাধান, আমি এটি আরও নীচে বর্ণনা করছি:
#! /usr/bin/perl
my $arg, @ssh, $preamble =
q{printf '%.0s' "'\";set x=\! b=\\\\;setenv n "\
";set q=\';printf %.0s "\""'"';q='''';n=``()echo;x=!;b='\'
printf '%.0s' '\'';set b \\\\;set x !;set -x n \n;set q \'
printf '%.0s' '\'' #'"\"'";export n;x=!;b=\\\\;IFS=.;set `echo;echo \.`;n=$1 IFS= q=\'
};
@ssh = ('ssh');
while ($arg = shift @ARGV and $arg ne '--') {
push @ssh, $arg;
}
if (@ARGV) {
for (@ARGV) {
s/'/'\$q\$b\$q\$q'/g;
s/\n/'\$q'\$n'\$q'/g;
s/!/'\$x'/g;
s/\\/'\$b'/g;
$_ = "\$q'$_'\$q";
}
push @ssh, "${preamble}exec sh -c 'IFS=;exec '" . join "' '", @ARGV;
}
exec @ssh;
এটি perl
প্রায় একটি মোড়ক স্ক্রিপ্ট ssh
। আমি এটি কল sexec
। আপনি এটিকে ডাকেন:
sexec [ssh-options] user@host -- cmd and its args
সুতরাং আপনার উদাহরণে:
sexec user@host -- "${cmd[@]}"
এবং মোড়ক cmd and its args
একটি কমান্ড লাইনে পরিণত হয় যা সমস্ত শেলগুলি cmd
তার আরোগুলি (তাদের সামগ্রীতে নির্বিশেষে) দিয়ে কল করার অর্থ ব্যাখ্যা করে ।
সীমাবদ্ধতা:
- কমান্ডটি উদ্ধৃত করার উপস্থাপনা এবং উপায়টির অর্থ দূরবর্তী কমান্ড লাইনটি উল্লেখযোগ্য পরিমাণে বৃহত্তর হয়ে গেছে যার অর্থ একটি কমান্ড লাইনের সর্বাধিক আকারের সীমাটি শীঘ্রই পৌঁছে যাবে।
- আমি এটির সাথে কেবল এটি পরীক্ষা করেছি: সাম্প্রতিক ডেবিয়ান সিস্টেমে পাওয়া বোর্ন শেল (উত্তরাধিকারী সরঞ্জামের কাস্টম থেকে), ড্যাশ, বাশ, জেডএস, এমএক্স, লক্ষ, যশ, কেএস 93, আরসি, এস, আকঙ্গা, সিএসএস, টিসিএস, মাছ বিন / শ, / ইউএসআর / বিন / কেএসএস, / বিন / সিএসএস এবং / ইউএসআর / এক্সপিজি 4 / বিন / এসএস সোলারিস 10 এ।
- যদি
yash
রিমোট লগইন শেল হয় তবে আপনি কোনও কমান্ডটি পাস করতে পারবেন না যার আর্গুমেন্টে অবৈধ অক্ষর রয়েছে, তবে এটি এমন একটি সীমাবদ্ধতা yash
যে আপনি কোনওভাবেই কাজ করতে পারবেন না।
- কিছু কিছু শেল সিএসএস বা বাশের মতো কিছু স্টার্টআপ ফাইল পড়ে যখন এসএসএসের উপর চাপ দেওয়া হয়। আমরা ধরে নিলাম যারা নাটকীয়ভাবে আচরণটি পরিবর্তন করে না যাতে উপস্থাপনাটি এখনও কাজ করে।
- পাশেই
sh
, এটি ধরেও নেয় দূরবর্তী সিস্টেমের printf
কমান্ড রয়েছে।
এটি কীভাবে কাজ করে তা বোঝার জন্য, আপনাকে জানতে হবে যে বিভিন্ন শেলগুলিতে উদ্ধৃতি কীভাবে কাজ করে:
- বোর্ন:
'...'
এর কোনও বিশেষ চরিত্রহীন দৃ strong় উক্তি । "..."
দুর্বল উক্তি যেখানে "
ব্যাকস্ল্যাশ দিয়ে পালানো যায়।
csh
। বোর্ন হিসাবে একই যে এর বাইরে "
পালানো যায় না "..."
। এছাড়াও একটি নতুনলাইন চরিত্রটি ব্যাকস্ল্যাশ সহ উপস্থাপিত করতে হবে। এবং !
একক উদ্ধৃতিতেও সমস্যা তৈরি করে।
rc
। একমাত্র উদ্ধৃতিগুলি '...'
(শক্তিশালী)। একক উদ্ধৃতিগুলির মধ্যে একটি একক উক্তি ''
(যেমন '...''...'
) প্রবেশ করানো হয় । ডাবল উদ্ধৃতি বা ব্যাকস্ল্যাশগুলি বিশেষ নয়।
es
। বাইরের উক্তি ব্যতীত আরসি হিসাবে একই, ব্যাকস্ল্যাশ একটি একক উদ্ধৃতি থেকে বাঁচতে পারে।
fish
: বোর্ন হিসাবে একই যে ব্যাকস্ল্যাশ '
ভিতরে প্রবেশ করে '...'
।
এই সমস্ত প্রতিবন্ধকতাগুলির সাথে, এটি সহজেই দেখা যায় যে কেউ কমান্ড লাইন যুক্তি নির্ভরযোগ্যতার সাথে উদ্ধৃত করতে পারে না যাতে এটি সমস্ত শেলগুলির সাথে কাজ করে।
একক উদ্ধৃতি ব্যবহার হিসাবে:
'foo' 'bar'
সব মিলিয়ে কাজ করে:
'echo' 'It'\''s'
কাজ করবে না rc
।
'echo' 'foo
bar'
কাজ করবে না csh
।
'echo' 'foo\'
কাজ করবে না fish
।
তবে আমরা পরিষদবর্গকে বেশিরভাগ সমস্যার কাজ করতে সক্ষম যদি আমরা ভেরিয়েবল সেই সমস্যাযুক্ত অক্ষর সঞ্চয় করতে পরিচালিত ব্যাকস্ল্যাশ কেমন হওয়া উচিত $b
, একক উদ্ধৃতি $q
মধ্যে, NEWLINE $n
(এবং !
মধ্যে $x
একটি শেল স্বাধীন ভাবে csh এর মূল ইতিহাস সম্প্রসারণ জন্য)।
'echo' 'It'$q's'
'echo' 'foo'$b
সব শেল কাজ করবে। এটি এখনও নতুন লাইনের জন্য কাজ করবে না csh
। যদি $n
নিউলাইন থাকে তবে এটিতে একটি নতুন লাইনে প্রসারিত হওয়ার জন্য আপনাকে এটি csh
লিখতে হবে $n:q
এবং এটি অন্যান্য শেলের জন্য কাজ করবে না। সুতরাং, পরিবর্তে এখানে আমরা কী করছি তা কল করছে sh
এবং sh
সেগুলি প্রসারিত করবে $n
। এর অর্থ হ'ল দুটি স্তরের উদ্ধৃতি, একটি রিমোট লগইন শেলের জন্য এবং একটির জন্য sh
।
$preamble
যে কোডে trickiest অংশ। এটা তোলে কোড শাঁস মাত্র এক ব্যাখ্যা (যখন এটি অন্যদের জন্য মন্তব্য করা হয়েছে) প্রতিটি যা কেবলমাত্র সেই সংজ্ঞা কিছু বিভাগ রয়েছে সব শাঁস বিভিন্ন বিভিন্ন উদ্ধৃতি নিয়ম ব্যবহার করে $b
, $q
, $n
, $x
তাদের নিজ নিজ শেল জন্য ভেরিয়েবল।
এখানে শেল কোডটি দেওয়া হবে যা host
উদাহরণস্বরূপ দূরবর্তী ব্যবহারকারীর লগইন শেল দ্বারা ব্যাখ্যা করা হবে :
printf '%.0s' "'\";set x=\! b=\\;setenv n "\
";set q=\';printf %.0s "\""'"';q='''';n=``()echo;x=!;b='\'
printf '%.0s' '\'';set b \\;set x !;set -x n \n;set q \'
printf '%.0s' '\'' #'"\"'";export n;x=!;b=\\;IFS=.;set `echo;echo \.`;n=$1 IFS= q=\'
exec sh -c 'IFS=;exec '$q'printf'$q' '$q'<%s>'$b'n'$q' '$q'arg with $and spaces'$q' '$q''$q' '$q'even'$q'$n'$q'* * *'$q'$n'$q'newlines'$q' '$q'and '$q$b$q$q'single quotes'$q$b$q$q''$q' '$q''$x''$x''$q
সমর্থিত শেলগুলির কোনওর দ্বারা ব্যাখ্যা করা হলে সেই কোডটি একই কমান্ডটি চালানো শেষ করে।
cmd
যুক্তিটি যদি হয় যে/bin/sh -c
আমরা সব ক্ষেত্রে 99% মধ্যে একটি পিক্সিক শেল দিয়ে শেষ করব, তাই না? অবশ্যই বিশেষ চরিত্রগুলি থেকে বাঁচা এইভাবে খানিকটা বেদনাদায়ক তবে এটি কি প্রাথমিক সমস্যার সমাধান করবে?