কমান্ডে ssh ওভার ssh এর সাথে সত্যই বাড়ে ing


15

আমি যখন pkill -fএসএসএসের মাধ্যমে দূরবর্তীভাবে চালানোর চেষ্টা করি এবং সম্ভাব্য ত্রুটি কোডটি বাতিল করার চেষ্টা করি (কোনও প্রক্রিয়া || trueনা পাওয়া গেলেও আমার স্ক্রিপ্টের বাকী অংশটি চালিয়ে যেতে), আমার প্রত্যাশা মতো আচরণ করে না।

$ pkill asdf || true
$ echo $?
0
$ pkill -f asdf || true
$ echo $?
0
$ ssh pi@10.20.0.10 "pkill asdf || true"
$ echo $?
0
$ ssh pi@10.20.0.10 "pkill -f asdf || true"
255

আমি অনুমান করি যে এটি ssh যা 255 প্রদান করে, কোটের মধ্যে আদেশ নয়, তবে কেন?

উত্তর:


29

আপনার অনুমান যে এটি sshনিজেই 255 প্রস্থান স্থিতি ফিরে আসে। sshমানুষ যে পৃষ্ঠাটি বলে:

ssh রিমোট কমান্ডের প্রস্থান স্থিতি সহ অথবা কোনও ত্রুটি ঘটলে 255 দিয়ে প্রস্থান করে।

আপনি যদি সহজভাবে চালাতে ssh pi@10.20.0.10 "pkill -f asdf"চান তবে আপনি সম্ভবত " কোনও প্রক্রিয়া মেলে না " 1এর pkillস্ট্যাটাসের সাথে মিল রেখে একটি প্রস্থান স্থিতি পেয়ে যাবেন ।

চ্যালেঞ্জিং অংশটি হ'ল বোঝা উচিত যে আপনি চালানোর সময় এসএসএইচ-তে কেন ত্রুটি ঘটে

ssh pi@10.20.0.10 "pkill -f asdf || true"

এসএসএইচ দূরবর্তী কমান্ড

এসএসএইচ সার্ভার রিমোট কমান্ড (গুলি) চালানোর জন্য একটি শেল প্রবর্তন করে। এখানে কর্মের একটি উদাহরণ এখানে:

$ ssh server "ps -elf | tail -5"
4 S root     35323  1024 12  80   0 - 43170 poll_s 12:01 ?        00:00:00 sshd: anthony [priv]
5 S anthony  35329 35323  0  80   0 - 43170 poll_s 12:01 ?        00:00:00 sshd: anthony@notty
0 S anthony  35330 35329  0  80   0 - 28283 do_wai 12:01 ?        00:00:00 bash -c ps -elf | tail -5
0 R anthony  35341 35330  0  80   0 - 40340 -      12:01 ?        00:00:00 ps -elf
0 S anthony  35342 35330  0  80   0 - 26985 pipe_w 12:01 ?        00:00:00 tail -5

লক্ষ্য করুন যে ডিফল্ট শেলটি হ'ল bashএবং দূরবর্তী কমান্ডটি একটি সাধারণ কমান্ড নয় বরং একটি পাইপলাইন , "নিয়ন্ত্রণ অপারেটর দ্বারা বিভক্ত এক বা একাধিক কমান্ডের অনুক্রম |"।

বাশ শেলটি উপলব্ধি করার জন্য যথেষ্ট চালাক যে -cবিকল্পটি দ্বারা কমান্ডটি একটি সরল কমান্ড হিসাবে প্রেরণ করা হলে এটি একটি নতুন প্রক্রিয়াটি প্রকৃতপক্ষে নকল না করে অনুকূলিত করতে পারে, execঅতিরিক্ত পদক্ষেপের পরিবর্তে এটি সরাসরি সরল কমান্ডটি ব্যবহার করে এর forking আগেই execs। আপনি যখন রিমোট সিম্পল কমান্ডটি চালান তখন কী ঘটে তার উদাহরণ এখানে দেওয়া হয়েছে ps -elf:

$ ssh server "ps -elf" | tail -5
1 S root     34740     2  0  80   0 -     0 worker 11:49 ?        00:00:00 [kworker/0:1]
1 S root     34762     2  0  80   0 -     0 worker 11:50 ?        00:00:00 [kworker/0:3]
4 S root     34824  1024 31  80   0 - 43170 poll_s 11:51 ?        00:00:00 sshd: anthony [priv]
5 S anthony  34829 34824  0  80   0 - 43170 poll_s 11:51 ?        00:00:00 sshd: anthony@notty
0 R anthony  34830 34829  0  80   0 - 40340 -      11:51 ?        00:00:00 ps -elf

