Các chuỗi bị xiềng xích nguyên tử?


8

Nếu có một quá trình liên tục ghi vào một tệp và tôi muốn kiểm soát tệp bằng root, tôi có thể làm một cái gì đó như thế này:

sudo rm somefile; sudo touch somefile

Có thể cho quá trình nối thêm vào tập tin giữa hai lệnh này? Nếu vậy, có cách nào để đảm bảo rằng không có lệnh nào khác được chạy ở giữa không?


4
Đây có thể là một vấn đề XY . Bạn có thể giải thích vấn đề tiềm ẩn mà bạn đang cố gắng giải quyết?
Nate Eldredge

1
@NateEldredge: Hoàn toàn không. Tôi có thể hủy bỏ lý do tại sao có vẻ như vậy dựa trên giả thuyết giả định của tôi. Thậm chí không có vấn đề. Chỉ tò mò thôi.
Darth Egregious

5
Quá trình này thực sự có thể sẽ tiếp tục ghi vào tệp đã xóa và thậm chí không cố mở tệp mới.
Random832

Giả định của tôi trong giả thuyết hóa ra hơi sai, nhưng tôi đoán bạn có thể thay đổi "nối" thành "mở" hoặc "chạm" và nó vẫn có ý nghĩa.
Darth Egregious

Câu trả lời:


12

Một dòng lệnh xích về cơ bản là một tập lệnh shell nhỏ; nó sẽ chạy lệnh đầu tiên bằng cách sử dụng thủ tục fork + exec thông thường, đợi cho nó thoát, sau đó chạy lệnh thứ hai theo cùng một cách. Giữa hai lệnh, có một số lượng thời gian tùy ý mà trình bao mất trong quá trình ghi sổ và xử lý, trong đó quá trình đa xử lý thông thường diễn ra và các quá trình khác có thể tùy ý làm những việc khác. Vì vậy, câu trả lời là không'. (Nếu bạn thực sự làm điều này, bạn sẽ thấy rằng mục nhập thư mục somefilebiến mất, nhưng bản thân tệp vẫn còn (vì nó được mở bởi một quy trình) cho đến khi nó đóng lại. , touchlệnh sẽ tạo một tệp mới, không liên quan với cùng tên và đường dẫn.)

Nếu bạn muốn thay đổi quyền sở hữu tệp thành root, chỉ cần thực hiện sudo chown root:root somefile(mặc dù tôi không chắc điều đó sẽ ảnh hưởng đến các quy trình với tệp mở như thế nào đối với tệp đó). Nếu bạn muốn hủy nội dung tệp hiện tại, hãy thử truncate -s 0 somefile(quá trình đang chạy sẽ tiếp tục nối vào tệp hiện trống). Nếu đó là một cái gì đó khác, có lẽ làm rõ những gì bạn muốn làm.


Cảm ơn Tom. Tôi không quan tâm lắm đến tình huống giả định của mình. Đã tự hỏi về việc làm một cái gì đó như thế này là có thể.
Darth Egregious

Về câu hỏi chung, tôi không nghĩ thực sự có cách nào để đảm bảo tính nguyên tử trong tập lệnh shell. Bạn có thể sử dụng các khóa và như vậy để đảm bảo rằng hai quy trình hợp tác không bước vào nhau và bạn có thể sử dụng các quyền để đảm bảo rằng một quy trình tùy ý không thể bước vào công việc của bạn. Nhưng ngăn không cho bất cứ thứ gì khác chạy sẽ gây rối nhiều với quá trình đa xử lý của kernel; Tôi không nghĩ mã ring-3 có thể làm điều đó cả.
Tom Hunt

Bạn có thể sử dụng khóa tệp bắt buộc nếu chúng được bật và khả dụng trên hệ thống tệp của bạn.
roaima

5
chowning somefile sẽ không ảnh hưởng đến các tiến trình có tệp xử lý tới somefile.
PSkocik

Ví dụ, bạn có thể làm exec 3>somefile; sudo chmod 0600 somefile; echo hello world >&3; sudo cat somefile; exec 3>&-.
PSkocik

6

Không. Một rmlệnh theo sau là một touchlệnh không phải là nguyên tử. Sẽ có một khoảng thời gian dài giữa hai lệnh - có thể trong phạm vi mili giây. Rất nhiều điều có thể xảy ra trong thời gian đó. Nếu bạn không may mắn, thông tin sudo của bạn thậm chí có thể hết hạn.

