tar to pipe nhưng giữ đầu ra -v verbose tách biệt với STDERR


12

Một lệnh tar bình thường

tar cvf foo.tar ./foo >foo.out 2>foo.err

có ba luồng IO đầu ra

  • lưu trữ dữ liệu vào foo.tar
  • danh sách tên tệp thành STDOUT (chuyển hướng vào foo.out)
  • thông báo lỗi tới STDERR (được chuyển hướng vào foo.err)

Sau đó tôi có thể kiểm tra foo.err để tìm thông báo lỗi mà không cần phải đọc qua danh sách tên tệp.

nếu tôi muốn làm gì đó với dữ liệu lưu trữ (chuyển nó qua netcat hoặc chương trình nén đặc biệt), tôi có thể sử dụng -f -tùy chọn tar do đó

tar cvf - ./foo 2>foo.err | squish > foo.tar.S

Nhưng bây giờ, danh sách tên tệp của tôi được trộn lẫn với các thông báo lỗi của tôi vì -vđầu ra của tar rõ ràng không thể chuyển đến STDOUT (đó là nơi lưu trữ dữ liệu lưu trữ) vì vậy tar đã khéo léo viết nó vào STDERR.

Sử dụng Korn shell, có một cách để xây dựng một lệnh chuyển luồng lưu trữ sang một lệnh khác nhưng vẫn thu được -vđầu ra riêng biệt với bất kỳ thông báo lỗi nào.


Bạn có quen thuộc teekhông? Đây có vẻ như là một trường hợp sử dụng khá hợp lệ cho nó.
HalosGhost

Câu trả lời:


9

Nếu hệ thống của bạn hỗ trợ /dev/fd/n:

tar cvf /dev/fd/3 ./foo 3>&1 > foo.out 2>foo.err | squish > foo.tar.S

Mà với việc triển khai AT & T của ksh( bashhoặc zsh) bạn có thể viết bằng cách sử dụng thay thế quy trình :

tar cvf >(squish > foo.tar.S) ./foo > foo.out 2>foo.err

Đó là thực hiện chính xác điều tương tự ngoại trừ lần này, shell quyết định sử dụng bộ mô tả tệp nào thay vì 3(thường là trên 9). Một sự khác biệt nữa là lần này, bạn có trạng thái thoát tarthay vì squish. Trên các hệ thống không hỗ trợ /dev/fd/n, một số vỏ có thể sử dụng các đường ống được đặt tên cho tính năng đó.

Nếu hệ thống của bạn không hỗ trợ /dev/fd/nhoặc vỏ của bạn không thể sử dụng các đường ống được đặt tên để thay thế quy trình, thì đó là nơi bạn phải xử lý các đường ống được đặt tên bằng tay .


6

Bạn phải sử dụng một đường ống được đặt tên cho điều đó.

Đầu tiên tạo một trong thư mục:

mkfifo foo.pipe

Sau đó sử dụng lệnh đó:

tar cvf foo.pipe ./foo >foo.out 2>foo.err & cat foo.pipe >foo.tar

Lưu ý: các cat-part, bây giờ cũng có thể được gziphoặc bất cứ điều gì, có thể đọc từ một ống:

tar cvf foo.pipe ./foo >foo.out 2>foo.err & gzip -c foo.pipe >foo.tar

Giải trình:

Kết quả được ghi vào ống tên ( foo.pipe), nơi proccess khác ( cat, gzip, netcat) đọc từ. Vì vậy, bạn không mất các kênh stdout / stderr để biết thông tin.


1
Có thể đáng chú ý những tác động của việc sử dụng một đường ống được đặt tên . 1) tốt nhất là đặt một umask 077(hoặc sử dụng một thư mục tạm thời riêng tư) để ngăn các quá trình khác đọc hoặc ghi vào nó (trên nhiều hệ thống, các ống có tên, giống như các tệp khác được tạo theo cách dễ đọc theo mặc định), 2) bạn cần đảm bảo đường ống có tên chỉ được sử dụng bởi mỗi phiên bản của tập lệnh của bạn (một lần nữa thư mục tạm thời riêng tư một lần trợ giúp) 3) Điều đó có nghĩa là bạn cần dọn dẹp sau đó hoặc nếu bị gián đoạn.
Stéphane Chazelas

1
+1 - Tôi thích câu trả lời này. Thật không may cho tôi, có một số điều kỳ lạ trong các đường ống được đặt tên trên hệ thống (cũ) của tôi khiến chúng không đáng tin khi tôi thử điều này.
RedGrittyBrick

1
@ StéphaneChazelas - Tôi nghĩ rằng đôi khi có thể dễ dàng dọn dẹp trước, như:p="/tmp/pipe$$"; mkfifo "$p"; (read na; cmd[s]...) <>"$p" & (echo;rm "$p"; cmd[s]...) >"$p"
mikeerv

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.