কাঁটাচামচ বোম্বের কাঁটা () কোথায়: () {: |: &};:?


25

সতর্কতা: বেশিরভাগ শেলগুলিতে এই কমান্ডটি চালনার ফলে একটি ভাঙ্গা ব্যবস্থা তৈরি হবে যার সমাধানের জন্য বাধ্যতামূলকভাবে শাটডাউন প্রয়োজন

আমি পুনরাবৃত্তি ফাংশন :(){ :|: & };:এবং এটি কী করে তা বুঝতে পারি। তবে কাঁটা সিস্টেম কলটি কোথায় আছে তা আমি জানি না। আমি নিশ্চিত নই, তবে পাইপে সন্দেহ করছি |


সম্পর্কিত (এবং পড়ার মূল্য): কাঁটাচামচ বোমা কীভাবে কাজ করে?
terdon

উত্তর:


30

পাইপের মধ্যে ফলস্বরূপ, x | yঅগ্রভাগ প্রক্রিয়া গোষ্ঠীর অংশ হিসাবে পাইপলাইন ধারণ করার জন্য একটি সাবশেল তৈরি করা হয়। এটি fork()অনির্দিষ্টকালের জন্য সাবশেলগুলি (মাধ্যমে ) তৈরি করে চলেছে , এভাবে কাঁটাচামচ তৈরি করে creating

$ for (( i=0; i<3; i++ )); do
>     echo "$BASHPID"
> done
16907
16907
16907
$ for (( i=0; i<3; i++ )); do
>     echo "$BASHPID" | cat
> done
17195
17197
17199

কোডটি চালিত হওয়া অবধি কাঁটাচামচটি ঘটে না, তবে :এটি আপনার কোডের চূড়ান্ত প্রার্থনা ।

কাঁটাচামচ বোমা কীভাবে কাজ করে তা বিচ্ছিন্ন করতে:

  • :() - নামক একটি নতুন ফাংশন সংজ্ঞায়িত করুন :
  • { :|: & } - একটি ফাংশন সংজ্ঞা যা পুনরাবৃত্তভাবে কলিং ফাংশনটিকে পটভূমিতে কলিং ফাংশনের অন্য একটি ইভেন্টে পাইপ করে
  • : - কাঁটাচামচ বোমা ফাংশন কল

এটি খুব স্মৃতিশক্তি নিবিড় না হয়ে থাকে তবে এটি পিআইডি চুষে খায় এবং সিপিইউ চক্র গ্রহণ করবে।


ইন x | y, কেন একটি উপ-শেল তৈরি করা হয়? আমার বোঝার জন্য, যখন বাশ একটি দেখে pipe, এটি pipe()সিস্টেম কল কার্যকর করে, যা দুটি ফেরত দেয় fds। এখন, কমান্ড_ লেফটটি execএড এবং আউটপুট কমান্ড_আর্টকে ইনপুট হিসাবে দেওয়া হবে। এখন কমান্ড_রাইট execএড হয়। তো, কেন BASHPIDপ্রতিবার আলাদা?
অভিজিৎ রাস্তোগি

2
@ শাদ্যাবিবি এটি সহজ - xএবং y2 টি পৃথক কমান্ড 2 পৃথক প্রক্রিয়াতে চলছে, সুতরাং আপনার 2 টি পৃথক সাব-শেল রয়েছে । যদি xশেলের মতো একই প্রক্রিয়াতে চলে তবে এর অর্থ xঅবশ্যই একটি অন্তর্নির্মিত হতে হবে।
jw013

24

কোডের শেষ বিটটি ;:ফাংশনটি চালাচ্ছে :(){ ... }। এখানেই কাঁটাচামচ ঘটছে।

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

প্রতিবার আপনি ফাংশন আহ্বান করছি :()আপনি সি ফাংশন আহ্বান করছি fork()। শেষ পর্যন্ত এটি সিস্টেমে সমস্ত প্রক্রিয়া আইডি (পিআইডি) নিঃশেষ করবে।

উদাহরণ

আপনি |:&অন্য কোনও কিছুর সাথে সরিয়ে নিতে পারবেন যাতে কী চলছে সে সম্পর্কে আপনি ধারণা পেতে পারেন।

