리눅스에서 ">>"를 사용할 때 bash는 O_APPEND에서 파일을 열습니까?


38

우리가 사용 echo 1234 >> some-file한다면 Documentation은 출력이 추가되었다고 말합니다.

내 생각에 일부 파일이 존재하지 않으면 O_CREAT가 새 파일을 만듭니다. 사용 된 경우 >O_TRUNC는 기존 파일을 자릅니다.

다음과 같은 경우 >>: 파일을 O_WRONLY (또는 O_RDWR)로 열고 O_APPEND를 시뮬레이션하여 종료 및 쓰기 작업을 수행하려고합니까? 아니면 파일이 O_APPEND로 열리면서 추가되도록 커널에 남겨 둘 것입니까?

conserver 프로세스가 echo에 의해 삽입 된 일부 마커를 덮어 쓰기 때문에 출력 파일이 NFS 마운트 포인트에서 왔을 때 NFS 문서에서 O_APPEND가 서버에서 지원되지 않으므로 클라이언트 커널이 처리해야하기 때문에 이것을 묻습니다. conserver 프로세스가 O_APPEND를 사용하고 있지만 >>리눅스에서 bash 를 확신하지 못 하므로 여기에 질문을합니다.


12
NFS의 문제 O_APPEND는 지원되지 않습니다. 문제는 에뮬레이트된다는 것입니다. 로컬 파일 시스템에서 열린 동일한 파일에 쓰는 여러 프로세스 O_APPEND 는 서로의 데이터를 덮어 쓰지 않습니다. NFS에서는 O_APPEND쓰기 전에 끝까지 검색하여 에뮬레이션되므로 경쟁 조건이 발생할 수 있습니다. NFS에서는이 문제를 해결할 방법이 없습니다. 각 병렬 작성기는 자체 파일을 작성해야합니다. 이 문제를 해결하는 유일한 방법은 NFS 서버에서 서버 프로세스를 설정하고 로거가로 그인하도록 |nc server port하고 서버가 들어오는 데이터를 로그에 추가하도록하는 것입니다.
Guntram Blohm은 Monica

@GuntramBlohm, +1, 확인 주셔서 감사합니다. 기본적으로 파일에 하나의 기록기 프로세스 만 사용하고 다른 모든 기록기 프로세스는이 과정을 거칩니다.
Prem

좋은 답변이 너무 많아서 어떤 대답을 받아 들여야하는지 잘 모르겠습니다. 첫 Bruce Ediger는 O_APPEND가 사용되었음을 보여주었습니다. 다음 Random832는 이것이 표준에 주어진다는 것을 보여주었습니다. 마지막으로 Eric Renouf는 동일한 답변으로 소스 코드를 보여주었습니다. 세 가지 관점 모두 최종 완성도에 추가됩니다.
Prem

6
간단히 말해서 NFS는 많은 버그이므로 사용해서는 안됩니다.
R ..

2
예, 그러나 우리는 O_EXCL이 발명되었을 때 이미 그런 식으로 배웠습니다.
케빈

답변:


60

나는 이것을 실행했다 : strace -o spork.out bash -c "echo 1234 >> some-file"당신의 질문을 알아 내기 위해. 이것이 내가 찾은 것입니다.

open("some-file", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3

echo명령을 실행 한 디렉토리에 "some-file"이라는 파일이 없습니다 .


50

이것은 Bash에서만 수행되는 것이 아니라 표준에 의해 요구됩니다.

단일 유닉스 사양에서 :

추가 된 출력 재 지정은 지정된 파일 디스크립터에서 출력을 위해 단어의 확장으로 인해 이름이 지정된 파일이 열리도록해야합니다. POSIX.1-2008의 시스템 인터페이스 볼륨에 정의 된 open () 함수가 O_APPEND 플래그로 호출 된 것처럼 파일이 열립니다 . 파일이 존재하지 않으면 파일을 작성해야합니다.

따라서 모든 POSIX 호환 쉘이이를 수행해야합니다. 일부 Unix 시스템에서는 /bin/shPOSIX 이외의 Bourne 쉘 (본래 Bourne 쉘은 원래 O_APPEND발명 되기 전에 작성 됨 ) 일 수 있으며 사용 가능한 POSIX 쉘은 일반적 으로 Solaris와 같은 다른 경로 위치에서 ksh사용할 수 있습니다 .sh/usr/xpg4/bin


2
흥미롭게도이를 수행하지 않는 쉘은 Bourne 쉘입니다. Bourne 쉘은 O_TRUNC 및 lseek ()없이 끝까지 열립니다. O_APPEND 플래그가 추가되기 전에 작성 되었기 때문 open()입니다. >>그 자체는 이전의 Thomson 쉘에 의해 소개되었습니다.
Stéphane Chazelas

1
@ StéphaneChazelas 또한 다양한 버전의 C 셸 소스를 조회했으며 4.3BSD-Reno까지 O_APPEND 플래그가 도입되지 않았습니다.
Random832

그것은 "있는 것처럼"이라고 말해서 다르게 구현할 수 없었습니다 (그러나 동일한 관찰 가능한 효과를 생성 함)? 표준이처럼은 보이지 않는다 필요 "처럼"동작하는지 뭔가를 O_APPEND의 사용을.
토마스

1
@Thomas 그것은 당신이 O_APPEND에 대해 문서화 된 모든 행동을 얻을 것이라는 것을 의미합니다. 이것은 모든 쓰기가 끝날 때 재배치하는 것을 의미합니다. "as as"는 표준이 아닌 언어로, 예를 들어 비 전통적인 Unix 플랫폼에서 실제로 open () 함수를 호출하는 것 이외의 다른 방법으로 열 수 있도록하기위한 것입니다.
Random832

이 동작이 표준에 있음을 보여주기 위해 +1.
Prem

32

소스를 보면 O_APPEND를 사용합니다. 710-713 make_cmd.c행의 bash 4.3.30의 경우 다음을 읽으십시오.

case r_appending_to:                /* >>foo */
case r_append_err_and_out:          /* &>> filename */
  temp->flags = O_APPEND | O_WRONLY | O_CREAT;
  break;

+1, 소스 코드 관점에서 답변을 표시합니다.
Prem

19

strace로컬 (NFS가 아닌) 파일 시스템에서 사용 하는 것을 조사해 보겠습니다 .

$ strace -eopen -- bash -c "echo foo >> /tmp/testfile000" 2>&1 | grep /tmp/testfile000
open("/tmp/testfile000", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3

$ strace -eopen -- bash -c "echo foo > /tmp/testfile000" 2>&1 | grep /tmp/testfile000
open("/tmp/testfile000", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3

다른 조개, 즉 dash, dash, sh비지 박스의 '와 mksh같은 방식으로 작동합니다.

이 옵션 -e open은 시스템 호출 -e trace=open만 추적 하는 것을 의미 합니다 open().

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.