Tệp giả cho dữ liệu tạm thời


98

Tôi thường muốn cung cấp dữ liệu chuỗi tương đối ngắn (có thể là một vài dòng) cho các chương trình dòng lệnh chỉ chấp nhận đầu vào từ các tệp (ví dụ: wdiff) theo kiểu lặp lại. Chắc chắn tôi có thể tạo một hoặc nhiều tệp tạm thời, lưu chuỗi ở đó và chạy lệnh với tên tệp làm tham số. Nhưng có vẻ như quy trình này sẽ rất kém hiệu quả nếu dữ liệu thực sự được ghi vào đĩa và nó cũng có thể gây hại cho đĩa hơn mức cần thiết nếu tôi lặp lại quy trình này nhiều lần, ví dụ nếu tôi muốn cung cấp một dòng văn bản dài tập tin để wdiff. Có một cách được khuyến nghị để phá vỡ điều này, giả sử bằng cách sử dụng các tệp giả như ống để lưu trữ dữ liệu tạm thời mà không thực sự ghi nó vào đĩa (hoặc chỉ ghi khi vượt quá độ dài quan trọng). Lưu ý rằng wdiff có hai đối số và,wdiff <"text".


Điều này có thể được giải quyết thông qua xargs?
NN

Không biết, nhưng nó sẽ không rõ ràng với tôi như thế nào. Theo như tôi hiểu xargssẽ làm cho các dòng đầu vào từ các đối số chuỗi tệp cho lệnh. Nhưng tôi cần điều ngược lại.
highsciguy

@rahmu Tôi đã có một cái nhìn, nhưng tôi nghĩ rằng thiết lập vấn đề là một chút khác nhau ở đó. Ít nhất tôi không thấy câu trả lời sẽ giúp ích như thế nào. Câu trả lời được chấp nhận để tạo các tệp tạm thời đúng cách về cơ bản là những gì tôi sẽ không tránh, nếu không có một loại bộ đệm nào thực sự ngăn chặn việc ghi các tệp. Tôi có hiểu biết hạn chế về cách các tệp tạm thời hoạt động!
highsciguy

Có chuyện gì với bạn echo $data_are_here | dumb_programvậy?
vonbrand

1
Điều này sẽ chỉ hỗ trợ một tệp đầu vào và không phải tất cả các chương trình sẽ đọc từ stdin.
highsciguy

Câu trả lời:


55

Sử dụng một đường ống được đặt tên . Bằng cách minh hoạ:

mkfifo fifo
echo -e "hello world\nnext line\nline 3" > fifo

Các -eecho nói để giải thích chính xác lối thoát mới ( \n). Điều này sẽ chặn, tức là, vỏ của bạn sẽ treo cho đến khi một cái gì đó đọc dữ liệu từ đường ống.

Mở shell khác ở đâu đó và trong cùng thư mục:

cat fifo

Bạn sẽ đọc tiếng vang, sẽ giải phóng lớp vỏ khác. Mặc dù đường ống tồn tại dưới dạng nút tệp trên đĩa, nhưng dữ liệu đi qua nó thì không; tất cả diễn ra trong ký ức. Bạn có thể nền ( &) tiếng vang.

Ống có bộ đệm 64k (trên linux) và giống như một ổ cắm, sẽ chặn trình ghi khi đầy, do đó bạn sẽ không mất dữ liệu miễn là bạn không giết chết người viết sớm.


Ok, cảm ơn, điều này cũng hoạt động với hai ống tên và wdiff. Nhưng tôi nghĩ để hiểu rằng có một lượng bộ nhớ (nhỏ) nhất định có sẵn cho đường ống là bộ đệm. Điều gì xảy ra nếu tôi vượt quá kích thước bộ đệm?
highsciguy

Tôi đã thêm một đoạn cuối cùng về vấn đề đó.
goldilocks

