Có được khóa đọc / ghi độc quyền trên một tệp để cập nhật nguyên tử


9

Tôi muốn có một tập tin được sử dụng như một bộ đếm. Người dùng A sẽ viết và tăng số này, trong khi Người dùng B yêu cầu đọc tệp. Có phải người dùng A có thể khóa tệp này để không ai có thể đọc hoặc ghi vào tệp đó cho đến khi việc ghi của người dùng A kết thúc?

Tôi đã xem xét flocknhưng dường như không thể làm cho nó hoạt động như tôi mong đợi.

flock -x -w 5 /dev/shm/counter.txt echo "4" >  /dev/shm/counter.txt && sleep 5

Nếu có một cách thích hợp hơn để có được tập tin gia tăng giống như nguyên tử này thì cũng thật tuyệt khi nghe!

Mục tiêu của tôi là:

LOCK counter.txt; write to counter.txt;

đồng thời

Read counter.txt; realize it's locked so wait until that lock is finished.

1
"dường như không thể làm cho nó hoạt động như tôi mong đợi." Có gì đặc biệt đó có nghĩa là?
John1024

Tôi chắc chắn rằng tôi đang sử dụng nó không chính xác, nhưng trong khi sử dụng mã ở trên, tôi có thể sử dụng hai shell và cả hai đều chỉnh sửa tệp truy cập trong khi tôi nghĩ rằng một khóa đang khóa nó. Vì vậy, nếu tôi chạy dòng đó hai lần trên hai shell riêng biệt, (mỗi cái có số riêng để lặp lại), tôi vẫn thấy số thứ hai được viết
d -_- b

1
Khi cái đầu tiên hoàn thành và giải phóng khóa của nó, cái thứ hai chạy. Đó không phải là cách nó nên hoạt động sao? (Trong đoạn mã trên, && sleep 5được thực thi sau khi đàn nhả khóa.)
John1024

Hmm xen kẽ ... Vì vậy, trong trường hợp đó, nó sẽ quá nhanh để mắt người tôi có thể bắt được. Tuyệt quá! Thử thách tiếp theo của tôi là làm thế nào để đưa nhiều lệnh vào flock, nhưng tôi sẽ đặt nó như một câu hỏi riêng biệt. Cảm ơn John!
d -_- b

3
@d -_- b Tôi thích tên người dùng của bạn. Đó là tên người dùng thông minh nhất mà tôi từng thấy.
Devyn Collier Johnson

Câu trả lời:


10

Việc xử lý lệnh của Bash dưới đây có thể gây ngạc nhiên:

flock -x -w 5 /dev/shm/counter.txt echo "4" >  /dev/shm/counter.txt && sleep 5

Bash đầu tiên chạy flock -x -w 5 /dev/shm/counter.txt echo "4" > /dev/shm/counter.txtvà, nếu điều đó hoàn thành thành công (giải phóng khóa), thì nó sẽ chạy sleep 5. Do đó, khóa không được giữ trong 5 giây mà người ta có thể mong đợi.

Bên cạnh &so với&&

Nếu một có hai lệnh, AB, sau đó:

  1. A & Bbắt đầu Atrong nền và sau đó bắt đầu Bmà không cần chờ đợi Ađể kết thúc.

  2. A && Bbắt đầu A, đợi cho nó hoàn thành, và sau đó, nếu nó hoàn thành thành công (mã thoát 0), bắt đầu B. Nếu Athất bại (mã thoát không khác), thì Bkhông bao giờ được chạy.

Tóm lại, &&&là hai toán tử danh sách hoàn toàn khác nhau.


3
nó sẽ làm tôi ngạc nhiên nếu trong A && B, Asẽ chờ đợi Bđể kết thúc.
Andras Gyomrey

1
trong A && B, A được thực thi trước. B chỉ được thực hiện nếu A thực hiện và thoát thành công. Sử dụng một; B luôn luôn thực thi B bất kể trạng thái thực thi của A.
kapad

15

Khóa tệp không bắt buộc 1 - tức là, bạn không thể khóa tệp để quá trình khác không thể truy cập được. Khóa một tập tin có nghĩa là nếu một quá trình (nother) kiểm tra xem nó đã bị khóa hay chưa, nó sẽ biết.

Mục đích của flocklà để làm những thứ như những gì bạn muốn, nhưng sau đó bạn phải sử dụng flockcho mỗi lần truy cập cố gắng . Hãy nhớ rằng đó là những cuộc gọi chặn; từ man flock:

nếu không thể lấy được khóa ngay lập tức, đàn sẽ đợi cho đến khi khóa có sẵn


1. Điều này làm cho tính năng này dường như vô dụng nếu bạn đang sử dụng nó, ví dụ như bảo mật, nhưng đó không phải là mục đích của khóa tệp - chúng là để đồng bộ hóa, đó là những gì bạn đang làm. Người dùng Leo chỉ ra rằng có thể có một triển khai khóa tệp bắt buộc không được chuẩn hóa trong nhân linux ( xem phần thảo luận này ), dựa trên sự tương đồng lịch sử từ các hệ điều hành * nix khác. Tuy nhiên, đây chỉ là giao diện cấp C.


Cảm ơn! Điều này giúp hiểu ý nghĩa của khía cạnh 'tư vấn' và cách tôi cần sử dụng flockmỗi lần. rất hữu ích
d -_- b

2

Bạn có thể sử dụng "lệnh sh -c ..." để chạy toàn bộ lệnh shell, bao gồm cả chuyển hướng tập tin, với khóa được giữ. Ngoài ra, vì bạn đang sử dụng tệp làm bộ đếm, bạn cần giữ khóa liên tục trong khi bạn đọc và ghi lại. Vì vậy, bạn sẽ muốn làm một cái gì đó như thế này để tăng bộ đếm và trả về giá trị mới của nó:

flock --exclusive --wait 5 /dev/shm/counter.txt sh -c 'read count < /dev/shm/counter.txt ; echo $((count + 1)) > /dev/shm/counter.txt ; echo $((count + 1))'

Thay đổi dấu cộng thành dấu trừ sẽ làm giảm bộ đếm:

flock --exclusive --wait 5 /dev/shm/counter.txt sh -c 'read count < /dev/shm/counter.txt ; echo $((count - 1)) > /dev/shm/counter.txt ; echo $((count - 1))'

Tôi hy vọng bạn sẽ khởi tạo bộ đếm trước khi bất kỳ sự tranh chấp nào có thể xảy ra, vì vậy không cần phải lo lắng về việc khóa sớm:

echo 0 > /dev/shm/counter.txt

Tôi không nghĩ bạn sẽ cần phải ghi lại giá trị truy cập trong khi tranh chấp có thể xảy ra, nhưng, nếu bạn đã từng làm như vậy, bạn nên làm như vậy:

flock --exclusive --wait 5 /dev/shm/counter.txt sh -c 'echo 0 > /dev/shm/counter.txt'

Tôi nghĩ bạn hiểu làm thế nào để đọc, nhưng tôi bao gồm nó cho đầy đủ:

flock --shared /dev/shm/counter.txt cat /dev/shm/counter.txt

Đây dường như là câu trả lời duy nhất thông báo chính xác rằng trong câu hỏi, tệp được mở bằng vỏ trước khi đàn thậm chí chạy ...
eichin
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.