একজন প্রহরী সেটআপ করুন

একটি টার্মিনাল উইন্ডোতে এটি করুন:

$ watch "ps -eaf|grep \"[s]leep 61\""

"ফিউজ বিলম্বিত" কাঁটাচামচ বোমা সেটআপ করুন

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

এছাড়াও প্রাথমিক কলটি শুরুর পরে আমরা পাশাপাশি ব্যাকগ্রাউন্ড করব। Ctrl+ zটাইপ করুন bg

$ :(){ sleep 61; : | : & };:

# control + z
[1]+  Stopped                 sleep 61
[2] 5845
$ bg
[1]+ sleep 61 &

এখন যদি আমরা jobsপ্রাথমিক উইন্ডোতে কমান্ডটি চালিত করি তবে আমরা এটি দেখতে পাবো:

$ jobs
[1]-  Running                 sleep 61 &
[2]+  Running                 : | : &

কয়েক মিনিট পরে:

$ jobs
[1]-  Done                    sleep 61
[2]+  Done                    : | :

প্রহরীটির সাথে চেক ইন করুন

ইতিমধ্যে অন্য উইন্ডোতে আমরা যেখানে চলছে watch:

Every 2.0s: ps -eaf|grep "[s]leep 61"                                                                                                                                             Sat Aug 31 12:48:14 2013

saml      6112  6108  0 12:47 pts/2    00:00:00 sleep 61
saml      6115  6110  0 12:47 pts/2    00:00:00 sleep 61
saml      6116  6111  0 12:47 pts/2    00:00:00 sleep 61
saml      6117  6109  0 12:47 pts/2    00:00:00 sleep 61
saml      6119  6114  0 12:47 pts/2    00:00:00 sleep 61
saml      6120  6113  0 12:47 pts/2    00:00:00 sleep 61
saml      6122  6118  0 12:47 pts/2    00:00:00 sleep 61
saml      6123  6121  0 12:47 pts/2    00:00:00 sleep 61

প্রক্রিয়াক্রমক্রম

এবং একটি ps -auxfএই প্রক্রিয়া শ্রেণিবিন্যাস দেখায়:

$ ps -auxf
saml      6245  0.0  0.0 115184  5316 pts/2    S    12:48   0:00 bash
saml      6247  0.0  0.0 100988   468 pts/2    S    12:48   0:00  \_ sleep 61
....
....
saml      6250  0.0  0.0 115184  5328 pts/2    S    12:48   0:00 bash
saml      6268  0.0  0.0 100988   468 pts/2    S    12:48   0:00  \_ sleep 61
saml      6251  0.0  0.0 115184  5320 pts/2    S    12:48   0:00 bash
saml      6272  0.0  0.0 100988   468 pts/2    S    12:48   0:00  \_ sleep 61
saml      6252  0.0  0.0 115184  5324 pts/2    S    12:48   0:00 bash
saml      6269  0.0  0.0 100988   464 pts/2    S    12:48   0:00  \_ sleep 61
...
...

সময় পরিষ্কার করুন

killall bashজিনিসগুলি হাতছাড়া হওয়ার আগেই থামিয়ে দেবে। আপনার ক্লিন আপটি এইভাবে করা কিছুটা ভারী হাতের হতে পারে, একটি মৃদু মৃদু উপায় যা সম্ভাব্যভাবে প্রতিটি bashশেলটি ছিঁড়ে না ফেলে, নিম্নলিখিতটি করা হবে:

  1. ফর্ক বোমাটি কোন সিউডো টার্মিনালটি চালু হতে চলেছে তা নির্ধারণ করুন

    $ tty
    /dev/pts/4
  2. সিউডো টার্মিনালটি মেরে ফেলুন

    $ pkill -t pts/4

তো কেমন যাচ্ছে?

ওয়েল প্রতিটি আবাহন bashএবং sleepসি ফাংশন একটি কল fork()থেকে bashযেখানে কমান্ডটি প্রয়োগ হওয়ার পর থেকে শেল।


7
bashপৃথক টার্মিনাল উপর চলমান হতে পারে। আরও ভাল ব্যবহার করা হবে pkill -t pts/2
ম্যাকিয়েজ পাইচোতকা

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