고쳐 쓰다

고쳐 쓰다

내 스크립트는 입력 스트림의 데이터 존재 여부에 따라 다르게 동작해야 합니다. 따라서 다음과 같이 호출할 수 있습니다.

$ my-script.sh

또는:

$ my-script.sh <<-MARK
    Data comes...
    ...data goes.
MARK

또는:

$ some-command | my-script.sh

마지막 두 사례는 데이터를 읽어야 하고, 첫 번째 사례는 데이터 손실을 확인하고 그에 따라 조치를 취해야 합니다.

스크립트(발췌)의 주요 부분은 다음과 같습니다.

#!/bin/bash
local myData;
read -d '' -t 0 myData;

[ -z "${myData}" ] && {
    # Notice the lack of the data.
} || {
    # Process the data.
}

나는 read입력 데이터를 읽은 다음 -d ''여러 행(예상)을 읽고 -t 0시간 제한을 0으로 설정하도록 선택했습니다. 시간 초과 이유는 무엇입니까? ~에 따르면help read(입력은 변경되지 않고 그대로 유지됩니다. 굵은 글씨는 제가 쓴 것입니다):

-t timeout전체 입력 줄을 몇 초 내에 읽지 않으면 시간이 초과되어 failure 를 반환합니다 TIMEOUT. 이 변수의 값은 TMOUT 기본 시간 초과입니다. TIMEOUT어쩌면 십진수 일 수도 있습니다. 0 인 경우 TIMEOUT지정된 파일 설명자에서 입력이 가능한 경우에만 읽기가 성공을 반환합니다.. 시간 초과가 초과되면 종료 상태가 128보다 큽니다.

그래서 제가 이해한 바에 따르면, 2번과 3번의 경우 데이터를 즉시 읽어야 합니다. 불행히도 이것은 사실이 아닙니다. -t(위 매뉴얼 페이지에 따라) 십진수 값을 취할 수 있으므로 읽기 행을 다음과 같이 변경하십시오 .

read -d '' -t 0.01 myData;

데이터가 있으면 실제로 읽고, 없으면 건너뜁니다(10ms 시간 초과 후). 하지만 TIMEOUTreal 로 설정해도 작동합니다 0.

실제로는 왜 안 됩니까?이 문제를 어떻게 해결하나요? 어쩌면 "데이터 존재에 따라 다르게 행동"하는 문제에 대한 다른 해결책이 있을까요?

고쳐 쓰다

@Isaac에게 감사드립니다. 인용된 온라인 버전과 내 로컬 버전 사이에 오해의 소지가 있는 차이점을 발견했습니다. (보통 로캘이 en_US로 설정되어 있지 않아 help read번역이 제공되지만 여기에 붙여넣을 수는 없습니다. 새로운 환경을 설정하는 것보다 온라인 번역이 더 빠르지만 그것이 전체 문제의 원인입니다).

따라서 Bash 버전 4.4.12의 경우:

TIMEOUT이 0이면 읽기가 즉시 반환됩니다.데이터를 읽으려고 시도하지 않고, 지정된 파일 설명자에서 입력이 가능한 경우에만 성공을 반환합니다.

이는 "TIMEOUT이 0인 경우 지정된 파일 설명자에서 입력이 가능한 경우에만 읽기가 성공을 반환합니다"라는 인상을 줍니다. 나에게 이것은 실제로 데이터를 읽으려고 시도하는 것을 의미합니다.

그래서 마침내 이것을 테스트했고 잘 작동했습니다.

read -t 0 && read -d '' myData;

의미: 읽을 것이 있는지 확인하고 성공하면 읽으십시오.

이삭은 기본적인 질문에 대한 정답을 제시합니다. 대체 솔루션에 관해서는 위의 "읽기 && 읽기" 접근 방식을 선호합니다.

답변1

read -t 0안 돼아니요모든 데이터를 읽으십시오.

당신은 잘못된 매뉴얼을 읽고 있습니다. man readPATH에 이름이 지정된 프로그램에 대한 매뉴얼을 제공 합니다 read. 이것은 매뉴얼이 아니다내장불다 read.

Bash 매뉴얼 페이지를 읽으려면 다음 man bash을 사용하여 검색 read [-ers]하거나 간단히 사용하십시오.

help read

다음 내용이 포함되어 있습니다(버전 4.4).

시간 초과가 0이면 데이터 읽기를 시도하지 않고 즉시 read가 반환됩니다.

따라서 아니요. 데이터를 읽는 데는 사용되지 않습니다 -t 0.


  1. 1분기

    실제로는 왜 안 됩니까?

왜냐하면 이것이 문서화된 작업 방식이기 때문입니다.

  1. 2분기

    이 문제를 어떻게 해결하나요?

이것이 버그로 간주되고(아마 그럴 것으로 의심됨) bash 소스 코드가 변경된 경우에만 가능합니다.

  1. 3분기

    어쩌면 "데이터 존재에 따라 다르게 행동"하는 문제에 대한 다른 해결책이 있을까요?

예, 실제로 해결책이 있습니다. help read위에서 인용한 내용 이후의 다음 문장은 다음과 같습니다.

지정된 파일 설명자에서 입력이 가능한 경우에만 성공을 반환합니다.

이는 데이터를 읽지 않더라도 사용 가능한 데이터의 실제 읽기를 트리거하는 데 사용될 수 있음을 의미합니다.

read -t 0 && read -d '' myData

[ "$myData" ] && echo "got input" || echo "no input was available"

이렇게 하면 지연이 발생하지 않습니다.

답변2

공개: 엄밀한 답변은 아니고 흔들림이 많습니다.

여기에는 몇 가지 일이 작용하고 있습니다. 먼저 bash내부적으로 제로 타임아웃을 처리합니다.완전히0이 아닌 시간 초과와 다릅니다. (코드를 보기로 결정했다면 시간을 할애할 준비를 하십시오. 생각만큼 간단하지는 않습니다. 상당히 심층적입니다.)

둘째, 파이프를 사용할 때 고유한 경쟁 조건이 있습니다. 프로세스는 "오른쪽에서 왼쪽으로" 생성됩니다. 즉, 명령줄의 마지막 프로세스가 먼저 생성됩니다. 그러나 셸이 계속 실행되어 이미 생성된 프로세스가 자체적으로 예약되기 전에 명령줄에서 추가 프로세스를 생성한다는 보장은 없습니다. 따라서 read입력이 준비되기 전에 실행될 가능성이 매우 높습니다. 특정 시스템에 따라 시간 초과 값을 약간 조정하면 -t 0유사한 방법을 사용하여 동작을 재현 할 수 있습니다 -t 0.00001. 1)

그 외에도 오늘날 대부분의 시스템이 병렬(멀티 코어 또는 멀티 프로세서)이라는 점을 고려하면 커널이 파이프라인의 모든 프로세스를 예약하는 방법에 따라 다른 결과를 얻을 수 있습니다(이에 영향을 미치는 한 가지는 현재 시스템 로드, 그나저나). taskset이 문제는 프로세스 그룹을 단일 특정 CPU로 제한하여 완화할 수 있습니다(예: 다음을 사용).


1)read 실제로는 부분적인 입력(3자 중 1~2자)만 받는 지점에 도달했습니다 .

관련 정보