Làm cách nào để chuyển hướng và nối cả stdout và stderr vào một tệp với Bash?


1533

Để chuyển hướng thiết bị xuất chuẩn đến một tệp bị cắt bớt trong Bash, tôi biết sử dụng:

cmd > file.txt

Để chuyển hướng thiết bị xuất chuẩn trong Bash, nối thêm vào một tệp, tôi biết sử dụng:

cmd >> file.txt

Để chuyển hướng cả thiết bị xuất chuẩnthiết bị xuất chuẩn sang tệp bị cắt ngắn, tôi biết sử dụng:

cmd &> file.txt

Làm cách nào để chuyển hướng cả thiết bị xuất chuẩnthiết bị xuất chuẩn vào tệp? cmd &>> file.txtđã không làm việc cho tôi.


37
Tôi muốn lưu ý rằng &> outfile là mã cụ thể của Bash (và các loại khác) và không khả chuyển. Cách để di động (tương tự như các câu trả lời bổ sung) luôn luôn và vẫn là> outfile 2> & 1
TheBotto

Câu trả lời:


1999
cmd >>file.txt 2>&1

Bash thực hiện các chuyển hướng từ trái sang phải như sau:

  1. >>file.txt: Mở file.txttrong chế độ chắp thêm và chuyển hướng stdoutđến đó.
  2. 2>&1: Chuyển hướng stderrđến "nơi stdouthiện đang đi" . Trong trường hợp này, đó là một tệp được mở trong chế độ chắp thêm. Nói cách khác, việc &1sử dụng lại bộ mô tả tập tin stdouthiện đang sử dụng.

33
làm việc tuyệt vời Nhưng có cách nào để hiểu điều này hay tôi nên coi nó như một cấu trúc bash nguyên tử?
flybywire

181
Đó là các chuyển hướng đơn giản, các câu lệnh chuyển hướng được đánh giá, như mọi khi, từ trái sang phải. >> tập tin: Đỏ. STDOUT vào tệp (chế độ chắp thêm) (viết tắt của 1 >> tệp) 2> & 1: Đỏ. STDERR đến "nơi stdout đi" Lưu ý rằng cách diễn giải "chuyển hướng STDERR sang STDOUT" là sai.
TheBotto

31
Nó nói "nối đầu ra (stdout, mô tả tệp 1) vào file.txt và gửi stderr (mô tả tệp 2) đến cùng một nơi với fd1".
Tạm dừng cho đến khi có thông báo mới.

2
@TheBotto tuy nhiên nếu tôi cần chuyển hướng STDERR sang tệp khác nhưng đang nối thêm thì sao? điều này có thể không
arod

41
nếu bạn làm cmd >>file1 2>>file2nó sẽ đạt được những gì bạn muốn.
Woodrow Doulass

367

Có hai cách để làm điều này, tùy thuộc vào phiên bản Bash của bạn.

Cách cổ điển và di động ( Bash pre-4 ) là:

cmd >> outfile 2>&1

Một cách không thể truy cập, bắt đầu với Bash 4

cmd &>> outfile

(tương tự &> outfile)

Để có phong cách mã hóa tốt, bạn nên

  • quyết định xem tính di động là một mối quan tâm (sau đó sử dụng cách cổ điển)
  • quyết định xem tính di động ngay cả đối với Bash trước 4 có phải là một mối quan tâm không (sau đó sử dụng cách cổ điển)
  • bất kể bạn sử dụng cú pháp nào, không thay đổi nó trong cùng một tập lệnh (nhầm lẫn!)

Nếu tập lệnh của bạn đã bắt đầu bằng #!/bin/sh(cho dù có ý định hay không), thì giải pháp Bash 4 và nói chung bất kỳ mã cụ thể nào của Bash, không phải là cách để đi.

Cũng cần nhớ rằng Bash 4 &>>chỉ là cú pháp ngắn hơn - nó không giới thiệu bất kỳ chức năng mới hoặc bất cứ điều gì tương tự.

Cú pháp là (bên cạnh cú pháp chuyển hướng khác) được mô tả ở đây: http://bash-hackers.org/wiki/doku.php/syntax/redirection#appending_redirectedDefput_and_errorDefput


8
Tôi thích & >> vì nó phù hợp với &> và >>. Cũng dễ đọc 'nối thêm đầu ra và lỗi vào tệp này' hơn là 'gửi lỗi đến đầu ra, nối đầu ra vào tệp này'. Lưu ý trong khi Linux thường có phiên bản bash hiện tại, OS X, tại thời điểm viết, vẫn yêu cầu bash 4 để cài đặt thủ công qua homebrew, v.v.
mikemaccana

Tôi thích nó hơn vì nó ngắn hơn và chỉ có hai vị trí trên mỗi dòng, vậy ví dụ zsh sẽ tạo ra từ "& >>" gì?
Phillipp

Cũng cần lưu ý rằng, trong một công việc định kỳ, bạn phải sử dụng cú pháp trước 4, ngay cả khi hệ thống của bạn có Bash 4.
hyperjack

5
@zsero cron hoàn toàn không sử dụng bash ... nó sử dụng sh. Bạn có thể thay đổi vỏ mặc định bằng cách thêm vào trước SHELL=/bin/bashđể các crontab -etập tin.
Ray Foss

89

Trong Bash, bạn cũng có thể chỉ định rõ ràng các chuyển hướng của mình đến các tệp khác nhau:

cmd >log.out 2>log_error.out

Bổ sung sẽ là:

cmd >>log.out 2>>log_error.out

