Thực hiện các thao tác ghi nguyên tử trong một tệp trong bash


13

Sau khi xem qua tài liệu bash , câu hỏi này và câu hỏi này vẫn chưa rõ cho tôi làm thế nào tôi có thể thực hiện các thao tác ghi nguyên tử (nối thêm) vào một tệp trong bash. Tôi có một tập lệnh được chạy trong nhiều trường hợp và tại một số điểm phải ghi dữ liệu vào một tệp:

echo "$RESULT" >> `pwd`/$TEMP_DIR/$OUT_FILE

Làm thế nào có thể thực hiện tất cả các hoạt động ghi từ tất cả các tập lệnh đang chạy đồng thời sang tập tin nguyên tử đó (để dữ liệu từ một phiên bản không trùng lặp dữ liệu từ một tập tin khác)?


1
FYI bạn không cần `pwd`; bạn chỉ có thể sử dụng một dấu chấm ( .). Ngoài ra, bạn nên trích dẫn toàn bộ tên tập tin vì nó bao gồm các biến .
tự đại diện

1
Bạn cũng có thể muốn xem xét khả năng sử dụng FIFO .
Wildcard

@Wildcard Cảm ơn. Tôi đã sử dụng pwdtrước đó trong kịch bản để thông báo cho người dùng về thư mục làm việc hiện tại và cũng viết các mục trong một tệp nhật ký. nhìn qua các bộ phận hiện tại.
Sebi

1
Trên thực tế, có một giới thiệu tốt hơn về FIFO ngay trên trang web này; liên kết tôi đã cung cấp vài phút trước là thông số kỹ thuật POSIX mkfifovà không chính xác ở mức giới thiệu.
tự đại diện

Cho dù đó là một tập tin hay một tập tin, bạn vẫn có nguy cơ hai trường hợp viết cùng một lúc và cắt xén các kết quả đầu ra của nhau.
clacke

Câu trả lời:


10

Có vẻ như bạn cần sử dụng flocknhư trong ví dụ từ người đàn ông ( http://linux.die.net/man/1/flock )

(
flock -x 200

# Put here your commands that must do some writes atomically

) 200>/var/lock/mylockfile 

Và đặt tất cả các lệnh của bạn phải là nguyên tử trong ().


Thao tác ghi sẽ là nguyên tử mặc dù (flock -s 200 # Đặt ở đây các lệnh của bạn phải thực hiện một số ghi nguyên tử) 200> / var / lock / mylockfile được đọc trên nhiều tập lệnh đang chạy đồng thời? Hoặc, ngược lại, khóa chỉ liên quan đến / var / lock / mylockfile?
Sebi

1
Tập lệnh của bạn khóa / var / lock / mylockfile, nhưng chỉ một phiên bản tập lệnh của bạn có thể có được khóa ghi trên nó. Các trường hợp khác sẽ đợi cho đến khi /var/lock/mylockfilecó sẵn để khóa.
Serge Kurenkov

-s là một khóa chia sẻ - phù hợp để đọc, đối với khóa ghi bạn phải sử dụng -x / -e. Đó là trong trang người đàn ông bạn liên kết.
Evan Benn

Tại thời điểm nào việc mở khóa xảy ra trong mã này? Ngay khi một cái gì đó được viết cho /var/lock/mylockfilequá trình được gọi là flock -x?
Chris Stryczynski

@ChrisStryczynski Bạn có thể chạy ví dụ này (flock -x 200; date; sleep 10; date;) 200>/var/lock/mylockfiletrong hai shell và thấy rằng việc mở khóa chỉ xảy ra sau khi tất cả các lệnh trong () được thực thi (đó là trong một
nhánh con

4

flocklà một trong những cách của hoạt động lồng vào nhau. Tiện ích này là một phần của bộ công cụ linux-linux và chỉ có sẵn cho Linux. Các tiện ích khác, có sẵn trên một loạt các nền tảng, dựa trên setlocktiện ích của Daniel J. Bernstein từ gói daemontools của anh ấy:

  • setlock từ daemontools
  • setlock từ daemontools-encore của Bruce Guenter
  • s6-setlock từ s6 của Laurent Bercot
  • chpst từ runit của Gerrit Pape
  • runlock từ perp của Wayne Marshall
  • setlock từ bộ công cụ nosh của tôi

Các công cụ này hoạt động với một mô hình hơi khác với mô hình được sử dụng trong câu trả lời của M. Kurenkov (một công cụ flockcũng có thể sử dụng, nhưng không có trong câu trả lời đó). Người ta gọi setlockchương trình để tải chuỗi cho lệnh phải được lồng vào nhau. setlockchính nó mở và khóa tệp khóa và để lại một bộ mô tả tệp cho nó mở trong quy trình của nó. Khóa vẫn tồn tại miễn là quá trình đó thực hiện (trừ khi lệnh tiếp theo được xâu chuỗi để giải phóng khóa một cách rõ ràng bằng cách tìm và đóng bộ mô tả tệp đang mở).

Đối với trường hợp trong câu hỏi, người ta phải lồng vào lệnh tạo ra dòng đầu ra, lưu ý rằng điều này gọi một bên ngoài echo thay cho echolệnh tích hợp shell :

setlock mylockfile echo "$ RESULT" >> ./$TEMP_DIR/$OUT_FILE

Trong trường hợp này, không cần thiết phải khóa liên động mở tệp đầu ra ở chế độ chắp thêm. Nếu đúng như vậy, người ta sẽ phải mở tệp đó trong khóa, điều này bắt buộc phải sử dụng các chương trình như fdredir/ redirfd:

setlock mylockfile fdredir --append 1 "./$TEMP_DIR/$OUT_FILE" echo "$ RESULT"
cái nào có thể biến thành hàm shell nếu muốn:

outfile () {setlock mylockfile fdredir --append 1 "./$TEMP_DIR/$OUT_FILE" "$ @"; } 
[
Vách ] outfile echo "$ RESULT"
hoặc bám theo cú pháp shell và để nó được giải thích bởi shell thứ hai chạy dưới khóa liên động, yêu cầu một số trích dẫn không tầm thường nếu các biến shell của một người không được xuất dưới dạng biến môi trường:

setlock mylockfile sh -c 'echo' "$ RESULT" '>> "./'$TEMP_DIR'/'$OUT_FILE'" '

Điều này tất nhiên khái quát cho những thứ khác ngoài việc ghi vào các tệp đầu ra:

setlock mylockfile sh -c 'lồng vào nhau; đồ đạc …'

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.