कांटा बम पर कांटा () कहां है: () {: |: &}:?


25

चेतावनी: अधिकांश गोले में इस कमांड को चलाने से टूटी हुई प्रणाली को ठीक करने के लिए मजबूर शटडाउन की आवश्यकता होगी

मैं पुनरावर्ती कार्य को समझता हूं :(){ :|: & };:और यह क्या करता है। लेकिन मुझे नहीं पता कि फोर्क सिस्टम कॉल कहां है। मुझे यकीन नहीं है, लेकिन मुझे पाइप में संदेह है |


संबंधित और पढ़ने के लायक): कांटा बम कैसे काम करता है?
terdon

जवाबों:


30

में पाइप के परिणामस्वरूप x | y, अग्रभूमि प्रक्रिया समूह के हिस्से के रूप में पाइपलाइन को समाहित करने के लिए एक उपधारा बनाया गया है। यह fork()अनिश्चित काल तक उपधाराएं (के माध्यम से ) बनाता रहता है , इस प्रकार कांटा बम बनाता है ।

$ 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, एक उप-शेल क्यों बनाया गया है? मेरी समझ के लिए, जब bash एक देखता है pipe, तो यह pipe()सिस्टम कॉल निष्पादित करता है, जो दो रिटर्न देता है fds। अब, command_left execed है और इनपुट के रूप में आउटपुट command_right को खिलाया जाता है। अब, कमांड_ राइट execएड है। तो, BASHPIDहर बार अलग क्यों है ?
अभिजीत रस्तोगी

2
@shadyabhi यह सरल है - xऔर y2 अलग-अलग कमांड हैं जो 2 अलग-अलग प्रक्रियाओं में चल रहे हैं, इसलिए आपके पास 2 अलग-अलग उप-खंड हैं। यदि xशेल के रूप में एक ही प्रक्रिया में चलता है, तो इसका मतलब है कि xएक अंतर्निहित होना चाहिए।
jw013

24

कोड का अंतिम बिट, ;:फ़ंक्शन चला रहा है :(){ ... }। यहीं पर कांटा लग रहा है।

अर्धविराम पहले आदेश को समाप्त करता है, और हम एक और शुरू कर रहे हैं, अर्थात फ़ंक्शन को लागू करना :। इस फ़ंक्शन की परिभाषा में खुद को एक कॉल शामिल है ( :) और इस कॉल का आउटपुट एक पृष्ठभूमि वाले संस्करण में पाइप किया गया है :। यह अनिश्चित काल के लिए प्रक्रिया को बढ़ाता है।

हर बार जब आप फ़ंक्शन को बुला रहे हैं तो :()आप C फ़ंक्शन को कॉल कर रहे हैं 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
...
...

समय साफ करें

A killall bashचीजों को हाथ से निकलने से पहले ही रोक देगा। इस तरह से अपनी सफाई करना थोड़ा भारी हाथ हो सकता है, एक किंडर जेंटलर तरीका जो संभावित रूप से हर bashशेल को फाड़ नहीं सकता है, निम्नलिखित करने के लिए होगा:

  1. निर्धारित करें कि छद्म टर्मिनल क्या कांटा बम चलाने वाला है

    $ tty
    /dev/pts/4
  2. छद्म टर्मिनल को मार डालो

    $ pkill -t pts/4

तो क्या चल रहा है?

खैर के प्रत्येक मंगलाचरण bashऔर sleepसी फ़ंक्शन की कॉल है fork()से bashजहां आदेश चला गया था से खोल।


7
bashअलग टर्मिनलों पर चल सकता है। उपयोग करने के लिए बेहतर होगा pkill -t pts/2
मैकीज पीचोटका

@MaciejPiechotka - टिप के लिए धन्यवाद। पहले कभी नहीं देखा कि, मैंने इसे उत्तर में जोड़ दिया है!
slm
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.