나에게 명령이 있다면
$ ./script >> file.log
두 번 호출되고 첫 번째 호출이 끝나기 전에 두 번째 호출이 발생하면 어떻게 되나요?
첫 번째 호출이 출력 파일에 대한 배타적 잠금을 획득합니까? 그렇다면 쓰기를 시도할 때 두 번째 스크립트가 실패합니까, 아니면 쉘이 출력을 수락하고(스크립트가 종료되도록 허용) 오류를 발생합니까?
아니면 로그 파일이 두 번 기록됩니까?
답변1
Unix 시스템은 일반적으로 강제 잠금을 피합니다. 어떤 경우에는 커널이 사용자 프로그램에 의한 수정을 방지하기 위해 파일을 잠그지만, 단순히 다른 프로그램에서 파일을 쓰는 경우에는 그렇지 않습니다. 어떤 UNIX 시스템도 프로그램이 파일에 쓰고 있기 때문에 파일을 잠그지 않습니다.
스크립트의 동시 인스턴스가 서로 방해하지 않도록 하려면 명시적인 잠금 메커니즘을 사용해야 합니다.flock
lockfile
.
추가하기 위해 파일을 열면(해당되는 경우 >>
) 모든 프로그램은 항상 파일 끝에 기록하는 것이 보장됩니다. 따라서 여러 인스턴스의 출력은 서로 덮어쓰지 않으며, 차례로 쓰는 경우 출력은 작성된 순서와 동일합니다.
일어날 수 있는 나쁜 일은 인스턴스 중 하나가 여러 출력 블록을 쓰고 함께 출력될 것으로 예상하는 경우입니다. 한 인스턴스의 연속 쓰기 사이에 다른 인스턴스가 자체 쓰기를 수행할 수 있습니다. 예를 들어, 인스턴스 1이 을 쓰고 foo
인스턴스 2가 을 쓰고 hello
인스턴스 2만 을 쓰면 bar
파일에 가 포함됩니다 foohellobar
.
프로세스가 시스템 호출을 호출하면 파일에 효과적으로 기록됩니다 write
. 프로그램에 대한 호출은 write
원자적입니다. 각 호출은 write
다른 프로그램에 의해 중단될 수 없는 일련의 바이트를 씁니다. 일반적으로 단일 호출로 효과적으로 쓸 수 있는 데이터 양에는 제한이 있습니다 write
. 더 큰 크기의 경우 데이터의 시작 부분만 기록되고 애플리케이션은 write
다시 호출해야 합니다. 또한 많은 프로그램이 수행됩니다.완충기: 메모리 영역에 데이터를 축적한 후 이 데이터를 블록에 씁니다. 일부 프로그램은 한 줄 또는 기타 의미 있는 분리를 완료한 후 출력 버퍼를 플러시합니다. 이러한 프로그램을 사용하면 너무 길지 않은 한(최대 몇 킬로바이트, 운영 체제에 따라 다름) 전체 라인이 중단되지 않을 것으로 예상할 수 있습니다. 프로그램이 의미 있는 위치에서 플러시되지 않고 버퍼 크기에 따라 플러시되는 경우 한 인스턴스에서는 4kB, 다른 인스턴스에서는 4kB, 첫 번째 인스턴스에서는 4kB 등이 표시될 수 있습니다.
답변2
추가를 의미하는 를 사용하고 있으므로 >>
각 인스턴스에 대한 모든 출력 줄은 발생 순서대로 추가됩니다.
스크립트 출력이 인쇄 1\n
되고 5\n
각 출력 사이에 1초의 지연이 있고 인스턴스 2가 2.5초 후에 시작되면 다음 결과를 얻게 됩니다.
1
2
1
3
2
4
3
5
4
5
따라서 귀하의 질문에 대답하자면: 아니요.