Làm thế nào tôi có thể đạt được
cmd >> file1 2>&1 1>>file2
Đó là, thiết bị xuất chuẩn và thiết bị xuất chuẩn nên chuyển hướng đến một tệp (tệp1) và chỉ thiết bị xuất chuẩn (tệp 2) mới nên chuyển hướng sang tệp khác (cả trong chế độ chắp thêm)?
Làm thế nào tôi có thể đạt được
cmd >> file1 2>&1 1>>file2
Đó là, thiết bị xuất chuẩn và thiết bị xuất chuẩn nên chuyển hướng đến một tệp (tệp1) và chỉ thiết bị xuất chuẩn (tệp 2) mới nên chuyển hướng sang tệp khác (cả trong chế độ chắp thêm)?
Câu trả lời:
Vấn đề là khi bạn chuyển hướng đầu ra của mình, nó không còn khả dụng cho lần chuyển hướng tiếp theo. Bạn có thể chuyển sang tee
trong một khung con để giữ đầu ra cho lần chuyển hướng thứ hai:
( cmd | tee -a file2 ) >> file1 2>&1
hoặc nếu bạn muốn xem đầu ra trong terminal:
( cmd | tee -a file2 ) 2>&1 | tee -a file1
Để tránh thêm stderr của lần đầu tiên tee
vào file1
, bạn nên chuyển hướng stderr của lệnh của bạn sang một số mô tả tệp (ví dụ 3), và sau đó thêm điều này vào thiết bị xuất chuẩn:
( 2>&3 cmd | tee -a file2 ) >> file1 3>&1
# or
( 2>&3 cmd | tee -a file2 ) 3>&1 | tee -a file1
(cảm ơn @ fra-san)
Với zsh
:
cmd >& out+err.log > out.log
Trong chế độ chắp thêm:
cmd >>& out+err.log >> out.log
Trong zsh
và được cung cấp mult_ios
tùy chọn chưa bị vô hiệu hóa, khi một bộ mô tả tệp (ở đây 1) được chuyển hướng nhiều lần để ghi, thì trình bao thực hiện một tích hợp tee
để sao chép đầu ra cho tất cả các mục tiêu.
cmd >& file1 > file2
Bạn có thể: tag stdout (sử dụng sed UNBUFFERED, tức là sed -u ...
:), stderr cũng đi đến stdout (không được gắn thẻ, vì nó không đi qua sed gắn thẻ đó), và do đó có thể phân biệt 2 trong logfile kết quả.
Cách sau: chậm (Nó có thể được tối ưu hóa nghiêm túc, bằng cách sử dụng để tạo ra một tập lệnh perl thay vì trong khi ...; làm ...; thực hiện, ví dụ, sẽ sinh ra các chuỗi con & lệnh ở mỗi dòng!), Lạ (có vẻ như tôi cần 2 giai đoạn {} trong một lần đổi tên thiết bị xuất chuẩn và sau đó trong giai đoạn khác thêm "stderr vào" stderr cho nó), v.v. Nhưng đó là: " bằng chứng về khái niệm ", sẽ cố gắng giữ thứ tự đầu ra là hầu hết các thiết bị xuất chuẩn & stderr càng nhiều càng tốt:
#basic principle (some un-necessary "{}" to visually help see the layers):
# { { complex command ;} | sed -e "s/^/TAGstdout/" ;} 2>&1 | read_stdin_and_redispatch
#exemple:
# complex command = a (slowed) ls of several things (some existing, others not)
# to see if the order of stdout&stderr is kept
#preparation, not needed for the "proof of concept", but needed for our specific exemple setup:
\rm out.file out_AND_err.file unknown unknown2
touch existing existing2 existing3
#and the (slow, too many execs, etc) "proof of concept":
uniquetag="_stdout_" # change this to something unique, that will NOT appear in all the commands outputs...
# avoid regexp characters ("+" "?" "*" etc) to make it easy to remove with another sed later on.
{
{ for f in existing unknown existing2 unknown2 existing3 ; do ls -l "$f" ; sleep 1; done ;
} | sed -u -e "s/^/${uniquetag}/" ;
} 2>&1 | while IFS="" read -r line ; do
case "$line" in
${uniquetag}*) printf "%s\n" "$line" | tee -a out_AND_err.file | sed -e "s/^${uniquetag}//" >> out.file ;;
*) printf "%s\n" "$line" >> out_AND_err.file ;;
esac;
done;
# see the results:
grep "^" out.file out_AND_err.file
ls unknown
) để in một cái gì đó trên stderr? >&2 echo "error"
sẽ ổn thôi (2) tee
có thể nối thêm nhiều tệp cùng một lúc. (3) Tại sao không chỉ cat
thay vì grep "^"
? (4) tập lệnh của bạn sẽ thất bại khi đầu ra stderr bắt đầu bằng _stdout_
. (5) Tại sao?
ls loop
; đuôi thông thường (ví dụ, trên aix.). 3): grep "^" cũng hiển thị cả tên tệp. 4): điều này có thể được thay đổi bởi các biến. 5): ví dụ phức tạp hoạt động trên các ose cũ (ex, aix cũ) nơi tôi đã thử nghiệm nó (không có sẵn perl).
uniquetag="banaNa11F453355B28E1158D4E516A2D3EDF96B3450406
...)
Nếu thứ tự đầu ra phải là: stdout thì stderr ; không có giải pháp chỉ với chuyển hướng.
Stderr phải được lưu trữ vào một tập tin tạm thời
cmd 2>>file-err | tee -a file1 >>file2
cat file-err >> file1
rm file-err
Sự miêu tả:
Cách duy nhất để chuyển hướng một đầu ra (một fd như stdout hoặc stderr) sang hai tệp là sao chép nó. Lệnh tee
này là công cụ chính xác để tái tạo nội dung mô tả tệp. Vì vậy, một ý tưởng ban đầu để có một đầu ra trên hai tệp sẽ được sử dụng:
... | tee file1 file2
Điều đó tái tạo stdin của tee cho cả hai tệp (1 & 2) khiến đầu ra của tee vẫn không được sử dụng. Nhưng chúng ta cần phải chắp thêm (sử dụng -a
) và chỉ cần một bản sao. Điều này giải quyết cả hai vấn đề:
... | tee -a file1 >>file2
Để cung cấp tee
với thiết bị xuất chuẩn (cái cần lặp lại), chúng ta cần tiêu thụ stderr trực tiếp ra khỏi lệnh. Một cách, nếu thứ tự không quan trọng (thứ tự đầu ra sẽ (rất có thể) sẽ được giữ nguyên như được tạo, tùy theo đầu ra nào sẽ được lưu trước). Hoặc:
cmd 2>>file1 | tee -a file2 >>file1
cmd 2>>file1 > >( tee -a file2 >>file1 )
( cmd | tee -a file2 ) >> file1 2>&1
Tùy chọn 2 chỉ hoạt động trong một số shell. Tùy chọn 3 sử dụng một lớp con bổ sung (chậm hơn) nhưng chỉ sử dụng tên tệp một lần.
Nhưng nếu thiết bị xuất chuẩn phải là đầu tiên (bất kỳ đầu ra thứ tự nào được tạo ra), chúng ta cần lưu trữ stderr để nối nó vào tệp ở cuối (giải pháp đầu tiên được đăng).
sponge
:(cmd | tee -a out >> out+err) 2>&1 | sponge >> out+err
Vì lợi ích của sự đa dạng:
Nếu hệ thống của bạn hỗ trợ /dev/stderr
, thì
(cmd | tee -a /dev/stderr) 2>> file1 >> file2
sẽ làm việc. Đầu ra tiêu chuẩn của cmd
được gửi đến cả thiết bị xuất chuẩn và thiết bị xuất chuẩn của đường ống. Các lỗi tiêu chuẩn của cmd
bỏ qua tee
và đi ra stderr của đường ống.
Vì thế
cmd
vàcmd
, xen kẽ.Đó là một vấn đề đơn giản để gửi các luồng đó đến các tệp chính xác.
Như với hầu hết mọi cách tiếp cận như thế này (bao gồm câu trả lời của Stéphane ),
file1
có thể khiến các dòng không theo thứ tự.
out+err
vàout
có nghĩa là ở đây. Tên tập tin? Luồng được chuyển hướng?