6
Chuyển hướng hai luồng vào cùng một tệp bằng tùy chọn đầu tiên của bạn sẽ khiến luồng đầu tiên ghi "trên đầu" của luồng thứ hai, ghi đè một số hoặc tất cả nội dung. Sử dụng cmd >> log.out 2> log.out thay thế.
Orestis P.

3
Cảm ơn vì đã bắt được điều đó; bạn nói đúng, người này sẽ đóng băng người kia. Tuy nhiên, lệnh của bạn cũng không hoạt động. Tôi nghĩ rằng cách duy nhất để ghi vào cùng một tệp là như đã được đưa ra trước đó cmd >log.out 2>&1. Tôi đang chỉnh sửa câu trả lời của mình để xóa ví dụ đầu tiên.
Aaron R.

65

Trong Bash 4 (cũng như ZSH 4.3.11):

cmd &>>outfile

vừa ra khỏi hộp


2
@all: đây là một câu trả lời hay, vì nó hoạt động với bash và ngắn gọn, vì vậy tôi đã chỉnh sửa để đảm bảo rằng nó đề cập đến bash một cách rõ ràng.
mikemaccana

10
@mikemaccana: Câu trả lời của TheBotto cho thấy giải pháp bash 4 kể từ năm 2009
jfs

52

Điều này sẽ hoạt động tốt:

your_command 2>&1 | tee -a file.txt

Nó sẽ lưu trữ tất cả các bản ghi trong file.txt cũng như kết xuất chúng trên thiết bị đầu cuối.


Đây là câu trả lời đúng nếu bạn cũng muốn xem đầu ra trong thiết bị đầu cuối. Tuy nhiên, đây không phải là câu hỏi ban đầu.
Mikko Rantalainen

25

Thử cái này

You_command 1>output.log  2>&1

Việc sử dụng &> x.file của bạn không hoạt động trong bash4. xin lỗi vì điều đó : (

Đây là một số lời khuyên bổ sung.

0, 1, 2 ... 9 là các mô tả tệp trong bash.

0 là viết tắt của stdin, 1 là viết tắt của stdout, 2 là viết tắt của stderror. 3 ~ 9 là phụ tùng cho bất kỳ việc sử dụng tạm thời khác.

Bất kỳ bộ mô tả tệp nào cũng có thể được chuyển hướng đến bộ mô tả tệp hoặc tệp khác bằng cách sử dụng toán tử >hoặc >>(chắp thêm).

Cách sử dụng: < file_descriptor > > < filename | & file_descriptor >

Vui lòng tham khảo http://www.tldp.org/LDP/abs/html/io-redirection.html


Ví dụ của bạn sẽ làm một cái gì đó khác với OP yêu cầu: Nó sẽ chuyển hướng You_commandthiết bị xuất chuẩn sang thiết bị xuất chuẩn và thiết bị xuất chuẩn của You_commandtệp output.log. Ngoài ra, nó sẽ không thêm vào tập tin nhưng nó sẽ ghi đè lên nó.
pabouk

Chính xác: Bộ mô tả tệp có thể là bất kỳ giá trị nào lớn hơn 3 cho tất cả các tệp khác.
Itachi

5
Câu trả lời của bạn hiển thị lỗi chuyển hướng đầu ra phổ biến nhất: chuyển hướng STDERR đến nơi STDOUT hiện đang trỏ và chỉ sau khi chuyển hướng STDOUT sang tệp. Điều này sẽ không khiến STDERR được chuyển hướng đến cùng một tệp. Thứ tự của các vấn đề chuyển hướng.
Jan Wikholm

1
điều đó có nghĩa là, trước tiên tôi nên chuyển hướng STDERROR sang STDOUT, sau đó chuyển hướng STDOUT sang một tệp. 1 > output.log 2>&1
Quintus.Zhou

1
@ Quintus.Zhou Yup. Phiên bản của bạn chuyển hướng lỗi ra ngoài, đồng thời ra tệp.
Alex Yaroshevich 8/03/2015

11

Tôi ngạc nhiên rằng trong gần mười năm, chưa có ai đăng tải phương pháp này:

Nếu sử dụng các phiên bản cũ hơn của bash nếu &>>không có sẵn, bạn cũng có thể làm:

(cmd 2>&1) >> file.txt

Bầy này một subshell, vì vậy nó là kém hiệu quả hơn so với phương pháp truyền thống của cmd >> file.txt 2>&1, và nó do đó sẽ không làm việc cho các lệnh đó cần phải sửa đổi vỏ hiện tại (ví dụ cd, pushd), nhưng phương pháp này cảm thấy tự nhiên hơn và dễ hiểu đối với tôi:

  1. Chuyển hướng stderr sang thiết bị xuất chuẩn.
  2. Chuyển hướng thiết bị xuất chuẩn mới bằng cách thêm vào một tệp.

Ngoài ra, các dấu ngoặc đơn loại bỏ bất kỳ sự mơ hồ nào về trật tự, đặc biệt nếu bạn muốn chuyển ống xuất chuẩn và thiết bị xuất chuẩn sang lệnh khác thay thế.


Việc thực hiện này gây ra một quá trình bổ sung cho hệ thống để chạy. Sử dụng cú pháp cmd >> file 2>&1hoạt động trong tất cả các shell và không cần thêm một quy trình để chạy.
Mikko Rantalainen

@MikkoRantalainen Tôi đã giải thích rằng nó sinh ra một subshell và kém hiệu quả hơn. Quan điểm của phương pháp này là nếu hiệu quả không phải là vấn đề lớn (và hiếm khi như vậy), thì cách này dễ nhớ hơn và khó hiểu hơn.
jamesdlin
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.