tail은 전체 파일을 읽습니까?


113

tail25GB 텍스트 tail파일을 원하면 명령이 전체 파일을 읽습니까?

파일이 디스크에 흩어져있을 수 있기 때문에 파일이 필요하다고 생각하지만 그러한 내부 구조를 잘 이해하지 못합니다.

답변:


119

아니요, tail전체 파일을 읽지 않고 끝까지 검색 한 다음 예상 줄 수에 도달 할 때까지 블록을 뒤로 읽은 다음 파일 끝까지 올바른 방향으로 행을 표시하고 -f옵션이 사용되는 경우 파일 .

그러나 tail파이프에서 읽을 때와 같이 검색 할 수없는 입력이 제공된 경우 전체 데이터를 읽는 것 외에는 선택의 여지가 없습니다.

마찬가지로, 지원되는 경우 tail -n +linenumber구문 또는 tail +linenumber비표준 옵션 을 사용하여 파일 시작 부분부터 시작하여 줄을 찾도록 요청 tail하면 전체 파일을 읽습니다 (중단되지 않은 경우).


14
젠장, 너무 빨리 :-). 관련 소스 코드 는 다음과 같습니다 . 파일 FD 끝에서 마지막 N_LINES 줄을 인쇄하십시오. 파일의 시작 부분을 누르거나 NUMBER 개의 줄 바꿈을 읽을 때까지 한 번에 'BUFSIZ'바이트를 읽고 파일을 뒤로 이동하십시오 (첫 번째는 제외).
Patrick

1
또한 tail +n전체 파일을 읽습니다. 먼저 원하는 수의 줄 바꿈을 찾은 다음 나머지를 출력합니다.
SF.

@SF. 실제로 답변이 업데이트되었습니다.
jlliagre

4
모든 tail구현이 제대로 수행 되지는 않습니다 . 예를 들어 busybox 1.21.1 tail은 이와 관련하여 손상되었습니다. 또한 때 행동이 달라주의 tail표준 입력을 보내고 및 표준 입력은 일반 파일과 파일의 초기 위치입니다 때 시작 부분에없는 tail(처럼 호출 { cat > /dev/null; tail; } < file)
스테판 Chazelas가

4
@StephaneChazelas * nix-이상한 가장자리 케이스의 세계가 정상화되고 있습니다. (찾을 수없는 입력과 검색 불가능한 입력은 확실히 유효한 지점입니다.)
CVn

69

tail자신이 어떻게 작동 하는지 볼 수 있습니다 . 내 파일 중 하나에 대해 read세 번 수행되며 총 약 10K 바이트를 읽습니다.

strace 2>&1  tail ./huge-file >/dev/null  | grep -e "read" -e "lseek" -e "open" -e "close"
open("./huge-file", O_RDONLY)           = 3
lseek(3, 0, SEEK_CUR)                   = 0
lseek(3, 0, SEEK_END)                   = 80552644
lseek(3, 80551936, SEEK_SET)            = 80551936
read(3, ""..., 708) = 708
lseek(3, 80543744, SEEK_SET)            = 80543744
read(3, ""..., 8192) = 8192
read(3, ""..., 708) = 708
close(3)                                = 0

이것이 어떻게 질문에 대답하는지 모르겠습니다. 여기서 무슨 일이 일어나고 있는지 설명해 주시겠습니까?
아이언 사무엘 맥린 장로

10
stracetail실행될 때 시스템 호출이 수행하는 작업을 보여줍니다 . 시스템 호출에 대한 소개는 en.wikipedia.org/wiki/System_call에서 읽을 수 있습니다 . 간단히-열기-파일을 열고 핸들 (이 예에서는 3), lseek읽을 위치와 읽은 위치를 읽은 후 read읽은 바이트 수를 반환합니다.
Sergei Kurenkov

2
따라서 시스템 호출을 분석하면 때때로 프로그램 작동 방식을 이해할 수 있습니다.
세르게이 쿠렌 코프

26

파일이 디스크에 흩어져있을 수 있기 때문에 [파일을 순차적으로 읽어야한다] 고 생각하지만 그러한 내부 구조를 잘 이해하지 못합니다.

아시다시피, tail파일의 끝 부분 (시스템 호출 lseek)을 찾고 뒤로 작동합니다. 그러나 위에서 인용 한 말에서 "꼬리가 파일의 끝을 찾기 위해 디스크의 어디에 있는지 어떻게 알 수 있습니까?"

대답은 간단하다 : 꼬리는 모른다. 사용자 수준 프로세스는 파일을 연속 스트림으로 인식하므로 tail파일 시작의 오프셋을 알 수 있습니다. 그러나 파일 시스템에서 파일의 "inode"(디렉토리 항목)는 파일 데이터 블록의 물리적 위치를 나타내는 숫자 목록과 연관됩니다. 파일을 읽을 때 커널 / 장치 드라이버는 필요한 부분을 파악하고 디스크상의 위치를 ​​파악하여 가져옵니다.

그것은 우리가 운영 체제를 가지고있는 종류입니다. 따라서 파일 블록이 어디에 흩어져 있는지 걱정할 필요가 없습니다.


2

head또는 전체 파일을 읽는 tail 것으로 보이면 파일에 줄 바꿈 문자가 거의 없거나 전혀 없기 때문일 수 있습니다 . 몇 달 전에 문자열이 아닌 공백이 없어도 직렬화 된 매우 큰 (기가 바이트) JSON 블롭 으로이 문제를 해결했습니다.

GNU head / tail이 있다면 line 대신 -c N첫 번째 / 마지막 N 바이트 를 인쇄하는 데 사용할 수 있지만 불행히도 이것은 POSIX 기능이 아닙니다.


1

당신은에서 볼 수 있듯이 소스 코드 라인 (525), 당신은 구현에 대한 설명을 볼 수 있습니다.

 /* Print the last N_LINES lines from the end of file FD.
   Go backward through the file, reading 'BUFSIZ' bytes at a time (except
   probably the first), until we hit the start of the file or have
   read NUMBER newlines.
   START_POS is the starting position of the read pointer for the file
   associated with FD (may be nonzero).
   END_POS is the file offset of EOF (one larger than offset of last byte).
   Return true if successful.  */
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.