คำเตือน: การเรียกใช้คำสั่งนี้ในเชลล์ส่วนใหญ่จะส่งผลให้ระบบแตกหักซึ่งจะต้องบังคับให้ปิดระบบเพื่อแก้ไข
ฉันเข้าใจฟังก์ชั่นวนซ้ำ:(){ :|: & };:
และสิ่งที่ทำ แต่ฉันไม่รู้ว่าระบบสายส้อมอยู่ที่ไหน ผมไม่แน่ใจ |
แต่ผมสงสัยว่าในท่อ
คำเตือน: การเรียกใช้คำสั่งนี้ในเชลล์ส่วนใหญ่จะส่งผลให้ระบบแตกหักซึ่งจะต้องบังคับให้ปิดระบบเพื่อแก้ไข
ฉันเข้าใจฟังก์ชั่นวนซ้ำ:(){ :|: & };:
และสิ่งที่ทำ แต่ฉันไม่รู้ว่าระบบสายส้อมอยู่ที่ไหน ผมไม่แน่ใจ |
แต่ผมสงสัยว่าในท่อ
คำตอบ:
เป็นผลมาจากไปป์ใน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 เป็นexec
ed และเอาต์พุตถูกป้อนไปที่ command_right เป็นอินพุต ตอนนี้ command_right เป็นexec
ed ดังนั้น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
ดีกว่าที่จะใช้