OS X, bash: ít hoạt động hơn trên các mô tả tệp mở, cat không


10

Trong tập lệnh bash tôi đang làm việc (phải chạy trên Ubuntu và OS X), tôi cần chuyển hướng đầu ra của hàng trăm lệnh thành một tệp.
Thay vì nối thêm &>...vào tất cả chúng, tôi chỉ đơn giản là làm

exec 9>&1
exec 5<>/tmp/some-file.txt
exec 1>&5

Cho đến nay rất tốt, nhưng giữa chừng tất cả các lệnh đó, tôi cần đọc mọi thứ đã được viết cho đến nay, trong khi vẫn giữ cho bộ mô tả tệp mở.
Bây giờ, trên Ubuntu tôi chỉ có thể làm

cat /dev/fd/5

hoặc là

tee </dev/fd/5

nhưng trên OS X, không có gì được in cả (và các lệnh thoát ngay lập tức).
Tuy nhiên, bằng cách sử dụng lesstôi có thể thấy nội dung của tập tin trên cả hai.
Tôi có thể đạt được hiệu ứng trên (hoạt động trên cả hai hệ điều hành) bằng cách sử dụng

less /dev/fd/5 | tee

nhưng đó có vẻ là một hack.

Vậy, tại sao lessrõ ràng có thể thấy những thứ catkhông thể có trên OS X? (Hoặc tất cả con cháu BSD bị ảnh hưởng?)
Hay tôi đang làm gì đó sai?

Câu trả lời:


13

Trên OS X, giống như trên tất cả các hệ thống mà chúng được hỗ trợ ngoại trừ Linux , việc mở /dev/fd/xgiống như thực hiện a dup(x), kết quả fd ít nhiều điểm cho cùng một mô tả tệp mở như trên fd x và đặc biệt sẽ có cùng độ lệch trong tệp.

Linux là ngoại lệ ở đây. Trên Linux, /dev/fd/xlà một liên kết tượng trưng đến /proc/self/fd/x/proc/self/fd/xlà một liên kết giả đối với tệp đang mở trên fd x. Trên Linux khi bạn thực hiện open("/dev/fd/x", somemode), bạn nhận được một mô tả tệp mở hoàn toàn mới cho cùng một tệp như mở trên x. Fd mới mà bạn có được không liên quan đến fd x dưới bất kỳ hình thức nào. Cụ thể, phần bù sẽ nằm ở phần đầu của tệp (trừ khi bạn mở bằng O_APPENDkhóa học) và chế độ (đọc / ghi / nối ...) có thể khác với phần trên fd x (thậm chí bạn có thể nhận được một cái gì đó hoàn toàn khác với những gì trên fd x, như đầu kia của ống khi mở nó ở chế độ ngược lại). (Điều đó cũng có nghĩa là nó không hoạt động đối với các socket chẳng hạn mà bạn không thể mở () ).

Vì vậy, trên Linux, khi bạn làm

exec 5<> file
echo test >&5

Phần bù của fd 5 nằm ở cuối tập tin. Nếu bạn làm

cat <&5

Bạn không nhận được gì.

Vẫn khi bạn làm:

cat /dev/fd/5

Bạn thấy testbởi vì catcó một fd chỉ đọc mới filekhông liên quan đến fd 5.

Trên các hệ thống khác, khi

cat /dev/fd/5

cat nhận được một fd là bản sao của fd 5, do đó, vẫn có phần bù ở cuối tệp.

Lý do tại sao nó hoạt động lesslà vì một số lý do, lessthực hiện một lseek()fd đó vào đầu tập tin ( lseek(1); lseek(0)để xác định xem tập tin có thể tìm kiếm được hay không).

Ở đây, bạn có thể muốn có một fd để đọc và một để viết nếu bạn muốn cả hai có độ lệch khác nhau:

exec 5< file 9>&1 > file

Hoặc bạn sẽ phải mở lại tệp nếu vẫn ở đó hoặc làm lseek()như lessvậy.

ksh93zshlà các shell duy nhất có lseek()toán tử dựng sẵn :

cat <&5 <#((0)) # ksh93
{sysseek 0; cat} <&5 # zsh, zmodload zsh/system to enable that builtin

Hoặc là:

cat /dev/fd/5 5<#((0))  # ksh93
sysseek -u 5 0; cat /dev/fd/5 # zsh
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.