Có an toàn để chuyển hướng thiết bị xuất chuẩn và thiết bị xuất chuẩn vào cùng một tệp mà không có bản sao mô tả tệp không?


27

Tôi bắt đầu trong thư mục trống.

$ touch aFile
$ ls
aFile

Sau đó, tôi lshai đối số, một trong số đó không có trong thư mục này. Tôi chuyển hướng cả hai luồng đầu ra đến một tập tin có tên output. Tôi sử dụng >>để tránh viết đồng thời.

$ ls aFile not_exist >>output 2>>output
$ cat output
ls: cannot access 'not_exist': No such file or directory
aFile

Mà dường như để làm việc. Có bất kỳ nguy hiểm cho phương pháp này?


6
Đó là một cuộc bỏ phiếu nhanh chóng. Phải mất năm giây. Bạn có thể cho tôi biết làm thế nào mà bạn có thể đánh giá sự xứng đáng của câu hỏi của tôi nhanh như vậy không? Và tốt hơn nữa, có gì sai với nó để tôi có thể cải thiện nó?
exit_status

Tại sao bạn không sử dụng tiêu chuẩn hơn ls aFile not_exist &>>outputở đây? (Lưu ý, tôi giả sử bạn đang sử dụng bash .)
FedonKadifeli

5
Bởi vì điều đó không giúp tôi hiểu những gì tôi đang hỏi về. Tôi biết làm thế nào để chuyển hướng các luồng này vào cùng một tệp, thậm chí là có thể. Những gì tôi muốn biết là nếu có bất cứ điều gì sai với những gì tôi đề nghị trong câu hỏi. @FedonKadifeli
exit_status

1
@FedonKadifeli &>>KHÔNG chuẩn. Đó là một cú pháp mơ hồ, mơ hồ, hoạt động khác nhau trong các shell khác nhau. Tôi tự hỏi các bạn lấy đồ từ đâu
Chú Billy

4
Bash không phải là một tiêu chuẩn . Tiêu chuẩn POSIX bắt buộc ls &>>foo ...phải được phân tích cú pháp thành hai ls &đồng chí >>foo ...và đây là cách các trình bao khác như /bin/shtừ Ubuntu đang phân tích cú pháp. Đối với nó bị phản đối, bạn có thể nhìn vào đây - mặc dù tôi không giả vờ rằng đó là bất kỳ loại thẩm quyền nào. Bạn có thể hỏi những người bashbảo trì nếu họ xem xét sử dụng đó là một ý tưởng tốt, mặc dù.
Chú Billy

Câu trả lời:


22

Không, nó không chỉ an toàn như tiêu chuẩn >>bar 2>&1.

Khi bạn viết

foo >>bar 2>>bar

bạn đang mở bartệp hai lần với O_APPEND, tạo hai đối tượng tệp hoàn toàn độc lập [1], mỗi đối tượng có trạng thái riêng (con trỏ, chế độ mở, v.v.).

Điều này rất giống với 2>&1việc chỉ gọi cuộc gọi dup(2)hệ thống và tạo ra các bí danh stderr và stdout có thể hoán đổi cho cùng một đối tượng tệp.

Bây giờ, có một vấn đề với điều đó:

O_APPENDcó thể dẫn đến các tệp bị hỏng trên các hệ thống tệp NFS nếu có nhiều quá trình nối dữ liệu vào một tệp cùng một lúc. Điều này là do NFS không hỗ trợ nối thêm vào một tệp, do đó, kernel client phải mô phỏng nó, điều này không thể thực hiện được nếu không có điều kiện chạy đua.

Bạn thường có thể tin tưởng vào khả năng của tập tin như bartrong foo >>bar 2>&1được ghi vào cùng lúc từ hai địa điểm riêng biệt là khá thấp. Nhưng bằng cách của >>bar 2>>barbạn, bạn chỉ cần tăng nó một chục đơn đặt hàng lớn, mà không có lý do.

[1] "Mô tả tệp mở" trong biệt ngữ POSIX.


3
Chính thức, đối với các tập tin chế độ chắp thêm, nó là an toàn . Vấn đề được trích dẫn là một lỗi trong NFS khiến nó không phù hợp (không tuân thủ POSIX) như một hệ thống tệp. Tuy nhiên, đối với trường hợp không có chế độ bổ sung, nó không bao giờ an toàn.
R ..

1
Đó là phi vật chất. Nối đôi của OP không an toàn để sử dụng (ngoài việc hoàn toàn vô nghĩa). Và O_APPENDdù sao cũng là một botch - khá khó để thực hiện chính xác.
mosvy

Tôi tin rằng điều kiện cuộc đua NFS chỉ giữa các khách hàng khác nhau. HĐH máy khách nên phối hợp tất cả các ghi giữa các quy trình của nó.
Barmar

