여러 개의 Bash 셸 스크립트를 병렬로 실행하고 싶습니다. 그러나 경쟁 조건을 피하고 싶습니다. 이 목적으로 사용할 수 있는 진정한 유닉스 명령은 무엇 이며 어떻게 사용할 수 있습니까?
여러 개의 Bash 셸 스크립트를 병렬로 실행하고 싶습니다. 그러나 경쟁 조건을 피하고 싶습니다. 이 목적으로 사용할 수 있는 진정한 유닉스 명령은 무엇 이며 어떻게 사용할 수 있습니까?
답변:
경우 lockfile
시스템에 설치되어 있지 않은 경우, mkdir
이 원자 조작, 그리고 디렉토리가 이미 (한 당신은 추가하지 않는 존재하는 경우는 실패 일을 할 것입니다 -p
명령 줄 스위치).
create_lock_or_wait () {
path="$1"
wait_time="${2:-10}"
while true; do
if mkdir "${path}.lock.d"; then
break;
fi
sleep $wait_time
done
}
remove_lock () {
path="$1"
rmdir "${path}.lock.d"
}
#!/bin/bash
# Makes sure we exit if flock fails.
set -e
(
# Wait for lock on /var/lock/.myscript.exclusivelock (fd 200) for 10 seconds
flock -x -w 10 200
# Do stuff
) 200>/var/lock/.myscript.exclusivelock
이렇게하면 "("과 ")"사이의 코드가 한 번에 하나의 프로세스 만 실행되고 프로세스가 잠금을 너무 오래 기다리게됩니다.
lockf(1)
.
lockf(1)
그러나이 예제에서 사용 된 방식으로는 작동하지 않습니다. 파일 디스크립터 번호를 인수로 사용할 수 없습니다.
lockfile (1)은 좋은 후보처럼 보이지만 procmail 패키지 의 일부이므로 아직 컴퓨터에 설치하지 않았을 수 있습니다. 아직 설치되지 않은 경우 시스템에 맞게 패키지화해야하는 인기있는 패키지입니다. 내가 확인한 4 개의 시스템 중 3 개에 설치되어 있고 다른 하나는 사용 가능합니다.
그것을 사용하는 것은 간단합니다 :
#!/bin/sh
LOCKFILE=$HOME/.myscript/lock
mkdir -p `dirname $LOCKFILE`
echo Waiting for lock $LOCKFILE...
if lockfile -1 -r15 $LOCKFILE
then
# Do protected stuff here
echo Doing protected stuff...
# Then, afterward, clean up so another instance of this script can run
rm -f $LOCKFILE
else
echo "Failed to acquire lock! lockfile(1) returned $?"
exit 1
fi
내가 제공 한 옵션은 최대 15 초 동안 1 초에 한 번 재 시도합니다. 영원히 기다리려면 "-r"플래그를 삭제하십시오.
시스템 호출 mkdir()
은 POSIX 파일 시스템에서 원자 적입니다. 따라서 mkdir
명령을 정확히 한 번만 호출 mkdir()
하여 목적을 달성 하는 방식으로 명령을 사용하십시오 . (IOW는 사용하지 마십시오 mkdir -p
). 해당 잠금 해제는 rmdir
물론입니다.
주의 사항 : mkdir()
네트워크 파일 시스템에서 원자가 아닐 수도 있습니다.
rmdir
원자 따라서도?
유닉스에서만 실행중인 경우 fifo를 사용하십시오. 작업 기록을 fifo에 기록하고이 파일에서 프로세스를 읽도록하면 독자가 fifo를 차단합니다.
잠금 파일은 정상이지만 설명에 대해서는 fifo를 사용합니다.
여기에 게시 된 " ? 쉘 스크립트에서 올바른 잠금은 "사용 FLOM (무료 잠금 관리자) 실행으로 도구를 직렬화 명령과 쉘 스크립트는 쉽게로된다
flom -- command_to_serialize
FLOM을 사용하면 여기에 설명 된대로보다 실용적인 사용 사례 (분산 잠금, 리더 / 라이터, 숫자 리소스 등)를 구현할 수 있습니다. http://sourceforge.net/p/flom/wiki/FLOM%20by%20examples/
make(1)
을 인수 할 수있는 방식으로 종속성을 표현할 수 없습니까 ? (즉,make -j 9
코어가 8 개인 경우)? 이것은 더 세분화 된 인터리빙 작업의 이점을 추가했습니다.