Một chương trình duy nhất gọi unlinkopengọi sẽ để lại một cửa sổ ngắn hơn nhiều cho một cuộc đua, nhưng nó vẫn có thể xảy ra.

Một cách tiếp cận an toàn hơn sẽ là tạo tệp mới với tên tạm thời và sử dụng lệnh renamegọi hệ thống. "Ghi đè" một tên với lệnh renamegọi hệ thống được đảm bảo là nguyên tử. Điều này có thể đạt được bằng cách sử dụng touchmv.

Nhưng một quá trình đã mở tệp cũ để ghi có thể tiếp tục ghi vào đó rất lâu sau khi nó bị xóa. Đây sẽ là trường hợp cho cả một tập tin bị xóa bằng cách sử dụng unlinkvà một tập tin bị xóa bằng cách sử dụng rename.


3

Khi một tiến trình mở tệp để đọc, bạn không cần phải làm gì với quyền sở hữu hoặc quyền: quá trình có thể tiếp tục truy cập tệp. Bạn thậm chí có thể xóa tệp và quá trình sẽ có thể tiếp tục truy cập tệp qua tệp thủ công.

Xem xét các quyền là một cổng kiểm soát để có được một tập tin.

Nếu bạn muốn tạo một tệp nguyên tử, thì thay vì làm điều này:

sudo rm somefile
sudo touch somefile

bạn có thể cân nhắc điều này:

sudo touch anotherfile
sudo perl -e "rename 'anotherfile', 'somefile'"

mà nguyên tử sẽ thay thế somefilebằng anotherfile. (Tôi muốn sử dụng hơn mv -fnhưng tôi không thể tìm thấy một tuyên bố đảm bảo cuộc gọi này gọi rename(2)hệ thống.


Có lẽ bạn có thể cập nhật Câu hỏi của mình để giải thích ý của bạn bằng cách "kiểm soát tệp". Bạn có thể có một vấn đề XY ở đây.


Sử dụng mv -fđể có được một rename(2)cuộc gọi hệ thống. Bạn không đúng ln, bởi vì nó luôn sử dụng lệnh link(2)gọi hệ thống, không thể thay thế nguyên tử. ln -fchỉ cần làm unlink(2)trên mục tiêu đầu tiên.
Peter Cordes

@PeterCordes ah vâng tất nhiên, cảm ơn bạn. Tôi đã có lntrên não. Tôi không chắc làm thế nào để được rename(2)đảm bảo tham gia và đã quá muộn để đi đào sâu hơn
roaima

POSIX đảm bảo rằng mv"sẽ thực hiện các hành động tương đương" rename(old, new). pubs.opengroup.org/onlinepub/9699919799/utilities/mv.html . mv -fhành động như mv -inếu đích không thể ghi, nhưng nó không giống cp -fhoặc ln -fnơi nó sẽ hủy liên kết trước.
Peter Cordes

2

Không nhưng

sudo rm somefile; sudo touch somefile

là an toàn trong hầu hết các tình huống.

Hầu hết các quy trình mở tệp và sau đó sử dụng bộ mô tả tệp thu được để truy cập nội dung tệp.

Nếu một quá trình mở một số tệp, trong sh:

 exec 3>somefile

Sau đó, một quy trình khác được tự do hủy liên kết (= remove) somefile và filedescriptor mà trên đó somefile được mở bởi quy trình đầu tiên (3 trong trường hợp này) sẽ tiếp tục đề cập đến nội dung ban đầu của somefile, hiện là một tệp trong limbo.

sudo touch somefile

sẽ tạo ra một số tệp mới, không liên quan và tất cả các quy trình đã mở một số tệp cũ và hiện chỉ sử dụng một bộ lọc dữ liệu để tham chiếu đến nó sẽ không bị ảnh hưởng bởi vì chúng đang tham chiếu đến một tệp khác - hiện đang ở trạng thái limbo.

Nếu một quy trình không phải là root tham chiếu đến một số tệp theo tên, họ sẽ gặp lỗi EPERM, vì một số tệp mới là thuộc sở hữu gốc.

Nếu bạn muốn ngăn nhiều quá trình trong cùng một người dùng (ví dụ: root) làm hỏng một tệp, linux có khóa tệp bắt buộc và tư vấn. Bạn có thể sử dụng flocklệnh trong shell script để khóa tập tin tư vấn (xem trang hướng dẫn để biết thêm thông tin).

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.