일반적인 포크 폭탄의 작동 방식을 알지만 일반적인 bash 포크 폭탄의 끝에 &가 필요한 이유와 이러한 스크립트가 다르게 동작하는 이유를 이해하지 못합니다.
:(){ (:) | (:) }; :
과
:(){ : | :& }; :
전자는 로그인 화면으로 돌아 가기 전에 CPU 사용량을 급증시킵니다. 후자는 대신 시스템이 정지되어 하드 재부팅을 강제합니다. 왜 그런 겁니까? 둘 다 지속적으로 새로운 프로세스를 생성하므로 시스템이 다르게 동작하는 이유는 무엇입니까?
두 스크립트는 모두 다르게 동작합니다
:(){ : | : }; :
비록 내가 같은 것을 기대했을지라도 전혀 문제를 일으키지 않습니다. bash 매뉴얼 페이지에는 파이프 라인의 명령이 이미 서브 쉘에서 실행되었다고 나와 있으므로 다음과 같이 믿습니다. | : 이미 충분합니다. 나는 새로운 서브 쉘에서 파이프 라인을 실행해야하는데 왜 그렇게 많이 바뀌는가?
편집 : htop을 사용하고 프로세스의 양을 제한하면서 첫 번째 변형이 실제 프로세스 트리를 생성하고 두 번째 변형이 동일한 수준에서 모든 프로세스를 생성하고 마지막 변형이 프로세스를 생성하지 않는 것으로 나타났습니다 조금도. 이것은 나를 더 혼란스럽게하지만 어쨌든 도움이 될 수 있습니까?
답변
경고 생산 기계에서이 장치를 실행하지 마십시오. 그냥하지 마십시오.
경고 : “폭탄” ulimit -u
을 사용하려면 사용 중인지 확인하십시오 . 아래 [a]를 읽으십시오 .
PID와 날짜 (시간)를 얻는 함수를 정의 해 봅시다 :
bize:~$ d(){ printf '%7s %07d %s\n' "$1" "$BASHPID" "$(date +'%H:%M:%S')"; }
단순 비 문제 bomb
새로운 사용자에 대한 기능 (자신을 보호 : 읽기 [A] ) :
bize:~$ bomb() { d START; echo "yes"; sleep 1; d END; } >&2
해당 함수가 실행되도록 호출되면 다음과 같이 작동합니다.
bize:~$ bomb
START 0002786 23:07:34
yes
END 0002786 23:07:35
bize:~$
명령 date
이 실행 된 후 “yes”가 인쇄되고 1 초 동안 휴면 상태가 된 다음 닫기 명령이 종료 date
되고 마지막으로 함수는 새 명령 프롬프트 인쇄를 종료합니다. 멋진 것은 없습니다.
| 파이프
다음과 같이 함수를 호출하면
bize:~$ bomb | bomb
START 0003365 23:11:34
yes
START 0003366 23:11:34
yes
END 0003365 23:11:35
END 0003366 23:11:35
bize:~$
한 번에 두 개의 명령이 시작되고 1 초 후에 두 개의 명령이 시작된 후 프롬프트가 리턴됩니다.
이것이 |
두 프로세스를 병렬로 시작 하는 파이프의 이유입니다 .
& 배경
엔딩을 추가하여 통화를 변경하면 &
:
bize:~$ bomb | bomb &
[1] 3380
bize:~$
START 0003379 23:14:14
yes
START 0003380 23:14:14
yes
END 0003379 23:14:15
END 0003380 23:14:15
프롬프트가 즉시 리턴되고 (모든 조치가 백그라운드로 전송 됨) 두 명령이 이전과 같이 실행됩니다. [1]
프로세스의 PID 전에 “작업 번호”값이 인쇄됩니다 3380
. 나중에 파이프가 끝났음을 나타내는 동일한 번호가 인쇄됩니다.
[1]+ Done bomb | bomb
그 효과입니다 &
.
&
프로세스가 더 빨리 시작되도록 하는 이유입니다 .
더 간단한 이름
단순히 b
두 명령을 실행하기 위해 호출되는 함수를 만들 수 있습니다 . 세 줄로 입력 :
bize:~$ b(){
> bomb | bomb
> }
그리고 다음과 같이 실행됩니다.
bize:~$ b
START 0003563 23:21:10
yes
START 0003564 23:21:10
yes
END 0003564 23:21:11
END 0003563 23:21:11
우리 ;
는 정의에서 no 를 사용 했습니다 b
(개행은 요소를 분리하는 데 사용되었습니다). 그러나 한 줄에 대한 정의의 경우 다음과 같이을 사용하는 것이 일반적입니다 ;
.
bize:~$ b(){ bomb | bomb ; }
대부분의 공백도 필수는 아니며 이에 해당하는 문자를 작성할 수 있습니다 (그러나 덜 명확함).
bize:~$ b(){ bomb|bomb;}
또한 a &
를 사용 하여 }
(및 두 프로세스를 백그라운드로 전송) 분리 할 수 있습니다 .
폭탄.
함수가 자신을 호출하여 꼬리를 물게하면 “포크 폭탄”을 얻습니다.
bize:~$ b(){ b|b;} ### May look better as b(){ b | b ; } but does the same.
더 많은 함수를 더 빨리 호출하려면 파이프를 백그라운드로 보냅니다.
bize:~$ b(){ b|b&} ### Usually written as b(){ b|b& }
필요한 후에 함수에 첫 번째 호출을 추가하고 ;
이름을 다음과 같이 변경 :
하면 다음을 얻습니다.
bize:~$ :(){ :|:&};:
또는 다른 이름 (눈사람)과 함께 재미있는 방식으로 작성되었습니다.
☃(){ ☃|☃&};☃
ulimit (이를 실행하기 전에 설정해야 함)는 많은 오류가 발생한 후 프롬프트를 매우 빠르게 리턴합니다 (오류 목록이 중지되면 프롬프트를 표시하기 위해 Enter를 누르십시오).
이것을 “포크 폭탄”이라고 부르는 이유는 쉘이 서브 쉘을 시작하는 방법은 실행중인 쉘을 포크 한 다음 exec ()를 실행 명령과 함께 포크 프로세스에 호출하기 때문입니다.
파이프는 두 개의 새로운 프로세스를 “포크”합니다. 무한대로하면 폭탄이 생깁니다.
또는 토끼가 너무 빨리 번식하기 때문에 처음에 불렀던 토끼.
타이밍:
-
:(){ (:) | (:) }; time :
종료 된
실제 0m45.627s -
:(){ : | :; }; time :
종료 된
실제 0m -
:(){ : | :& }; time :
real 0m00.002 s
여전히 실행 중
귀하의 예 :
-
:(){ (:) | (:) }; :
두 번째 마감이
)
분리되는 곳}
은보다 복잡한 버전입니다:(){ :|:;};:
. 파이프의 각 명령은 어쨌든 서브 쉘 내부에서 호출됩니다. 어느의 효과입니다()
. -
:(){ : | :& }; :
공백이 없도록 작성된 더 빠른 버전입니다
:(){(:)|:&};:
(13 자). -
:(){ : | : }; :
###은 zsh에서는 작동하지만 bash에서는 작동하지 않습니다.bash에서 구문 오류가 발생
하면 다음}
과
같이 닫기 전에 메타 문자가 필요 합니다.:(){ : | :; }; :
[a]
새로운 깨끗한 사용자를 만드십시오 (내에게 전화하겠습니다bize
). 콘솔에서이 새로운 사용자에 로그인sudo -i -u bize
하거나
$ su - bize
Password:
bize:~$
max user processes
한계를 확인한 후 변경하십시오 .
bize:~$ ulimit -a ### List all limits (I show only `-u`)
max user processes (-u) 63931
bize:~$ ulimit -u 10 ### Low
bize:~$ ulimit -a
max user processes (-u) 1000
10 명만 사용하면 독방 신규 사용자가 한 명뿐입니다 bize
. killall -u bize
대부분의 폭탄을 시스템에서 쉽게 호출 하여 제거 할 수 있습니다. 어느 쪽이 여전히 작동하는지 묻지 마십시오. 그러나 여전히 : 매우 낮지 만 안전한면에서 시스템에 적응하십시오 .
이렇게 하면 “포크 폭탄”이 시스템을 무너 뜨리지 않습니다 .
더 읽을 거리 :