คำเตือน: การเรียกใช้คำสั่งนี้ในเชลล์ส่วนใหญ่จะส่งผลให้ระบบแตกหักซึ่งจะต้องบังคับให้ปิดระบบเพื่อแก้ไข
ฉันเข้าใจฟังก์ชั่นวนซ้ำ:(){ :|: & };:และสิ่งที่ทำ แต่ฉันไม่รู้ว่าระบบสายส้อมอยู่ที่ไหน ผมไม่แน่ใจ |แต่ผมสงสัยว่าในท่อ
คำเตือน: การเรียกใช้คำสั่งนี้ในเชลล์ส่วนใหญ่จะส่งผลให้ระบบแตกหักซึ่งจะต้องบังคับให้ปิดระบบเพื่อแก้ไข
ฉันเข้าใจฟังก์ชั่นวนซ้ำ:(){ :|: & };:และสิ่งที่ทำ แต่ฉันไม่รู้ว่าระบบสายส้อมอยู่ที่ไหน ผมไม่แน่ใจ |แต่ผมสงสัยว่าในท่อ
คำตอบ:
เป็นผลมาจากไปป์ในx | y, subshell ถูกสร้างขึ้นเพื่อให้มีไปป์ไลน์เป็นส่วนหนึ่งของกลุ่มกระบวนการเบื้องหน้า สิ่งนี้ยังคงสร้าง subshells (ผ่านfork()) ไปเรื่อย ๆ ดังนั้นจึงสร้าง fork bomb
$ 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
ทางแยกไม่ได้เกิดขึ้นจริงจนกว่าจะมีการเรียกใช้รหัสอย่างไรก็ตามซึ่งเป็นการร้องขอขั้นสุดท้าย:ในรหัสของคุณ
หากต้องการแยกการทำงานของ fork bomb:
:() - กำหนดฟังก์ชั่นใหม่ที่เรียกว่า :{ :|: & } - คำจำกัดความของฟังก์ชั่นที่ทำหน้าที่เรียกไปยังอินสแตนซ์อื่นของฟังก์ชันการโทรในพื้นหลัง: - เรียกใช้ฟังก์ชัน fork bombสิ่งนี้มีแนวโน้มที่จะไม่ได้ใช้หน่วยความจำมากเกินไป แต่มันจะดูดค่า PID และใช้รอบของ CPU
x | yทำไมมีย่อยเปลือกสร้าง? เพื่อความเข้าใจของฉันเมื่อทุบตีเห็นpipeจะรันระบบโทรที่ผลตอบแทนที่สองpipe() fdsตอนนี้ command_left เป็นexeced และเอาต์พุตถูกป้อนไปที่ command_right เป็นอินพุต ตอนนี้ command_right เป็นexeced ดังนั้นBASHPIDแต่ละครั้งแตกต่างกันอย่างไร
                    xและyมี 2 คำสั่งแยกกันทำงานใน 2 กระบวนการแยกกันดังนั้นคุณมี 2 subshells แยก หากxทำงานในกระบวนการเดียวกับเชลล์นั่นหมายความว่าxจะต้องเป็นบิวด์อิน
                    บิตสุดท้ายของรหัสกำลังเรียกใช้ฟังก์ชั่น;: :(){ ... }นี่คือที่เกิดขึ้นของส้อม
:อัฒภาคยุติคำสั่งแรกและเราจะเริ่มต้นอีกคนหนึ่งคือการเรียกใช้ฟังก์ชั่น ความหมายของฟังก์ชั่นนี้รวมถึงการเรียกร้องให้ตัวเอง ( :) :และผลผลิตของสายนี้จะประปาเป็นรุ่น กระบวนการนี้ประกอบไปด้วยกระบวนการอย่างไม่มีกำหนด
ทุกครั้งที่คุณโทรฟังก์ชั่นที่คุณกำลังเรียกใช้ฟังก์ชันซี:() fork()ในที่สุดสิ่งนี้จะทำให้หมดกระบวนการ ID (PID) ทั้งหมดในระบบ
คุณสามารถสลับ|:&กับสิ่งอื่นเพื่อที่คุณจะได้ทราบว่าเกิดอะไรขึ้น
ในหน้าต่างเทอร์มินัลหนึ่งทำได้:
$ watch "ps -eaf|grep \"[s]leep 61\""
ในหน้าต่างอื่นเราจะเรียกใช้ fork bomb รุ่นดัดแปลงเล็กน้อย รุ่นนี้จะพยายามเค้นตัวเองเพื่อให้เราสามารถศึกษาสิ่งที่กำลังทำอยู่ รุ่นของเราจะนอนหลับ 61 :()วินาทีก่อนที่จะเรียกฟังก์ชั่น
นอกจากนี้เราจะเรียกการโทรเริ่มต้นด้วยหลังจากที่มีการเรียกใช้ Ctrl+ ชนิดแล้วzbg
$ :(){ 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เปลือกหอยลงทุกครั้ง
กำหนดเทอร์มินัลเทียมหลอกว่า fork bomb กำลังจะทำงาน
$ tty
/dev/pts/4
ฆ่าสถานีหลอก
$ pkill -t pts/4แต่ละการเรียกใช้ของbashและsleepเป็นการเรียกใช้ฟังก์ชัน C fork()จากbashเชลล์จากตำแหน่งที่คำสั่งรัน
bashอาจกำลังรันอยู่บนเทอร์มินัลแยกกัน pkill -t pts/2ดีกว่าที่จะใช้