Tại sao phải chuyển hướng đầu ra sang 2> & 1 và 1> & 2?


36

Tôi đã bắt gặp một số lệnh sử dụng 2>&11>&2, nhưng tôi hoàn toàn không thể hiểu được mục đích của việc sử dụng nó và khi nào tôi nên sử dụng nó.

Những gì tôi hiểu

Tôi biết rằng 1đại diện cho tiêu chuẩn ra và 2đại diện cho lỗi tiêu chuẩn. Tôi hiểu rằng 2>&1liên hợp gặt đập đầu ra của 2để 1và ngược lại.

Những gì tôi không nhận được

  1. Khi nào tôi nên sử dụng nó?
  2. Mục đích của nó là gì?

Câu trả lời:


39

Đôi khi bạn muốn chuyển hướng cả thiết bị xuất chuẩn thiết bị xuất chuẩn đến cùng một vị trí, Đây là khi >&được sử dụng - nó trỏ một mô tả tệp sang một mô tả khác.


Ví dụ, nếu bạn muốn viết cả stdout và stderr đến cùng một tập tin (có thể là /dev/nullhay output.txt), bạn có thể chuyển hướng một cách riêng biệt, với

app 1>/dev/null 2>/dev/null

hoặc bạn có thể chuyển hướng một bộ mô tả tệp sang tệp và bộ mô tả tệp khác vào tệp đầu tiên:

app 1>/dev/null 2>&1

app 2>/dev/null 1>&2

Trong ví dụ đầu tiên, 2>&1mô tả tập tin điểm # 2 đến nơi # 1 đã được trỏ. Ví dụ thứ hai đạt được điều tương tự, thay vào đó chỉ bắt đầu bằng stderr.

Một ví dụ khác, có những trường hợp khi thiết bị xuất chuẩn (mô tả tệp số 1) đã trỏ đến vị trí mong muốn, nhưng bạn không thể gọi nó theo tên (nó có thể được liên kết với một đường ống, ổ cắm hoặc như vậy). Điều này thường xảy ra khi sử dụng mở rộng quy trình ( ` `hoặc $( )toán tử), thông thường chỉ thu được thiết bị xuất chuẩn, nhưng bạn có thể muốn bao gồm thiết bị xuất chuẩn trong đó. Trong trường hợp này, bạn cũng sẽ sử dụng >&để trỏ stderr vào thiết bị xuất chuẩn:

out=$(app 2>&1)

Một ví dụ phổ biến khác là máy nhắn tin, hoặc grep, hoặc tiện ích tương tự, vì đường ống |thường chỉ hoạt động trên thiết bị xuất chuẩn, bạn sẽ chuyển hướng thiết bị xuất chuẩn sang thiết bị xuất chuẩn trước khi sử dụng đường ống:

app 2>&1 | grep hello

Làm thế nào để biết được các 2>&1hoặc 1>&2là có đúng không? Bộ mô tả tệp đã được thiết lập ở bên phải >&và bộ mô tả tệp bạn muốn chuyển hướng sang bên trái. ( 2>&1có nghĩa là "mô tả tập tin điểm # 2 đến mô tả tập tin số 1".)


Một số shell có các phím tắt cho các chuyển hướng phổ biến; đây là những ví dụ từ Bash:

  • 1> có thể rút ngắn lại chỉ >

  • 1>foo 2>&1đến >&foohoặc&>foo

  • 2>&1 | program đến |& program


Tôi không biết rằng làm như app 1>/dev/null 2>&1vậy có nghĩa là 2> & 1 sẽ trỏ đến tệp mà 1 đã chuyển hướng đến. Tôi có thể dễ dàng làm điều đó app > /dev/null &>?
PeanutsMonkey

Tôi đang có một thời gian khó hiểu the already set up fd goes to the right of >&, and the fd you want to redirect goes to the left. Bạn có ý nghĩa gì bởi bộ mô tả tập tin đã được thiết lập? Nó có nghĩa gì là quyền của?
PeanutsMonkey


Xin lỗi trừ khi bạn có ý định dạy tôi chỉ đường, tôi không tuân theo tuyên bố bạn đã nêu như đã lưu ý trước đó.
PeanutsMonkey

1
Lấy từng mô tả tệp chuyển hướng từng cái một, từ trái sang phải và áp dụng các quy tắc đó theo thứ tự đó. Nếu trước tiên bạn trực tiếp xuất ra một tệp, sau đó chuyển hướng stderr đến nơi mà thiết bị xuất chuẩn mà chúng ta hiện đang trỏ, thì stderr và stdout sẽ chuyển đến cùng một tệp. Nếu bạn hoán đổi hai chuyển hướng đó xung quanh, thì bạn sẽ nhận được các kết quả khác nhau (chuyển hướng stderr đến nơi thiết bị xuất chuẩn hiện tại , sau đó di chuyển thiết bị xuất chuẩn để trỏ đến một tệp khác, trong khi stderr tiếp tục nơi nó được chỉ vào).
Jason

2

Một tình huống khi bạn cần là khi bạn muốn hiển thị straceđầu ra trong máy nhắn tin. stracein đầu ra của nó thành lỗi tiêu chuẩn và đường ống thường kết nối đầu ra tiêu chuẩn với đầu vào tiêu chuẩn, do đó bạn phải sử dụng chuyển hướng:

strace -p $pid 2>&1 | less

