헤드 스크립트 출력 설명

헤드 스크립트 출력 설명

따라서 이 쉘 스크립트는 다음과 같습니다.

#!/bin/bash
head >/dev/null;
head;

시퀀스 번호(예: seq 10000 | ./sscript)를 사용하여 호출하면 거의 항상 동일한 출력을 제공합니다.

산출:

     //blank line
1861
1862
1863
1864
1865
1866
1867
1868
1869

나는 그것을 추적했지만 strace seq 10000 | ./sscript이 숫자가 정확히 어디서 왔는지 스스로 설명할 수 없었습니다. strace가 끝나면:

write(1, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14"..., 4096) = 4096
write(1, "1\n1042\n1043\n1044\n1045\n1046\n1047\n"..., 4096) = 4096
write(1, "\n1861\n1862\n1863\n1864\n1865\n1866\n1"..., 4096) = 4096
write(1, "2680\n2681\n2682\n2683\n2684\n2685\n26"..., 4096) = 4096
write(1, "499\n3500\n3501\n3502\n3503\n3504\n350"..., 4096) = 4096
write(1, "18\n4319\n4320\n4321\n4322\n4323\n4324"..., 4096) = 4096
write(1, "7\n5138\n5139\n5140\n5141\n5142\n5143\n"..., 4096) = 4096
write(1, "\n5957\n5958\n5959\n5960\n5961\n5962\n5"..., 4096) = 4096
write(1, "6776\n6777\n6778\n6779\n6780\n6781\n67"..., 4096) = 4096
write(1, "595\n7596\n7597\n7598\n7599\n7600\n760"..., 4096) = 4096
write(1, "14\n8415\n8416\n8417\n8418\n8419\n8420"..., 4096) = 4096
write(1, "3\n9234\n9235\n9236\n9237\n9238\n9239\n"..., 3838) = 3838

write세 번째 항목만 반환되는 이유는 무엇입니까(경우에 따라 두 번째 항목만 반환됨)?

실제로 스크립트의 두 번째 줄 때문에 반환 줄의 처음 10줄(세 번째 또는 두 번째 쓰기)만 인쇄되지만 head여전히 손실됩니다.

답변1

head기본적으로 10줄을 인쇄하지만 이렇게 하면 가능한 한 많은 입력을 읽습니다. GNU에는 head파일에 총 몇 줄이 있는지 알아야 하는 몇 가지 옵션이 있으므로 다음과 같이 읽는 데 아무런 문제가 없습니다. 가능한 한 많이.

head8192바이트로 보이는 버퍼를 채우기 위해 가능한 한 많이 읽어옵니다.

~ seq 10000 | strace -fe read ./foo.sh
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\260e\1\0\0\0\0\0"..., 832) = 832
...
Process 17610 attached
...
[pid 17610] read(0, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14"..., 8192) = 8192
...
[pid 17611] read(0, "\n1861\n1862\n1863\n1864\n1865\n1866\n1"..., 8192) = 8192
...

처음 두 쓰기는 각각 4096바이트이므로 첫 번째 쓰기에서 사용할 수 있습니다 head.

타이밍에 따라 다릅니다. 첫 번째 항목이 10줄을 인쇄하고 종료할 때 하나가 성공적으로 제거되면 seq두 번째 항목이 두 번째 항목에 의해 제거됩니다.writeheadwritehead

이것Mike Self의 의견매우 계몽적입니다:

일반 파일을 사용해 보세요.

seq 10000 >/tmp/nums; yourscript </tmp/nums

예상한 대로 동작하는 이유는 head출력을 사용하여 현재 읽기 지점을 읽기 지점 다음 줄로 재배치하려고 시도하기 때문입니다.lseek(). 이는 일반 파일, 리디렉션된 파일 등에 대해서는 작동하지만 파이프에는 작동하지 않습니다.

The lseek() function shall fail if:

...

ESPIPE The fildes argument is associated with a pipe, FIFO, or socket.

이는 다음을 사용하여 볼 수 있습니다 strace.

~ seq 10000 | strace -fe lseek ./foo.sh
...
Process 18561 attached
[pid 18561] lseek(0, -8171, SEEK_CUR)   = -1 ESPIPE (Illegal seek)
[pid 18561] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=18561, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
Process 18562 attached
[pid 18562] lseek(0, -8146, SEEK_CUR)   = -1 ESPIPE (Illegal seek)
...

관련 정보