무한 루프 종료


52

종료 할 때마다 자동으로 다시 실행하려는 명령이 있으므로 다음과 같이 실행했습니다.

while [ 1 ]; do COMMAND; done;

하지만 루프를 멈출 수 없다면 전체 루프 Ctrl-c가 아니라 죽 COMMAND입니다.

어떻게 비슷한 것을 얻을 수 있지만 터미널을 닫지 않고 멈출 수 있습니까?


11
내가 bash에 있다면 Ctrl-Z를 사용하여 작업을 중지 한 다음 "kill % 1"을 사용하여 작업을 종료하십시오.
Paul Cager

3
Linus는 “리눅스가 훌륭하다는 것을 알고 있습니다. 5 초 안에 무한 루프를합니다.” – 실제로 ... 몇 초만 더 기다리면 완료 될 것입니다.
lornix

@PaulCager도 저를 위해 일했습니다! 왜 Ctrl-C가 작동하지 않는 곳에서 작동합니까?
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

@cirosantilli 그것은 외부 작업 (bash "wrapper")을 죽입니다. 어떤 상황에서는 "COMMAND"를 즉시 죽이지 않을 것입니다. 예를 들어, 배경을 설정하면 부모가 죽어도 살아 숨어있을 수 있습니다. 그러나 루프는 죽었고 그것이 중요한 부분입니다.
오리온

답변:


37

명령의 종료 상태를 확인하십시오. 신호에 의해 명령이 종료 된 경우 종료 코드는 128 + 신호 번호입니다. 로부터 bash에 대한 GNU 온라인 설명서 :

쉘의 목적으로, 종료 상태가 0 인 명령이 성공했습니다. 종료 상태가 0이 아니면 실패를 나타냅니다. 이처럼 직관적으로 보이지 않는 방식이 사용되므로 성공을 나타내는 잘 정의 된 방법과 다양한 실패 모드를 나타내는 다양한 방법이 있습니다. 번호가 N 인 치명적 신호에서 명령이 종료되면 Bash는 종료 상태로 128 + N 값을 사용합니다.

POSIX는 또한 신호로 종료 된 명령의 값이 128보다 크지 만 GNU처럼 정확한 값을 지정하지 않는 것으로 지정합니다.

신호를 수신하여 종료 된 명령의 종료 상태는 128보다 큰 것으로보고됩니다.

예를 들어, control-C로 명령을 인터럽트하면 SIGINT가 Unix 시스템에서 신호 2이므로 종료 코드는 130이됩니다. 그래서:

while [ 1 ]; do COMMAND; test $? -gt 128 && break; done

9
이것이 보장되지는 않는다는 것을 언급해야합니다. 실제로 많은 응용 프로그램 에서이 작업을 수행하지 않습니다.
Chris Down

1
@Kyle Jones : POSIX / GNU 문서에 링크 할 수 있습니까?
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

@cirosantilli 님.
Kyle Jones

@KyleJones 감사합니다! 실제로 신호를 처리 paplay alert.ogg하기 때문에 COMMAND = 작동하지 paplay않습니까?
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

@cirosantilli 네, 그 이유입니다. 프로세스가 신호를 처리하고 종료하는 경우 처리되지 않은 신호로 종료되는 프로세스와 다릅니다.
Kyle Jones

48

ctrl+를 사용하여 작업을 실행하는 동안 백그라운드에서 작업을 중지하고 넣을 수 있습니다 z. 그런 다음 다음을 사용하여 작업을 종료 할 수 있습니다.

$ kill %1

여기서 [1]은 작업 번호입니다.


설명 및 자세한 내용은 이 답변 을 참조하십시오 .
Skippy le Grand Gourou

2
이 비교적 최근의 답변은 단순히 작동합니다. 공감해야합니다. +1
shivams

당신은 저를 많이 도와주었습니다. 이것은 내가이 질문에서 검색 한 것입니다 :)
Maximilian Ruta

18

무한 루프를 스크립트에 넣고 신호를 처리하는 것이 가장 좋습니다. 기본 시작점 은 다음과 같습니다 . 꼭 맞게 수정하고 싶을 것입니다. 스크립트는 - (또는 ) trap를 잡기 위해 사용 하고 명령을 종료하고 ( 여기서는 테스트로 사용 했습니다) 종료합니다.ctrlcSIGTERMsleep

cleanup ()
{
kill -s SIGTERM $!
exit 0
}

trap cleanup SIGINT SIGTERM

while [ 1 ]
do
    sleep 60 &
    wait $!
done

4
좋은. 다음은이 팁을 사용하여 자동 재시작 netcat 래퍼를 만드는 방법입니다.trap "exit 0" SIGINT SIGTERM; while true; do netcat -l -p 3000; done
Douglas

2
trap무한 루프를 사용하여 동일한 (bash) 스크립트 에이 접근 방식을 추가하는 경우 $$대신 사용 $!하십시오 ( 여기 참조 )
ardnew

15

나는 일반적으로 그냥 잡고 있습니다 Ctrl-C. 조만간 사이에 등록되어 루프 COMMAND를 종료합니다 while. 아마도 더 좋은 방법이있을 것입니다.


1
이유는 확실하지 않지만 paplay1s 파일 과 같은 특정 명령에는 실패 합니다.
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

그것은 나를 위해 일했다
Alexandr

이것이 모든 솔루션의 강력한 힘입니다. : /
Markroxor

8

bash를 실행 -e하면 오류 조건에서 종료됩니다.

#!/bin/bash -e
false # returns 1
echo This won't be printed

7

왜 간단하지 않습니까?

while [ 1 ]; do COMMAND || break; done;

또는 스크립트에서 사용될 때

#!/bin/bash
while [ 1 ]; do
  # ctrl+c terminates COMMAND and exits the while loop
  # (assuming COMMAND responds to ctrl+c)
  COMMAND || break
done;

1
매우 우아한 솔루션. 그러나 COMMAND가 항상 성공 종료 상태를 반환하는 경우에만 작동하지 않습니까?
howardh December

네 @howardh, 맞습니다.
데일 앤더슨

3

다른 솔루션을 선호합니다.

touch .runcmd; while [ -f ".runcmd" ]; do COMMAND; sleep 1; done

루프를 종료하려면 다음을 수행하십시오.

rm .runcmd && kill `pidof COMMAND`

2
  1. PID를 사용하여 프로세스를 항상 종료 할 수 있으므로 터미널을 닫을 필요가 없습니다.
  2. 데몬과 같은 무한 루프에서 무언가를 실행하려면 백그라운드에 두는 것이 가장 좋습니다.
  3. while : 무한 루프를 만들고 [ 1 ]

    while :; do COMMAND; done &

PID가 인쇄됩니다. 를 사용하여 프롬프트를 종료 ctrl+d하면 백그라운드 작업이 종료되지 않으며 나중에 다음을 사용하여 작업을 종료 할 수 있습니다kill PID

PID를 잃어버린 경우 pstree -pa $USER또는 PID pgrep -fl '.*PROCESS.*'를 찾도록 도와 줄 수 있습니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.