Bạn có ý nghĩa pipes generally connect standard output to standard inputgì?
PeanutsMonkey

2
Ý tôi là pipe ( |) lấy đầu ra tiêu chuẩn của lệnh đầu tiên và kết nối nó với đầu vào tiêu chuẩn của lệnh thứ hai.
jpalecek

2

Đôi khi bạn muốn chuyển hướng cả stdout( 1) và stderr( 2) đến cùng một vị trí ( /dev/nullví dụ). Một cách để đạt được điều này sẽ là:

$ program 1>/dev/null 2>/dev/null

Nhưng hầu hết mọi người rút ngắn điều này bằng cách chuyển hướng stderrđến stdoutvới 2>&1:

$ program 1>/dev/null 2>&1

Một phiên bản thậm chí ngắn hơn là:

$ program >&- 2>&-

1

2: Đó là khi bạn sẽ có đầu ra đến từ cả lỗi tiêu chuẩn và lỗi tiêu chuẩn, và bạn muốn chúng được tổng hợp thành một chuỗi.

1: Khi bạn muốn thao tác đầu ra của cả lỗi tiêu chuẩn và lỗi tiêu chuẩn.


Bạn có ý nghĩa gì khi thao túng? Hiểu biết của tôi là bất cứ điều gì chuyển hướng đến>2 được gửi đến / dev / null. Hay tôi đã hoàn toàn hiểu sai?
PeanutsMonkey

Đó là không đúng. Bằng cách thao tác tôi có nghĩa là đường ống nó đến grep hoặc một cái gì đó tương tự. Xem ở đây cho một ví dụ.
soandos

0

Tôi sử dụng nó để bắt đầu một công việc tách ra:

someProgram 2>&1 >& my.log &

sau đó tôi có thể đăng xuất và someProgram vẫn sẽ chạy. Chức năng được cung cấp bởi GNU Screen, tmux và một số chương trình khác - nhưng ở đây nó đạt được mà không phụ thuộc bên ngoài.


1
Điều đó chỉ hoạt động miễn là không có SIGHUP gửi đến chương trình. Sử dụng tốt hơn nohuphoặc disowntrong những trường hợp như vậy.
slhck

@slhck: ok. Nhưng nếu tôi không gửi SIGHUP đến chương trình - sẽ không có ai, phải không?
Adobe

Không, thiết bị đầu cuối kiểm soát sẽ cảnh báo các quá trình đăng xuất bằng SIGHUP. Trong thực tế, nếu bạn chạy shell từ xa thông qua SSH và thoát, ví dụ, quy trình của bạn cũng sẽ chết.
slhck

@slhck: Không thể đúng: Tôi sử dụng nó trong một vài năm - Tôi đăng xuất khỏi ssh và quá trình vẫn đang chạy.
Adobe

Tôi sẽ phải tìm kiếm điều này chi tiết hơn, nhưng chỉ đưa các chương trình vào nền đã không làm việc cho tôi trong mọi trường hợp và nó chắc chắn không hoạt động trên máy cục bộ của tôi. Zsh và Bash cũng hành xử khác nhau ở đây.
slhck

0

Hãy tưởng tượng có một thư mục có tên trycó ba tệp này:file file1 and file2.

Bây giờ chạy lệnh này:

cat file file1 file2 file3

Ba tệp đầu tiên mở nhưng catsẽ xuất hiện lỗi trong khi mở tệp thứ tư vì nó không tồn tại.

Bây giờ chạy:

cat file file1 file2 file3 1>outfile 2>&1

Bạn sẽ không thấy bất kỳ kết quả trên màn hình: Thứ nhất 1>outfilesẽ chuyển hướng đầu ra của lệnh để outfilevà sau đó nó sẽ chuyển hướng ( 2>&1) lỗi ném khi cố gắng mở file3đểoutfile .

1>&2 hoạt động tương tự và chuyển hướng luồng lỗi đến đầu ra tiêu chuẩn.

Hi vọng điêu nay co ich!


0

Kịch bản thay thế: các lệnh đầu cuối hiển thị đầu ra vào một thiết bị đầu cuối khác

Sử dụng ttylệnh trong mỗi thiết bị đầu cuối để xác định chúng:

$ tty
/dev/pts/0

$ tty
/dev/pts/1

Giả sử các TTY này, để chuyển hướng thiết bị xuất chuẩn đầu tiên sang thiết bị thứ hai, hãy chạy cái này trong thiết bị đầu cuối đầu tiên:

exec 1>/dev/pts/1

Lưu ý: Bây giờ mọi đầu ra lệnh sẽ hiển thị trên pts / 1

Để khôi phục thiết bị xuất chuẩn mặc định của pts / 0:

exec 1>/dev/pts/0

Xem video này cho một cuộc biểu tình.


0

Trường hợp khi chuyển hướng stderr sang thiết bị xuất chuẩn đã được đề cập ở đây (ví dụ: sử dụng nó để lọc (grep) thông báo lỗi).

Trường hợp khác là chuyển hướng stdout sang stderr. Một usecase phổ biến (ít nhất là đối với tôi) là gửi các cảnh báo / thông báo lỗi được in bằng "echo" (trong shellscripts của tôi) đến stderr (để chúng có thể thu hút sự chú ý của người dùng dễ dàng hơn).

Ví dụ,

echo "file \"${file\" does not exist..." 1>&2
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.