Tạo tệp khác có nhiều rắc rối hơn bất kỳ thứ gì. Tạo một thư mục thay thế và kiểm tra kết quả của quá trình tạo. Sổ tay Unix chỉ ra rằng chỉ có một nhiệm vụ có thể thành công trong việc tạo một thư mục, thư mục kia sẽ bị lỗi nếu thư mục đã tồn tại, bao gồm cả trường hợp 2 tác vụ đã thử nó cùng một lúc. Bản thân hệ điều hành xử lý vấn đề, do đó bạn không phải làm như vậy.
Nếu không phải vì khóa cũ, đó là tất cả những gì bạn phải làm. Tuy nhiên, mọi thứ xảy ra, các chương trình bị hủy bỏ và không phải lúc nào cũng loại bỏ khóa của họ. Vì vậy, việc triển khai có thể phức tạp hơn một chút.
Trong tập lệnh, tôi thường sử dụng mã bên dưới. Nó tự động xử lý khóa cũ. Bạn có thể thực hiện như nhau trong C. trang Kiểm tra người đàn ông:
man -s 2 mkdir
EXECUTION_CONTROL_FILE: là một PATH tên và tên Dir, một cái gì đó giống như/usr/tmp/myAppName
second_of_now: trả lại thời gian hiện tại trong vài giây (bao gồm dưới đây)
LOCK_MAX_TIME: là bao lâu chỉ trong vài giây một khóa có thể tồn tại trước khi nó được coi là cũ
ngủ 5: Người ta luôn cho rằng một khóa sẽ làm điều gì đó ngắn và ngọt ngào. Nếu không, có thể chu trình giấc ngủ của bạn sẽ lâu hơn.
LockFile() {
L_DIR=${EXECUTION_CONTROL_FILE}.lock
L_DIR2=${EXECUTION_CONTROL_FILE}.lock2
(
L_STATUS=1
L_FILE_COUNT=2
L_COUNT=10
while [ $L_STATUS != 0 ]; do
mkdir $L_DIR 2>/dev/null
L_STATUS=$?
if [ $L_STATUS = 0 ]; then
# Create the timetime stamp file
second_of_now >$L_DIR/timestamp
else
# The directory exists, check how long it has been there
L_NOW=`second_of_now`
L_THEN=`cat $L_DIR/timestamp 2>/dev/null`
# The file does not exist, how many times did this happen?
if [ "$L_THEN" = "" ]; then
if [ $L_FILE_COUNT != 0 ]; then
L_THEN=$L_NOW
L_FILE_COUNT=`expr $L_FILE_COUNT - 1`
else
L_THEN=0
fi
fi
if [ `expr $L_NOW - $L_THEN` -gt $LOCK_MAX_TIME ]; then
# We will try 10 times to unlock, but the 10th time
# we will force the unlock.
UnlockFile $L_COUNT
L_COUNT=`expr $L_COUNT - 1`
else
L_COUNT=10 # Reset this back in case it has gone down
sleep 5
fi
fi
done
)
L_STATUS=$?
return $L_STATUS
}
####
#### Remove access lock
####
UnlockFile() {
U_DIR=${EXECUTION_CONTROL_FILE}.lock
U_DIR2=${EXECUTION_CONTROL_FILE}.lock2
(
# This 'cd' fixes an issue with UNIX which sometimes report this error:
# rm: cannot determine if this is an ancestor of the current working directory
cd `dirname "${EXECUTION_CONTROL_FILE}"`
mkdir $U_DIR2 2>/dev/null
U_STATUS=$?
if [ $U_STATUS != 0 ]; then
if [ "$1" != "0" ]; then
return
fi
fi
trap "rm -rf $U_DIR2" 0
# The directory exists, check how long it has been there
# in case it has just been added again
U_NOW=`second_of_now`
U_THEN=`cat $U_DIR/timestamp 2>/dev/null`
# The file does not exist then we assume it is obsolete
if [ "$U_THEN" = "" ]; then
U_THEN=0
fi
if [ `expr $U_NOW - $U_THEN` -gt $LOCK_MAX_TIME -o "$1" = "mine" ]; then
# Remove lock directory as it is still too old
rm -rf $U_DIR
fi
# Remove this short lock directory
rm -rf $U_DIR2
)
U_STATUS=$?
return $U_STATUS
}
####
second_of_now() {
second_of_day `date "+%y%m%d%H%M%S"`
}
####
#### Return which second of the date/time this is. The parameters must
#### be in the form "yymmddHHMMSS", no centuries for the year and
#### years before 2000 are not supported.
second_of_day() {
year=`printf "$1\n"|cut -c1-2`
year=`expr $year + 0`
month=`printf "$1\n"|cut -c3-4`
day=`printf "$1\n"|cut -c5-6`
day=`expr $day - 1`
hour=`printf "$1\n"|cut -c7-8`
min=`printf "$1\n"|cut -c9-10`
sec=`printf "$1\n"|cut -c11-12`
sec=`expr $min \* 60 + $sec`
sec=`expr $hour \* 3600 + $sec`
sec=`expr $day \* 86400 + $sec`
if [ `expr 20$year % 4` = 0 ]; then
bisex=29
else
bisex=28
fi
mm=1
while [ $mm -lt $month ]; do
case $mm in
4|6|9|11) days=30 ;;
2) days=$bisex ;;
*) days=31 ;;
esac
sec=`expr $days \* 86400 + $sec`
mm=`expr $mm + 1`
done
year=`expr $year + 2000`
while [ $year -gt 2000 ]; do
year=`expr $year - 1`
if [ `expr $year % 4` = 0 ]; then
sec=`expr 31622400 + $sec`
else
sec=`expr 31536000 + $sec`
fi
done
printf "$sec\n"
}
Sử dụng như thế này:
# Make sure that 2 operations don't happen at the same time
LockFile
# Make sure we get rid of our lock if we exit unexpectedly
trap "UnlockFile mine" 0
.
. Do what you have to do
.
# We need to remove the lock
UnlockFile mine
Rất tốt câu hỏi . Tôi không thể nghĩ ra bất kỳ hoàn cảnh nào mà điều này sẽ xảy ra, trừ khi hai quy trình cạnh tranh đều chọn cùng một tên tệp duy nhất cùng một lúc (điều này rõ ràng là xấu). Có thể là một giải pháp cho các lỗi NFS rất cũ? – Celada
Bạn có cần tạo các tệp khóa trên NFS không?AFAIK bạn sẽ có thể sử dụng 'flock()' hoặc 'lockf()' trong hầu hết các trường hợp. – Hasturkun