@Barmar điều đó sẽ đúng nếu HĐH máy khách chỉ quan tâm đến chế độ xem riêng của nó về tệp nfs. Nhưng khi ghi vào tệp nfs được mở bằng O_APPEND, trước tiên khách hàng sẽ truy xuất kích thước "thực" của tệp từ máy chủ ("xác nhận lại" nút inode) và sau đó thực hiện cập nhật inode tìm kiếm + write + được lưu trong bộ nhớ cache và chỉ phần cuối cùng là được thực hiện dưới các khóa, có nghĩa là phần đầu tiên vẫn có thể lấy kích thước cũ từ máy chủ và ghi đè lên phần chính xác từ nút inode cục bộ / được lưu trữ. Cùng một vấn đề với lseek(SEEK_END).
mosvy

Tôi vẫn không thấy điều đó có thể gây ra tình trạng chủng tộc giữa hai luồng trên cùng một máy khách. Cả hai luồng nên tham chiếu đến cùng một nút được lưu trữ cục bộ.
Barmar

22

Điều gì xảy ra khi bạn làm

some_command >>file 2>>file

là nó filesẽ được mở để nối thêm hai lần. Điều này là an toàn để làm trên một hệ thống tập tin POSIX. Bất kỳ ghi nào xảy ra với tệp khi nó được mở để nối thêm sẽ xảy ra ở cuối tệp, bất kể dữ liệu đi qua luồng đầu ra tiêu chuẩn hay luồng lỗi tiêu chuẩn.

Điều này phụ thuộc vào sự hỗ trợ cho các hoạt động ghi thêm nguyên tử trong hệ thống tập tin cơ bản. Một số hệ thống tập tin, chẳng hạn như NFS, không hỗ trợ nối thêm nguyên tử. Xem ví dụ: câu hỏi "Tập tin có nối thêm nguyên tử trong UNIX không?" Trên StackOverflow.

Sử dụng

some_command >>file 2>&1

sẽ làm việc ngay cả trên NFS.

Tuy nhiên, sử dụng

some_command >file 2>file

không an toàn, vì trình bao sẽ cắt bớt tệp đầu ra (hai lần) và bất kỳ ghi nào xảy ra trên một trong hai luồng sẽ ghi đè lên dữ liệu đã được ghi bởi luồng khác.

Thí dụ:

$ { echo hello; echo abc >&2; } >file 2>file
$ cat file
abc
o

Các hellochuỗi được viết đầu tiên (với một dòng mới chấm dứt), và sau đó là chuỗi abctiếp theo một dòng mới được viết từ sai số chuẩn, ghi đè hell. Kết quả là chuỗi abccó một dòng mới, theo sau là những gì còn lại của đầu echora đầu tiên , một ovà một dòng mới.

Hoán đổi hai echoxung quanh vết thương chỉ tạo ra hellotrong tệp đầu ra vì chuỗi đó được viết sau cùng và dài hơn abcchuỗi. Thứ tự chuyển hướng xảy ra không quan trọng.

Nó sẽ tốt hơn và an toàn hơn để sử dụng thành ngữ hơn

some_command >file 2>&1

1
Mặc dù điều đó đúng với các loại đạn hiện đại, nhưng đó không phải là trường hợp của vỏ Bourne hoặc Thomson ( >>đến từ đâu), nơi >>sẽ mở ra để viết và tìm kiếm đến cuối cùng (tôi cho rằng vì O_APPEND chưa được phát minh trước đó). Ngay cả trên Solaris 10, /bin/sh -c '(echo a; echo b >&2) >> file 2>> file; cat file'đầu ra b.
Stéphane Chazelas

@ StéphaneChazelas Đó có phải là vấn đề với việc triển khai của Solaris 10 shhay với hệ thống tập tin của nó không?
Kusalananda

1
Đó là những gì >>ban đầu đang làm, nó không mở bằng O_APPEND, nó mở mà không có và tìm kiếm đến cùng. Đó không phải là một vấn đề, đó là những gì nó đã làm và được ghi nhận để làm.
Stéphane Chazelas

0

Nó phụ thuộc vào những gì bạn muốn đạt được. Tùy bạn quyết định liệu có ổn không khi có lỗi trong cùng một tệp với đầu ra. Đây chỉ là lưu văn bản trong một tệp có chức năng của trình bao cho phép bạn chuyển hướng theo ý muốn. Không có hoàn toàn có hay không. Mọi thứ trong Linux đều có thể được thực hiện theo nhiều cách, đây là cách của tôi ls notExistingFile existingFile >> output 2>&1 Để trả lời câu hỏi: Về mặt chuyển hướng, vâng, nó hoàn toàn an toàn.


Có nhiều điều hơn nó đang nói ở đây. Bài tập tương tự với >thay vì >>sẽ ghi đè lên một số nhân vật. Vì vậy, nó không chỉ là vỏ cho phép tôi chuyển hướng, bởi vì khi tôi chuyển hướng với >, kết quả là khác nhau. Vì vậy, có những sắc thái với >, có bất kỳ với >>?
exit_status

Có nó sẽ khác. Như tôi đã nói, nó phụ thuộc vào mục tiêu của bạn >- ghi đè. >>- chắp thêm
Thiên thần
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.