IT박스

배쉬 : 무한 수면 (무한 차단)

itboxs 2020. 6. 30. 20:57
반응형

배쉬 : 무한 수면 (무한 차단)


startx내 X를 평가하는 데 사용 합니다 .xinitrc. .xinitrc에서을 사용하여 창 관리자를 시작 /usr/bin/mywm합니다. 이제 WM을 죽이면 (다른 WM을 테스트하기 위해) .xinitrc스크립트가 EOF에 도달 했기 때문에 X도 종료됩니다 . 그래서 나는 이것을 내 끝에 추가했다 .xinitrc:

while true; do sleep 10000; done

이렇게하면 WM을 죽이면 X가 종료되지 않습니다. 이제 내 질문 : 반복 수면 대신 무한 수면을 어떻게 할 수 있습니까? 스크립트를 정지시키는 것과 같은 명령이 있습니까?

친애하는


sleep infinity 고양이 학대없이 제안하고 작동하는 것을 정확하게 수행합니다.


어쩌면 이것이 못생긴 것처럼 보이지만 실행을 cat계속하고 입력을 영원히 기다리게 하지 않겠습니까?


tail 차단하지 않습니다

항상 그렇듯이 : 모든 것에 대해 짧고 이해하기 쉽고 따르기 쉽고 완전히 잘못된 대답이 있습니다. 여기이 tail -f /dev/null범주에 속합니다.)

당신이 그것을 보시면 strace tail -f /dev/null이 솔루션은 차단되지 않습니다! sleepLinux와 같은 inotify시스템 과 같은 귀중한 리소스를 사용하기 때문에 문제 솔루션 보다 훨씬 나쁠 수 있습니다. 또한 루프 /dev/null만들기 위해 쓰는 다른 프로세스 tail. (Ubuntu64 16.10에서는 이미 사용량이 많은 시스템에서 초당 10 회의 syscall이 추가됩니다.)

문제는 차단 명령이었습니다

불행히도, 그런 것은 없습니다 ..

읽는다 : 나는 이것을 쉘로 직접 보관할 방법을 모른다.

모든 sleep infinity신호는 심지어 일부 신호에 의해 중단 될 수 있습니다. 따라서 예외적으로 반환되지 않는지 확인하려면 이미 수행 한 것처럼 루프에서 실행해야합니다 sleep. (Linux의 경우) /bin/sleep24 일에 한도를 정했다는 점을 명심하십시오 ( strace sleep infinity따라서 살펴보십시오 ).

while :; do sleep 2073600; done

( sleep24 일보다 높은 값으로 내부적으로 루프를 믿지만 이것은 차단되지 않고 매우 느리게 반복된다는 것을 의미합니다. 왜이 루프를 외부로 옮기지 않겠습니까?)

.. 그러나 당신은 이름 없는와 꽤 가까이 올 수 있습니다 fifo

프로세스에 신호가 전송되지 않는 한 실제로 차단되는 것을 만들 수 있습니다. 다음과 같은 용도 bash 4로 2 개의 PID와 1을 사용합니다 fifo.

bash -c 'coproc { exec >&-; read; }; eval exec "${COPROC[0]}<&-"; wait'

원하는 strace경우 이것이 실제로 차단 되는지 확인할 수 있습니다.

strace -ff bash -c '..see above..'

이것이 어떻게 구성 되었는가

read입력 데이터가 없으면 차단합니다 (다른 답변 참조). 그러나 tty(일명. stdin)은 일반적으로 사용자가 로그 아웃 할 때 닫히기 때문에 좋은 소스가 아닙니다. 또한에서 일부 입력을 도용 할 수 있습니다 tty. 좋지 않아.

read차단 하려면 fifo아무것도 반환하지 않는 것과 같은 것을 기다릴 필요가 있습니다. 에서 bash 4정확히 같은 우리를 제공 할 수있는 명령이 있습니다 fifo: coproc. 차단을 기다리는 경우 (우리 readcoproc)가 완료됩니다. 슬프게도 이것은 두 개의 PID와 a를 열어 두어야합니다 fifo.

명명 된 변형 fifo

named를 사용하지 않으면 fifo다음과 같이 할 수 있습니다.

mkfifo "$HOME/.pause.fifo" 2>/dev/null; read <"$HOME/.pause.fifo"

읽기에 루프를 사용하지 않는 것은 약간의 실수,하지만 당신은이를 다시 사용할 수 있습니다 fifo로 자주로 같은과하게 read사용 terminat들 touch "$HOME/.pause.fifo"(더 하나의 읽기 대기 이상이있는 경우, 모두 한 번에 종료됩니다).

또는 Linux pause()syscall을 사용하십시오.

무한 차단을 위해 리눅스 커널 호출이 있는데, pause()우리가 원하는 것을한다 : 신호가 도착할 때까지 영원히 기다린다. 그러나 이것에 대한 사용자 공간 프로그램은 아직 없습니다.

그러한 프로그램을 만드는 것은 쉽습니다. 여기라는 매우 작은 리눅스 프로그램을 만들 수있는 조각이다 pause무기한 (요구 일시 정지 diet, gcc등)

printf '#include <unistd.h>\nint main(){for(;;)pause();}' > pause.c;
diet -Os cc pause.c -o pause;
strip -s pause;
ls -al pause

python

