Tôi muốn chạy song song nhiều tập lệnh shell Bash. Tuy nhiên, tôi muốn tránh điều kiện chủng tộc. Những lệnh Unix nào thực sự là nguyên tử mà tôi có thể sử dụng cho mục đích này và làm cách nào tôi có thể sử dụng chúng?
Tôi muốn chạy song song nhiều tập lệnh shell Bash. Tuy nhiên, tôi muốn tránh điều kiện chủng tộc. Những lệnh Unix nào thực sự là nguyên tử mà tôi có thể sử dụng cho mục đích này và làm cách nào tôi có thể sử dụng chúng?
Câu trả lời:
Nếu lockfile
không được cài đặt trên hệ thống của bạn, thì nó mkdir
sẽ thực hiện công việc: đó là một hoạt động nguyên tử và sẽ thất bại nếu thư mục đã tồn tại (miễn là bạn không thêm -p
công tắc dòng lệnh).
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
Điều này đảm bảo rằng mã giữa "(" và ")" chỉ được chạy bởi một quy trình tại một thời điểm và quy trình đó sẽ chờ khóa quá lâu.
lockf(1)
.
lockf(1)
Mặc dù vậy, không hoạt động theo cách được sử dụng trong ví dụ này. Nó không thể lấy số mô tả tập tin làm đối số.
lockfile (1) trông giống như một ứng cử viên tốt, mặc dù vậy hãy cẩn thận rằng đó là một phần của gói procmail , mà bạn có thể chưa cài đặt trên máy của mình. Đây là một gói đủ phổ biến mà nó nên được đóng gói cho hệ thống của bạn nếu nó chưa được cài đặt. Ba trong số bốn hệ thống tôi đã kiểm tra có nó, và hệ thống còn lại có sẵn.
Sử dụng nó rất đơn giản:
#!/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
Các tùy chọn tôi đã đưa ra khiến nó thử lại một lần một giây trong tối đa 15 giây. Thả cờ "-r" nếu bạn muốn nó chờ mãi.
Cuộc gọi hệ thống mkdir()
là nguyên tử trên các hệ thống tập tin POSIX. Vì vậy, sử dụng mkdir
lệnh theo cách mà nó liên quan đến chính xác một cuộc gọi mkdir()
sẽ đạt được mục đích của bạn. (IOW, không sử dụng mkdir -p
). Việc mở khóa tương ứng là rmdir
tất nhiên.
Caveat emptor: mkdir()
có thể không phải là nguyên tử trên các hệ thống tập tin mạng.
rmdir
do đó cũng nguyên tử?
Có thể lệnh lockfile sẽ làm những gì bạn cần.
lockfile ~/.config/mylockfile.lock
.....
rm -f important.lock
Nếu bạn chỉ chạy trên Unix, hãy sử dụng fifos. Bạn có thể viết hồ sơ công việc lên fifo và có các quy trình đọc từ tệp này và độc giả của bạn sẽ chặn trên fifos.
Khóa tập tin là ok, nhưng với những gì bạn mô tả tôi sẽ đi với fifos
Như được đăng ở đây: " Khóa chính xác trong shell script? ", Sử dụng công cụ FLOM (Free LOck Manager) , việc tuần tự hóa các lệnh và shell script trở nên dễ dàng như khi chạy
flom -- command_to_serialize
FLOM cho phép bạn triển khai các trường hợp sử dụng nhẹ nhàng hơn (khóa phân tán, độc giả / nhà văn, tài nguyên số, v.v.) như được giải thích tại đây: http://sourceforge.net/p/flom/wiki/FLOM%20by%20examples/
make(1)
tiếp quản? (ví dụ, làm mộtmake -j 9
nếu bạn có 8 lõi)? Điều này có thêm lợi thế của công việc xen kẽ với độ chi tiết mịn hơn.