이 bash 포크 폭탄은 왜 다르게 작동하며 &의 의미는 무엇입니까? 일반적인 bash 포크 폭탄의

일반적인 포크 폭탄의 작동 방식을 알지만 일반적인 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 ()를 실행 명령과 함께 포크 프로세스에 호출하기 때문입니다.

파이프는 두 개의 새로운 프로세스를 “포크”합니다. 무한대로하면 폭탄이 생깁니다.
또는 토끼가 너무 빨리 번식하기 때문에 처음에 불렀던 토끼.


타이밍:

  1. :(){ (:) | (:) }; time :
    종료 된
    실제 0m45.627s

  2. :(){ : | :; }; time :
    종료 된
    실제 0m

  3. :(){ : | :& }; time :
    real 0m00.002 s
    여전히 실행 중


귀하의 예 :

  1. :(){ (:) | (:) }; :

    두 번째 마감이 )분리되는 곳 }은보다 복잡한 버전입니다 :(){ :|:;};:. 파이프의 각 명령은 어쨌든 서브 쉘 내부에서 호출됩니다. 어느의 효과입니다 ().

  2. :(){ : | :& }; :

    공백이 없도록 작성된 더 빠른 버전입니다 :(){(:)|:&};:(13 자).

  3. :(){ : | : }; : ###은 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대부분의 폭탄을 시스템에서 쉽게 호출 하여 제거 할 수 있습니다. 어느 쪽이 여전히 작동하는지 묻지 마십시오. 그러나 여전히 : 매우 낮지 만 안전한면에서 시스템에 적응하십시오 .
이렇게 하면 “포크 폭탄”이 시스템을 무너 뜨리지 않습니다 .

더 읽을 거리 :


답변