Làm cách nào để chuyển hướng thiết bị xuất chuẩn và thiết bị xuất chuẩn sang tệp và hiển thị thiết bị xuất chuẩn sang bảng điều khiển?


18

Tôi biết cách chuyển hướng đến một tập tin và sử dụng tee; ở mức độ cơ bản. Vì thế

$ alias outanderr='bash -c "echo stdout >&1; echo stderr >&2"'
# A fake "application" displaying both output and error messages.

$ outanderr 1>file      # redirect stdout to a file, display stderr
stderr

$ outanderr 2>file      # redirect stderr to a file, display stdout
stdout

$ outanderr 1>file 2>&1 # redirect both to a file, display nothing

$ outanderr | tee file; echo "-- file contents --" && cat file
# redirect stdout to a file, display both (note: order is messed up)
stderr
stdout
-- file contents --
stdout

$ outanderr 2>&1 | tee file; echo "-- file contents --" && cat file
# redirect both to a file, display both
stdout
stderr
-- file contents --
stdout
stderr

Câu hỏi là: viết gì thay cho các dấu hỏi để có đầu ra bên dưới:

$ outanderr ???; echo "-- file contents --" && cat file
# redirect both to a file, display stderr
stderr
-- file contents --
stdout
stderr

Các hằng số:

  • Giả sử bash.
  • Thứ tự nên được giữ trong tập tin.
  • nội dung stderr được hiển thị theo từng dòng thời gian thực, tức là không có bộ đệm.
  • Tập tin tập lệnh riêng biệt có thể được sử dụng.
  • Phép thuật có thể là cần thiết.

Bạn có bao nhiêu quyền kiểm soát outanderrchương trình?
Kevin

1
@Kevin Tôi nghĩ rằng câu hỏi này chung chung hơn thế. Ở đây, outanderrchỉ là một bí danh in một dòng thành thiết bị xuất chuẩn và một dòng khác cho thiết bị xuất chuẩn. Ý tưởng (nếu có thể) là xây dựng một giải pháp chung có thể hoạt động với bất kỳ chương trình nào, mà không sửa đổi chúng.
lgeorget

@lgeorget Tôi hiểu điều đó, nhưng tôi không tin rằng có thể đáp ứng nghiêm ngặt tất cả các ràng buộc trong một giải pháp chung, vì vậy tôi đã xem liệu chúng ta có thể có được một điều cụ thể không.
Kevin

@Igeorget nói đúng.
TWiStErRob

Câu trả lời:


12
2>&1 >>outputfile | tee --append outputfile

Để kiểm tra dễ dàng:

echo -n >outputfile; bash -c "echo stdout >&1; echo stderr >&2" 2>&1 >>outputfile |
  tee --append outputfile; echo "outputfile:"; cat outputfile

Chỉnh sửa 1:

Điều này hoạt động bằng cách viết thiết bị xuất chuẩn (chỉ) vào tệp, tạo ra thiết bị xuất chuẩn sterrout để nó đi qua đường ống và có tee ghi đầu ra của nó vào cùng một tệp.

Cả hai ghi phải được thực hiện trong chế độ chắp thêm ( >>thay vì >) nếu không cả hai sẽ ghi đè lên đầu ra của nhau.

Vì đường ống là bộ đệm nên không có gì đảm bảo rằng đầu ra xuất hiện trong tệp theo đúng thứ tự. Điều này thậm chí sẽ không thay đổi nếu một ứng dụng được kết nối với cả hai bộ mô tả tệp (hai ống dẫn). Đối với đơn hàng được đảm bảo, cả hai đầu ra sẽ phải đi qua cùng một kênh và được đánh dấu tương ứng. Hoặc bạn sẽ cần một số thứ thực sự ưa thích:

  1. Nếu cả stdout và stderr đều được chuyển hướng đến một tệp (không phải cùng một tệp!) Và cả hai tệp đều nằm trên một khối FUSE thì mô-đun FUSE có thể đánh dấu mỗi lần ghi bằng dấu thời gian để ứng dụng thứ hai có thể sắp xếp dữ liệu chính xác và kết hợp nó cho các tập tin đầu ra thực sự. Hoặc bạn không đánh dấu dữ liệu nhưng yêu cầu mô-đun tạo tệp đầu ra kết hợp. Hầu hết có lẽ không có mô-đun FUSE nào ...
  2. Cả stdout và stderr đều có thể được chuyển đến /dev/null. Các đầu ra của ứng dụng sẽ được phân tách bằng cách chạy qua strace -f -s 32000 -e trace=write. Bạn sẽ phải đảo ngược việc trốn thoát trong trường hợp đó. Không cần phải nói rằng ứng dụng không chạy nhanh hơn bằng cách truy tìm.
  3. Có lẽ điều tương tự có thể đạt được bằng cách sử dụng một mô-đun FUSE đơn giản, hiện có và truy tìm mô-đun thay vì ứng dụng. Điều này có thể nhanh hơn truy tìm ứng dụng vì (hay đúng hơn là: nếu) mô-đun có thể có ít tòa nhà hơn so với ứng dụng.
  4. Nếu bản thân ứng dụng có thể được sửa đổi: Ứng dụng có thể bị dừng sau mỗi đầu ra (nhưng tôi nghĩ rằng điều này chỉ có thể từ bên trong) và chỉ tiếp tục sau khi nhận được tín hiệu s (SIGUSR1 hoặc SIGCONT). Ứng dụng đọc từ đường ống sẽ phải kiểm tra cả đường ống và tệp để tìm dữ liệu mới và gửi tín hiệu sau mỗi dữ liệu mới. Tùy thuộc vào loại ứng dụng, điều này có thể nhanh hơn hoặc thậm chí chậm hơn so với phương pháp strace. FUSE sẽ là giải pháp tốc độ tối đa.

1
Bah Bắt tôi ở giữa viết lên chính xác cùng một câu trả lời tại sao không.
Kevin

2
NB điều này có một điều kiện chủng tộc giới thiệu khả năng hoán đổi các dòng / lỗi, nhưng tôi không nghĩ rằng có thể tránh được.
Kevin

1
@Kevin Điều đó xảy ra với những người giỏi nhất trong chúng ta, tôi đã chịu đựng điều đó trước đây và gần như đã yêu cầu một tính năng "cho tôi thấy rằng ai đó đang viết" (mặc dù điều này sẽ phức tạp). Dường như với tôi rằng điều kiện cuộc đua chỉ xảy ra nếu một lần ghi vào tệp (thiết bị xuất chuẩn) xảy ra sau khi ghi vào đường ống.
Hauke ​​Laging

Điều đó sẽ không gửi cả stdoutstderrđến tee, hoặc tôi đang thiếu một cái gì đó? Tôi nghĩ rằng yêu cầu của OP là tee stderrchỉ.
Joseph R.

@JosephR. Bạn đã không thử rằng?
Hauke ​​Laging
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.