직접 컴파일하고 싶지 않지만 python설치 한 경우 Linux에서이를 사용할 수 있습니다.

python -c 'while 1: import ctypes; ctypes.CDLL(None).pause()'

(참고 : exec python -c ...현재 셸을 교체하는 데 사용 하면 PID 하나가 해제됩니다. 일부 IO 리디렉션을 사용하여 솔루션을 개선하여 사용하지 않는 FD를 해제 할 수도 있습니다. 이는 사용자에게 달려 있습니다.)

작동 방식 (제 생각) : ctypes.CDLL(None)표준 C 라이브러리를로드하고 pause()추가 루프 내 에서 함수를 실행합니다 . C 버전보다 효율적이지 않지만 작동합니다.

당신을위한 나의 추천 :

반복 수면을 유지하십시오. 이해하기 쉽고 휴대 성이 뛰어나며 대부분의 시간을 차단합니다.


TL; DR : sleep infinity실제로 허용 된 최대 시간을 잠들게합니다.

왜 이것이 어디에도 문서화되어 있지 않은지 궁금 해서 GNU coreutils 에서 소스 를 읽으려고 애썼 으며 대략 다음과 같이 실행됩니다.

  1. Use strtod from C stdlib on the first argument to convert 'infinity' to the double precision. So, assuming IEEE 754 double precision the 64-bit positive infinity value is stored in the seconds variable.
  2. Invoke xnanosleep(seconds) (found in gnulib), this in turn invokes dtotimespec(seconds) (also in gnulib) to convert from double to struct timespec.
  3. struct timespec is just a pair of numbers: integer part (in seconds) and fractional part (in nanoseconds). Naïvely converting positive infinity to integer would result in undefined behaviour (see §6.3.1.4 from C standard), so instead it truncates to TYPE_MAXIMUM (time_t).
  4. The actual value of TYPE_MAXIMUM (time_t) is not set in the standard (even sizeof(time_t) isn't); so, for the sake of example let's pick x86-64 from a recent Linux kernel.

This is TIME_T_MAX in the Linux kernel, which is defined (time.h) as:

(time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)

Note that time_t is __kernel_time_t and time_t is long; the LP64 data model is used, so sizeof(long) is 8 (64 bits).

Which results in: TIME_T_MAX = 9223372036854775807.

That is: sleep infinite results in an actual sleep time of 9223372036854775807 seconds (10^11 years). And for 32-bit linux systems (sizeof(long) is 4 (32 bits)): 2147483647 seconds (68 years; see also year 2038 problem).


Edit: apparently the nanoseconds function called is not directly the syscall, but an OS-dependent wrapper (also defined in gnulib).

There's an extra step as a result: for some systems where HAVE_BUG_BIG_NANOSLEEP is true the sleep is truncated to 24 days and then called in a loop. This is the case for some (or all?) Linux distros. Note that this wrapper may be not used if a configure-time test succeeds (source).

In particular, that would be 24 * 24 * 60 * 60 = 2073600 seconds (plus 999999999 nanoseconds); but this is called in a loop in order to respect the specified total sleep time. Therefore the previous conclusions remain valid.


In conclusion, the resulting sleep time is not infinite but high enough for all practical purposes, even if the resulting actual time lapse is not portable; that depends on the OS and architecture.

To answer the original question, this is obviously good enough but if for some reason (a very resource-constrained system) you really want to avoid an useless extra countdown timer, I guess the most correct alternative is to use the cat method described in other answers.


sleep infinity looks most elegant, but sometimes it doesn't work for some reason. In that case, you can try other blocking commands such as cat, read, tail -f /dev/null, grep a etc.


What about sending a SIGSTOP to itself?

This should pause the process until SIGCONT is received. Which is in your case: never.

kill -STOP "$$";
# grace time for signal delivery
sleep 60;

I recently had a need to do this. I came up with the following function that will allow bash to sleep forever without calling any external program:

snore()
{
    local IFS
    [[ -n "${_snore_fd:-}" ]] || { exec {_snore_fd}<> <(:); } 2>/dev/null ||
    {
        # workaround for MacOS and similar systems
        local fifo
        fifo=$(mktemp -u)
        mkfifo -m 700 "$fifo"
        exec {_snore_fd}<>"$fifo"
        rm "$fifo"
    }
    read ${1:+-t "$1"} -u $_snore_fd || :
}

NOTE: I previously posted a version of this that would open and close the file descriptor each time, but I found that on some systems doing this hundreds of times a second would eventually lock up. Thus the new solution keeps the file descriptor between calls to the function. Bash will clean it up on exit anyway.

This can be called just like /bin/sleep, and it will sleep for the requested time. Called without parameters, it will hang forever.

snore 0.1  # sleeps for 0.1 seconds
snore 10   # sleeps for 10 seconds
snore      # sleeps forever

There's a writeup with excessive details on my blog here


Instead of killing the window manager, try running the new one with --replace or -replace if available.


This approach will not consume any resources for keeping process alive.

while :; do sleep 1; done & kill -STOP $! && wait $!

Breakdown

  • while :; do sleep 1; done & Creates a dummy process in background
  • kill -STOP $! Stops the background process
  • wait $! Wait for the background process, this will be blocking forever, cause background process was stopped before

while :; do read; done

no waiting for child sleeping process.

참고URL : https://stackoverflow.com/questions/2935183/bash-infinite-sleep-infinite-blocking

반응형