3
/tmpđược cấu hình trong hầu hết các bản phân phối để sử dụng tmpfshệ thống tệp trong RAM. Khi bạn viết một tập tin vào /tmpnó sẽ đi thẳng vào RAM của bạn, đây là một câu trả lời tốt cho các tập tin bán đàn hồi phải được truy cập nhanh chóng và viết lại nhiều lần.

129

Trong Bash, bạn có thể sử dụng command1 <( command0 )cú pháp chuyển hướng, nó chuyển hướng command0thiết bị xuất chuẩn của nó và chuyển nó đến một command1cái tên lấy tên tệp làm đối số dòng lệnh. Điều này được gọi là quá trình thay thế .

Một số chương trình lấy các đối số dòng lệnh tên tệp thực sự cần một tệp truy cập ngẫu nhiên thực sự, vì vậy kỹ thuật này sẽ không hoạt động đối với các đối số đó. Tuy nhiên, nó hoạt động tốt với wdiff:

user@host:/path$ wdiff <( echo hello; echo hello1 ) <( echo hello; echo hello2 )
hello
[-hello1-]
{+hello2+}

Trong nền, điều này tạo ra một FIFO, chuyển lệnh bên trong <( )tới FIFO và chuyển mô tả tệp của FIFO làm đối số. Để xem những gì đang xảy ra, hãy thử sử dụng nó echođể in đối số mà không làm gì với nó:

user@host:/path$ echo <( echo hello )
/dev/fd/63

Tạo một ống có tên là linh hoạt hơn (nếu bạn muốn viết logic chuyển hướng phức tạp bằng nhiều quy trình), nhưng với nhiều mục đích, điều này là đủ, và rõ ràng là dễ sử dụng hơn.

Ngoài ra còn có >( )cú pháp khi bạn muốn sử dụng nó làm đầu ra, vd

$ someprogram --logfile >( gzip > out.log.gz )

Xem thêm bảng cheat chuyển hướng Bash cho các kỹ thuật liên quan.


Điều này không được hỗ trợ trong KSH
chanchal1987

5
ksh đã phát minh ra điều này. Bạn đang sử dụng một biến thể của ksh không hỗ trợ nó
Neil McGuigan

2
Một số chương trình lấy các đối số dòng lệnh tên tệp thực sự cần một tệp truy cập ngẫu nhiên thực sự, vì vậy kỹ thuật này sẽ không hoạt động đối với các đối số đó. Bạn làm gì trong những trường hợp này. Ví dụ ssh -F <(vagrant ssh-config) defaultsẽ rất tốt nhưng than ôi.
Sukima

10

wdiff là trường hợp đặc biệt do nó yêu cầu 2 đối số tên tệp, nhưng đối với tất cả các lệnh chỉ yêu cầu 1 đối số và từ chối một cách ngoan cố để lấy bất cứ điều gì ngoại trừ đối số tên tệp, có 2 tùy chọn:

  • Tên tệp '-' (nghĩa là dấu trừ) hoạt động khoảng 1/2 thời gian. Nó dường như phụ thuộc vào lệnh đang được đề cập và liệu nhà phát triển lệnh có bẫy trường hợp đó hay không và xử lý nó như mong đợi. ví dụ

    $> ls | con mèo -

  • Có một tệp psuedo có tên / dev / stdin tồn tại trong linux và có thể được sử dụng là một tên tệp hoàn toàn được yêu cầu bởi một lệnh. Điều này có nhiều khả năng hoạt động vì nó không yêu cầu bất kỳ xử lý tên tệp đặc biệt nào từ lệnh. Nếu một fifo hoạt động, hoặc phương pháp thay thế quá trình bash hoạt động thì điều này cũng sẽ hoạt động và không phải là vỏ cụ thể. ví dụ

    $> ls | mèo / dev / stdin


1
ít hơn và openssl như / dev / stdin thay vì / dev / fd / NUM :-)
lươn ghEEz
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.