빈 디렉토리에서 시작합니다.
$ touch aFile
$ ls
aFile
그런 다음 ls
두 가지 주장 중 하나는이 디렉토리에 없습니다. 두 출력 스트림을 모두라는 파일로 리디렉션합니다 output
. 나는 >>
동시에 쓰는 것을 피하기 위해 사용 합니다.
$ ls aFile not_exist >>output 2>>output
$ cat output
ls: cannot access 'not_exist': No such file or directory
aFile
작동하는 것 같습니다. 이 접근 방식에 위험이 있습니까?
답변
아니요, 표준만큼 안전하지는 않습니다 >>bar 2>&1
.
글을 쓸 때
foo >>bar 2>>bar
을 사용하여 bar
파일을 두 번 열어 각각 O_APPEND
독립적 인 상태 (포인터, 열린 모드 등)를 가진 두 개의 완전히 독립적 인 파일 객체 [1]를 만듭니다.
이것은 시스템 호출을 2>&1
호출하는 것과 매우 다르며 dup(2)
stderr 및 stdout을 동일한 파일 객체에 대해 상호 교환 가능한 별명으로 만듭니다.
이제 문제가 있습니다.
O_APPEND
둘 이상의 프로세스가 한 번에 파일에 데이터를 추가하는 경우 NFS 파일 시스템에서 파일이 손상 될 수 있습니다. NFS는 파일 추가를 지원하지 않기 때문에 클라이언트 커널이 파일을 시뮬레이션해야하므로 경쟁 조건 없이는 수행 할 수 없습니다.
당신은 일반적으로 같은 파일의 확률에 의지 할 수 bar
있는 foo >>bar 2>&1
매우 낮은 것으로 두 개의 별도의 장소에서 같은 시간에 기록된다. 그러나 >>bar 2>>bar
당신은 아무 이유없이 그것을 수십 배나 늘 렸습니다.
[1] POSIX lingo의 “파일 설명 열기”
답변
당신이 할 때 어떻게됩니까
some_command >>file 2>>file
즉 file
두 번 추가를 위해 열립니다. 이것은 POSIX 파일 시스템에서 수행하는 것이 안전합니다. 추가를 위해 파일을 열 때 파일에 발생하는 모든 쓰기는 데이터가 표준 출력 스트림 또는 표준 오류 스트림을 통해 전달되는지 여부에 관계없이 파일 끝에서 발생합니다.
이것은 기본 파일 시스템에서 원자 추가 쓰기 작업에 대한 지원에 의존합니다. NFS와 같은 일부 파일 시스템은 원자 추가를 지원하지 않습니다. 예를 들어 StackOverflow에서 “UNIX에서 파일을 추가합니까?” 라는 질문을 참조하십시오 .
사용
some_command >>file 2>&1
그래도 NFS에서도 작동합니다.
그러나
some_command >file 2>file
셸이 출력 파일을 잘라 내고 (두 번) 스트림에서 발생하는 모든 쓰기 는 다른 스트림에서 이미 쓴 데이터 를 덮어 씁니다 .
예:
$ { echo hello; echo abc >&2; } >file 2>file
$ cat file
abc
o
hello
문자열 (종단으로 바꿈) 먼저 기록되고, 다음 스트링 abc
개행 다음은 덮어, 표준 오차로 기록한다 hell
. 결과는 abc
줄 바꿈 이있는 문자열 이고, 첫 번째 echo
출력 의 왼쪽에 o
줄 바꿈이 있습니다.
그 줄이 마지막에 쓰여지고 줄 보다 길기 때문에 두 개의 echo
상처를 바꾸는 것은 hello
출력 파일 에서만 생성됩니다 abc
. 리디렉션이 발생하는 순서는 중요하지 않습니다.
더 관용적 인 것을 사용하는 것이 더 좋고 안전합니다.
some_command >file 2>&1
답변
그것은 당신이 달성하고자하는 것에 달려 있습니다. 출력과 같은 파일에 오류가 있는지 확인하는 것은 사용자의 몫입니다. 이것은 쉘의 기능으로 파일에 텍스트를 저장하여 원하는대로 리디렉션 할 수 있습니다. 절대적으로 예 또는 아니오는 없습니다. 리눅스의 모든 것이 여러 가지 방법으로 수행 될 수 있으므로 이것이 내 방법 ls notExistingFile existingFile >> output 2>&1
입니다. 리디렉션 자체 측면에서 완벽하게 안전합니다.