Có bash mở các tệp trong O_APPEND khi sử dụng trên >> >> trên linux không?


38

Nếu chúng ta sử dụng echo 1234 >> some-filethì Tài liệu nói rằng đầu ra được nối thêm.

Tôi đoán là, nếu một số tệp không tồn tại, thì O_CREAT sẽ tạo một tệp mới. Nếu >được sử dụng, thì O_TRUNC sẽ cắt bớt tệp hiện có.

Trong trường hợp >>: Tập tin sẽ được mở dưới dạng O_WRONLY (hoặc O_RDWR) và tìm cách kết thúc và ghi thao tác được thực hiện, mô phỏng O_APPEND? Hoặc tệp sẽ được mở dưới dạng O_APPEND, để nó vào kernel để đảm bảo việc nối thêm xảy ra?

Tôi đang hỏi điều này bởi vì một quy trình máy chủ đang ghi đè một số điểm đánh dấu được chèn bởi echo, khi tệp đầu ra từ điểm gắn NFS, & Tài liệu NFS nói rằng O_APPEND không được hỗ trợ trên máy chủ, do đó, máy khách sẽ phải xử lý nó. Tôi đoán quá trình máy chủ đang sử dụng O_APPEND, nhưng không chắc chắn về bash >>trên linux, do đó đặt câu hỏi ở đây.


12
Vấn đề trên NFS không O_APPENDđược hỗ trợ; Vấn đề là nó được mô phỏng. Trên hệ thống tệp cục bộ, một số quy trình ghi vào cùng một tệp được mở O_APPEND sẽ không bao giờ ghi đè lên dữ liệu của nhau; trên NFS, O_APPENDđược mô phỏng bằng cách tìm kiếm đến cuối trước khi viết, điều này để lại khả năng điều kiện chủng tộc. Không có cách nào xung quanh điều này trên NFS; mỗi nhà văn song song cần phải viết tập tin riêng của mình. Cách duy nhất để giải quyết vấn đề này là thiết lập quy trình máy chủ trên máy chủ NFS, ghi nhật ký loggers |nc server portvà để máy chủ nối thêm dữ liệu đến vào nhật ký.
Guntram Blohm hỗ trợ Monica

@GuntramBlohm, +1, cảm ơn vì đã xác nhận. Về cơ bản, đề xuất của bạn là chỉ sử dụng một quy trình nhà văn cho tệp và tất cả các quy trình nhà văn khác sẽ trải qua quy trình này.
Prem

Rất nhiều câu trả lời hay, Không chắc câu nào tôi nên chấp nhận. Bruce Ediger đầu tiên cho thấy O_APPEND được sử dụng. Random832 tiếp theo cho thấy rằng điều này được đưa ra trong các tiêu chuẩn. Cuối cùng, Eric Renouf cho thấy mã nguồn với cùng một câu trả lời. Tất cả ba quan điểm thêm vào bức tranh hoàn chỉnh cuối cùng.
Prem

6
Nói tóm lại, NFS là một lỗi của lỗi và không nên được sử dụng.
R ..

2
Vâng, nhưng chúng tôi đã học được cách đó khi O_EXCL được phát minh.
Kevin

Câu trả lời:


60

Tôi chạy này: strace -o spork.out bash -c "echo 1234 >> some-file"để tìm ra câu hỏi của bạn. Đây là những gì tôi tìm thấy:

open("some-file", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3

Không có tệp có tên "some-file" tồn tại trong thư mục mà tôi đã chạy echolệnh.


50

Điều này không chỉ được thực hiện ở Bash, mà nó còn được yêu cầu bởi tiêu chuẩn.

Từ thông số kỹ thuật Unix đơn :

Chuyển hướng đầu ra được nối sẽ làm cho tệp có kết quả tên từ việc mở rộng từ được mở để xuất ra trên bộ mô tả tệp được chỉ định. Tệp được mở như thể hàm open () như được định nghĩa trong âm lượng Giao diện hệ thống của POSIX.1-2008 được gọi bằng cờ O_APPEND. Nếu tập tin không tồn tại, nó sẽ được tạo.

Do đó, mọi vỏ tương thích POSIX đều phải làm điều đó. Trên một số hệ thống Unix, /bin/shcó thể là vỏ Bourne không phải POSIX (Vỏ Bourne ban đầu được viết trước đó O_APPENDđược phát minh) và vỏ POSIX có sẵn thường kshsẽ có sẵn shở một vị trí đường dẫn khác như Solaris /usr/xpg4/bin.


2
Thật thú vị, một cái vỏ không làm được nó là cái vỏ Bourne. Shell Bourne mở ra mà không có O_TRUNC và lseek () s đến cuối. Đó là bởi vì nó được viết trước khi cờ O_APPEND được thêm vào open(). >>chính nó đã được giới thiệu bởi người tiền nhiệm của nó vỏ Thomson.
Stéphane Chazelas

1
@ StéphaneChazelas Ngoài ra, tôi đã tra cứu nguồn vỏ C cho các phiên bản khác nhau và cờ O_APPEND không được giới thiệu cho đến 4.3BSD-Reno.
Random832

Nó nói "như thể", vì vậy nó không thể được thực hiện khác đi (nhưng tạo ra hiệu ứng có thể quan sát được)? Có vẻ như tiêu chuẩn không yêu cầu sử dụng O_APPEND, chỉ là thứ gì đó hoạt động "như thể".
Thomas

1
@Thomas Điều đó có nghĩa là bạn sẽ nhận được tất cả các hành vi được ghi lại cho O_APPEND, nghĩa là định vị lại ở cuối cho mỗi lần viết. "Như thể" chỉ là verbiage tiêu chuẩn có nghĩa là cho phép, ví dụ như nó được mở bằng một số phương tiện khác ngoài việc thực sự gọi hàm open () trên các nền tảng phi truyền thống.
Random832

+1, cho thấy hành vi này nằm trong các tiêu chuẩn.
Prem

32

Nhìn vào nguồn, nó sử dụng O_APPEND. Đối với bash 4.3.30 trong make_cmd.cdòng 710-713, hãy đọc:

case r_appending_to:                /* >>foo */
case r_append_err_and_out:          /* &>> filename */
  temp->flags = O_APPEND | O_WRONLY | O_CREAT;
  break;

+1, để hiển thị câu trả lời từ phối cảnh mã nguồn.
Prem

19

Hãy điều tra rằng sử dụng stracetrên hệ thống tệp cục bộ (không phải NFS):

$ strace -eopen -- bash -c "echo foo >> /tmp/testfile000" 2>&1 | grep /tmp/testfile000
open("/tmp/testfile000", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3

$ strace -eopen -- bash -c "echo foo > /tmp/testfile000" 2>&1 | grep /tmp/testfile000
open("/tmp/testfile000", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3

Vỏ khác, cụ thể là dash, dash, shcủa busybox' và mkshcư xử theo cùng một cách.

Tùy chọn này -e opencó nghĩa là -e trace=openchỉ theo dõi open()cuộc gọi hệ thống.

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.