আমি এর আগে এই আচরণটি পেরিয়ে এসেছি তবে আমি এই আস্কউবুন্টু উত্তর ছাড়া আর কোনও ভাল রেফারেন্স পাই না ।

পিকিল আচরণ

যেহেতু pkill -f asdf || trueকোনও সরল কমান্ড নয় (এটি একটি কমান্ডের তালিকা ), উপরের অপ্টিমাইজেশনটি এমনভাবে ঘটতে পারে না যখন আপনি চালাবেন ssh pi@10.20.0.10 "pkill -f asdf || true", sshdপ্রক্রিয়াটি কাঁটাচামচ করে এবং সম্পাদন করে bash -c "pkill -f asdf || true"

সিটিএক্সের উত্তরটি যেমন উল্লেখ করেছে, pkillএটি নিজস্ব প্রক্রিয়াটি হত্যা করবে না। যাইহোক, এটা হবে অন্য কোন প্রক্রিয়া যার কমান্ড লাইন মিলে যায় হত্যা -fপ্যাটার্ন। bash -cনিজস্ব পিতা বা মাতা (যেমন ঘটনাচক্রে) - তাই এটি এই প্রক্রিয়া নিহত কমান্ড এই প্যাটার্ন মেলে।

এসএসএইচ সার্ভারটি দেখতে পাবে যে রিমোট কমান্ডগুলি চালানোর জন্য এটি শেল প্রক্রিয়াটি শুরু হয়েছিল অপ্রত্যাশিতভাবে নিহত হয়েছিল সুতরাং এটি এসএসএইচ ক্লায়েন্টকে একটি ত্রুটির খবর দেয়।


1
উত্তর সঠিকভাবে উৎস হিসেবে একটি সমস্যা চিহ্নিত করার সময় pkillকারণ এটির ARG তালিকা regexp সাথে মিলে যায় তার পিতা বা মাতা শেল প্রক্রিয়া নষ্ট, আমি একটি পরিভাষা আপত্তি বাড়াতে হবে: x || yহয় না একটি যৌগ কমান্ড , এটি একটি এর কমান্ড তালিকা
স্টাফেন চেজেলাস

@ স্টাফেনচাজেলাস মতামতের জন্য ধন্যবাদ। আমি বাশকে শর্তযুক্ত কন্সট্রাক্টসগুলি যৌগিক কমান্ড হিসাবে অন্তর্ভুক্ত করে যাচ্ছিলাম তবে আমি সম্মত যে x||yকমান্ডের তালিকা হিসাবে বিবেচনা করা আরও যুক্তিযুক্তভাবে সুসংগত here আমি এখন বিভিন্ন পসিক্স সংজ্ঞায় লিঙ্ক অন্তর্ভুক্ত করার জন্য আমার উত্তরটি সম্পাদনা করেছি।
অ্যান্টনি জি - মনিকার পক্ষে ন্যায়বিচার

1
মনে রাখবেন যে সাধারণ ক্ষেত্রে, এটি এতটা অনুকূল নয় যে এটি অনুকূলিত করতে পারে না কারণ এটি একটি কমান্ডের তালিকাতে এটি চালানোর জন্য আরও একটি কমান্ড রয়েছে (সম্ভাব্য)। ইন zsh/ ksh93/ ফ্রিবিএসডিsh , false || pkill -f asdfহবে pkillশেল প্রক্রিয়ায় মৃত্যুদন্ড কার্যকর। bashযখন কেবলমাত্র একটি সাধারণ কমান্ড থাকে কেবলমাত্র অপ্টিমাইজেশন করে। true; pkill -f asdfএকটি সমস্যা হবে।
স্টাফেন চেজেলাস

9

আপনার রিমোট কমান্ড নিজেকে হত্যা করে:

$ ssh 10.0.3.70 'pgrep -af asdf'
$ ssh 10.0.3.70 'pgrep -af asdf || true'
1018 bash -c pgrep -af asdf || true

pgrep এবং pkill তাদের নিজস্ব প্রক্রিয়া উপেক্ষা করবে, কিন্তু -ফ পতাকা দ্বারা, তারা পিতৃত শেলটি খুঁজে পেতে পারে:

