나는 이것이 중단 없이 페어링을 제공할 것이라고 생각했지만 begin-end
그렇지 않습니다.
#!/bin/bash
fun()(
flock 1 || { echo >&2 "$BASHPID: FAIL: $?"; exit 1; }
echo "$BASHPID begin"
sleep 1;
echo "$BASHPID end"
)
fun &
fun &
fun &
fun &
fun &
fun &
fun &
fun &
fun &
wait
내가 뭘 잘못했나요?
답변1
이 접근 방식은 다음과 같이 작동합니다.
fun()(
(flock 9 || { echo >&2 "$BASHPID: FAIL: $?"; exit 1; }
echo "$BASHPID begin"
sleep 1;
echo "$BASHPID end"
) 9>test
)
이렇게 하면 보호해야 하는 명령이 완료되지 않는 한 잠긴 파일이 닫히지 않습니다. (물론 test
더 적합한 것으로 교체해야 합니다 .예를 들어사용 mktemp
. )
답변2
실패의 이유는 다음과 같습니다.man 2 flock
:
Flock()에 의해 생성된 잠금은 열린 파일 설명과 연결됩니다(open(2) 참조). 이는 중복된 파일 설명자(예를 들어, fork(2) 또는 dup(2)에 의해 생성됨)가 동일한 잠금을 참조하고 이러한 설명자 중 하나를 사용하여 잠금을 수정하거나 해제할 수 있음을 의미합니다.
이는 모든 프로세스가 동일한 파일 설명자를 상속하므로 프로세스 중 하나가 잠금을 수행하면 모두 파일 설명자를 공유한다는 의미입니다. 동일한 파일 설명자를 두 번 잠그는 것은 아무 일도 하지 않습니다.
나의 일반적인 해결책은 스크립트 자체를 잠그는 것입니다(그러나 동시에 스크립트를 여러 번 실행하면 문제가 발생합니다).
#!/bin/bash
fun()(
exec 3<"$0"
flock 3 || { echo >&2 "$BASHPID: FAIL: $?"; exit 1; }
echo "$BASHPID begin"
sleep 1;
echo "$BASHPID end"
)
fun &
fun &
fun &
fun &
fun &
fun &
fun &
fun &
fun &
wait
답변3
제가 생각하는 핵심은 다음과 같습니다.
file descriptor
1 예약되어stdout
사용됩니다. stdin/out/err이 아닌 9와 같은 다른 것을 사용해야 합니다.명 1 그룹예시가 표시됩니다.flock with file descriptor
잠긴 파일은 아래와 같이 지정된 파일 설명자 번호를 사용하여 열어야 합니다.명 1 그룹예는 다음과 같습니다:( flock -n 9 || exit 1 # ... commands executed under lock ... ) 9>/var/lock/mylockfile
답은 @Stephen Kitt의 것이었습니다.