startx내 X를 평가하는 데 사용 합니다 .xinitrc. 내 .xinitrc에서을 사용하여 창 관리자를 시작 /usr/bin/mywm합니다. 이제 WM을 죽이면 (다른 WM을 테스트하기 위해) .xinitrc스크립트가 EOF에 도달 했기 때문에 X도 종료됩니다 . 그래서 나는 이것을 내 끝에 추가했다 .xinitrc:
while true; do sleep 10000; done
이렇게하면 WM을 죽이면 X가 종료되지 않습니다. 이제 내 질문 : 루핑 수면 대신 무한 수면을 어떻게 할 수 있습니까? 스크립트를 정지시키는 것과 같은 명령이 있습니까?
친애하는
답변
sleep infinity 고양이 학대없이 제안하고 작동하는 것을 정확하게 수행합니다.
답변
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. 차단 read( 대기자)을 기다리면 coproc완료됩니다. 슬프게도 이것은 두 개의 PID와 a를 열어 두어야합니다 fifo.
명명 된 변형 fifo
named를 사용하지 않으면 fifo다음과 같이 할 수 있습니다.
mkfifo "$HOME/.pause.fifo" 2>/dev/null; read <"$HOME/.pause.fifo"
읽기에 루프를 사용하지 않는 것은 약간 느슨하지만, fifo원하는만큼 자주 재사용 하고 reads를 사용하여 터미널을 사용할 수 있습니다 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 버전보다 효율적이지 않지만 작동합니다.
당신을위한 나의 추천 :
반복 수면을 유지하십시오. 이해하기 쉽고 휴대 성이 뛰어나며 대부분의 시간을 차단합니다.
답변
어쩌면 이것이 못생긴 것처럼 보이지만 실행을 cat계속하고 입력을 영원히 기다리게 하지 않는 이유는 무엇입니까?
답변
TL; DR : sleep infinity실제로 허용 된 최대 시간을 잠들게합니다.
왜 이것이 어디에도 문서화되어 있지 않은지 궁금 해서 GNU coreutils 에서 소스 를 읽으려고 노력했으며 대략 다음과 같이 실행됩니다.
strtod‘무한대’를 배정도로 변환하려면 첫 번째 인수에서 C stdlib에서 사용하십시오 . 따라서 IEEE 754 배정도를 가정하면 64 비트 양의 무한대 값이seconds변수에 저장됩니다 .- 호출은
xnanosleep(seconds)( gnulib에서 발견 )이 차례를 발동에dtotimespec(seconds)( 도 gnulib의 ) 변환하는 방법double에struct timespec. struct timespec정수 부분 (초)과 소수 부분 (나노초)의 숫자 쌍입니다. 양의 무한대 를 정수 로 순전히 변환 하면 정의되지 않은 동작이 발생하고 (C 표준의 §6.3.1.4 참조) 대신로 절단됩니다TYPE_MAXIMUM (time_t).- 실제 값은
TYPE_MAXIMUM (time_t)표준에 설정되어 있지 않습니다 (sizeof(time_t)그렇지 않더라도). 예를 들어 최근 Linux 커널에서 x86-64를 선택하겠습니다.
이것은 TIME_T_MAXLinux 커널에 있으며 다음과 같이 ( time.h)로 정의 됩니다.
(time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
참고 time_t인 __kernel_time_t및 time_t입니다 long; LP64 데이터 모델이 사용되므로 sizeof(long)8 (64 비트)도 사용됩니다.
결과 : TIME_T_MAX = 9223372036854775807.
즉 sleep infinite, 실제 절전 시간은 9223372036854775807 초 (10 ^ 11 년)입니다. 그리고 32 비트 리눅스 시스템의 경우 ( sizeof(long)4 (32 비트)) : 2147483647 초 (68 년; 2038 년 문제 도 참조하십시오 ).
편집 : 분명히 nanoseconds호출 된 함수는 직접 syscall이 아니라 OS 종속 래퍼 ( gnulib에 정의되어 있음 )입니다.
그 결과로 추가 단계가 있습니다 : 일부 시스템 HAVE_BUG_BIG_NANOSLEEP인 true수면 24 일립니다 다음 루프에서했다. 이것은 일부 (또는 모두?) Linux 배포판의 경우입니다. configure- time 테스트가 성공한 경우 ( source ) 이 랩퍼를 사용할 수 없습니다 .
특히, 24 * 24 * 60 * 60 = 2073600 seconds(99999999 나노초 플러스); 그러나 지정된 총 절전 시간을 준수하기 위해 루프에서 호출됩니다. 따라서 이전 결론은 유효합니다.
결론적 으로 , 결과적인 실제 시간 경과가 휴대용이 아닌 경우에도 결과적인 수면 시간 은 무한하지만 모든 실제적인 목적을 위해 충분히 높을 수 없다. OS와 아키텍처에 따라 다릅니다.
원래 질문에 대답하기에, 이것은 분명히 충분하지만 어떤 이유로 ( 매우 자원이 제한된 시스템) 쓸모없는 여분의 카운트 다운 타이머를 피하고 싶다면 가장 적합한 대안은 cat다른 답변에 설명 된 방법 을 사용하는 것입니다 .
답변
sleep infinity가장 우아해 보이지만 때로는 어떤 이유로 작동하지 않습니다. 이 경우, 다른 차단 명령과 같은 시도 할 수 있습니다 cat, read, tail -f /dev/null, grep a등
답변
SIGSTOP 을 자신 에게 보내는 것은 어떻습니까?
SIGCONT가 수신 될 때까지 프로세스를 일시 정지해야합니다. 당신의 경우에는 : 결코.
kill -STOP "$$";
# grace time for signal delivery
sleep 60;
답변
왜 sleep infinity문서화되지 않았지만 작동 하는지 설명하겠습니다 . jp48의 답변 도 유용합니다.
가장 중요한 것 : inf또는 infinity(대소 문자를 구분하지 않음) 을 지정 하면 구현에서 허용하는 가장 긴 시간 동안 (예 : HUGE_VAL및 값이 더 작은) 휴면 상태가 될 수 있습니다 TYPE_MAXIMUM(time_t).
이제 세부 사항을 파헤쳐 보자. sleep명령 소스 코드는 coreutils / src / sleep.c 에서 읽을 수 있습니다 . 기본적으로 함수는 다음을 수행합니다.
double s; //seconds
xstrtod (argv[i], &p, &s, cl_strtod); //`p` is not essential (just used for error check).
xnanosleep (s);
이해 xstrtod (argv[i], &p, &s, cl_strtod)
xstrtod()
gnulib / lib / xstrtod.c 에 따르면 , 호출은 변환 함수를 사용하여 xstrtod()문자열 argv[i]을 부동 소수점 값 *s으로 변환하여 저장합니다 cl_strtod().
cl_strtod()
에서 볼 수 있듯이 로 coreutils / lib 디렉토리 / CL-strtod.c , cl_strtod()사용, 부동 소수점 값에 문자열로 변환합니다 strtod().
strtod()
에 따르면 man 3 strtod, strtod()유형의 값에 문자열로 변환합니다 double. 맨 페이지 말한다
(문자열의 초기 부분)의 예상 형식은 … 또는 (iii) 무한대 또는 …
무한대는
무한대는 대소 문자를 무시하고 “INF”또는 “INFINITY”입니다.
문서가 알려 주지만
올바른 값으로 오버플로가 발생하면 더하기 또는 빼기
HUGE_VAL(HUGE_VALF,HUGE_VALL)가 반환됩니다.
무한대가 어떻게 취급되는지는 명확하지 않다. 소스 코드 gnulib / lib / strtod.c를 보자 . 우리가 읽고 싶은 것은
else if (c_tolower (*s) == 'i'
&& c_tolower (s[1]) == 'n'
&& c_tolower (s[2]) == 'f')
{
s += 3;
if (c_tolower (*s) == 'i'
&& c_tolower (s[1]) == 'n'
&& c_tolower (s[2]) == 'i'
&& c_tolower (s[3]) == 't'
&& c_tolower (s[4]) == 'y')
s += 5;
num = HUGE_VAL;
errno = saved_errno;
}
따라서, INF및 INFINITY(대소 문자 구별)는 다음과 같이 간주된다 HUGE_VAL.
HUGE_VAL 가족
N1570 을 C 표준으로 사용합시다 . HUGE_VAL, HUGE_VALF및 HUGE_VALL매크로에 정의되어 §7.12-3
매크로
HUGE_VAL
는 양의 상수 상수로 확장되며 반드시 부동 소수점으로 표현할 필요는 없습니다. 매크로
HUGE_VALF
HUGE_VALL
는 각각 부동 및 긴 이중 아날로그입니다HUGE_VAL.
HUGE_VAL,HUGE_VALF및HUGE_VALL인피니티를 지원하는 구현에서 긍정적 인 인피니티 일 수 있습니다.
§7.12.1-5
부동 결과가 오버 플로우 및 기본 반올림이 적용되는 경우,이 함수는 매크로의 값을 반환
HUGE_VAL,HUGE_VALF또는HUGE_VALL반환 형식에 따라
이해 xnanosleep (s)
이제 우리는의 모든 본질을 이해합니다 xstrtod(). 위의 설명에서, xnanosleep(s)우리가 실제로 본 것은 실제로 의미 하는 것은 명백합니다 xnanosleep(HUGE_VALL).
xnanosleep()
소스 코드 gnulib / lib / xnanosleep.c에 따르면 xnanosleep(s)본질적으로 다음을 수행합니다.
struct timespec ts_sleep = dtotimespec (s);
nanosleep (&ts_sleep, NULL);
dtotimespec()
이 함수는 type 인수를 type double객체 로 변환합니다 struct timespec. 매우 간단하므로 소스 코드 gnulib / lib / dtotimespec.c를 인용 하겠습니다 . 모든 의견은 저에 의해 추가됩니다.
struct timespec
dtotimespec (double sec)
{
if (! (TYPE_MINIMUM (time_t) < sec)) //underflow case
return make_timespec (TYPE_MINIMUM (time_t), 0);
else if (! (sec < 1.0 + TYPE_MAXIMUM (time_t))) //overflow case
return make_timespec (TYPE_MAXIMUM (time_t), TIMESPEC_HZ - 1);
else //normal case (looks complex but does nothing technical)
{
time_t s = sec;
double frac = TIMESPEC_HZ * (sec - s);
long ns = frac;
ns += ns < frac;
s += ns / TIMESPEC_HZ;
ns %= TIMESPEC_HZ;
if (ns < 0)
{
s--;
ns += TIMESPEC_HZ;
}
return make_timespec (s, ns);
}
}
이후 time_t일체형으로 정의된다 (§7.27.1-3 참조), 우리가 유형의 최대 값이 가정 자연 time_t보다 작다 HUGE_VAL(유형 double우리가 오버 플로우하는 경우 입력 수단). (실제로이 절차는 본질적으로 동일하기 때문에이 가정은 필요하지 않습니다.)
make_timespec()
우리가 올라 가야하는 마지막 벽은 make_timespec()입니다. 운 좋게도 소스 코드 gnulib / lib / timespec.h 를 인용하면 충분합니다.
_GL_TIMESPEC_INLINE struct timespec
make_timespec (time_t s, long int ns)
{
struct timespec r;
r.tv_sec = s;
r.tv_nsec = ns;
return r;
}