$ pgrep -af asdf
$ pgrep -af asdf || true
$ bash -c 'pgrep -af asdf'
$ bash -c 'pgrep -af asdf || true'
9803 bash -c pgrep -af asdf || true

এটা বোধগম্য! bash -c 'pgrep -af asdf'(ছাড়া || true) নিজেকে খুঁজে না । কেন না? এটা আছে -f
গৌথিয়ার

2
@ গৌথিয়ার আসলে, আমি মনে করি এই ক্ষেত্রে, বাশ বুঝতে পারার যথেষ্ট চালাক যে কমান্ডটি একটি সাধারণ (কোনও যৌগিক কমান্ড নয়) তাই এটি একটি নতুন প্রক্রিয়াটি জোর করে না দিয়ে অনুকূলিত করে। আমি মনে করি এর আগে একই ধরণের আচরণটি আসবে (আমার উত্তরটি আপডেট করতে হবে)।
অ্যান্টনি জি - মনিকার

3

আপনি "এসিডেফ" এর সাথে মিলে এমন কোনও কিছু মারতে পিকিলকে বলে। আপনার এটি বলা উচিত [এস] এসডিএফের সাথে ম্যাচ করার জন্য, এইভাবে এটি "এসএসডিএফ" নামের কোনও কিছুর সন্ধান করবে তবে নিজেই দেখতে পাবে না (যদি আপনি এসডিএফের সাথে এসিডেফ সাজিয়ে রাখেন তবে লক্ষ্য করুন যে এসটি এর সাথে সংযুক্ত রয়েছে] এবং না এস।)

ssh 10.0.3.70 'pgrep -af "[a]sdf" || true'

এটি গ্রেপ / egrep / awk / ইত্যাদি ব্যবহার করে একটি সাধারণ কৌশল:

ps -ef | grep "something"  # will sometimes match itself too
ps -ef | grep "[s]omething" # will not match itself

# why it works:
# the commandline contains:     ps -ef | grep [s]omething
# and grep tries to find:                      something

এই কৌশলটি পুরানো, এবং আমি কয়েক দশক আগে এটি ইউনিক্স ফ্যাক্সে দেখেছি (যা এখনও পড়া ভাল!

এটিকে "স্বয়ংক্রিয়" করতে, এটি সহজ নয়, তবে সাধারণত প্রতিবার আপনার পরিবর্তনশীল স্ট্রিংয়ের জন্য গ্রেপ করা দরকার = "কিছু", আপনি চেষ্টা করতে পারেন:

grep "$(echo "${regexp}" | LC_ALL='C' sed -e 's/[a-zA-Z0-9_-]/[&]/')" 
#  if regexp="something",  it does: grep "[s]omething"
#  if regexp="otherthing", it does: grep "[o]therthing"
#  if regexp="^thirdthing", it does: grep "^[t]hirdthing" #ok, kept the "^"
#BUT fails on : regexp="[abc]def", as it does: grep "[[a]bc]def" instead of grep "[abc][d]ef" ...

দ্রষ্টব্য: আমি সচেতন যে আমার 'ব্যর্থ' গ্রেপ উদাহরণটি, কেউ আবার রেজিএক্সপকে যেমন রাখতে পারত, কারণ এটি ইতিমধ্যে নিজের সাথে মেলে না (ক, কমান্ডলাইনের '' '' এর সাথে মেলে না) । তবে এটি রেজিএক্সএক্সের পরীক্ষা দিয়ে তুচ্ছ নয়। সাধারণভাবে, কৌশলটি কাজ করে। যেটি স্বয়ংক্রিয়ভাবে চলে সে বেশিরভাগ সময় কাজ করবে। যখন না, কিছু চালাক হ্যাক (বা ম্যানুয়াল হস্তক্ষেপ) প্রয়োজন হবে।
অলিভিয়ার ডুলাক

এছাড়াও, (abc)?(def)?হতে হবে ([a]bc)?([d]ef)?... আপনি রিজেক্সের সাথে রেজেক্সকে পার্স করতে পারবেন না ?! > :-)
wizzwizz4

@ wizzwizz4 আমি জানি তবে আপনার উদাহরণটি ইতিমধ্যে নিজের সাথে মেলে না। এটি একটি জটিল জিনিস, আমি কেবল সহজ মামলার সহজ সমাধান সরবরাহ করেছি
অলিভিয়ার ডুলাক

@ wizzwizz4 আমি ইতিমধ্যে আমার প্রথম মন্তব্যে এটি বলেছি ...
অলিভিয়ার ডুলাক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.