bash - log - nohup 2 &1



在shell中,“2>&1”是什麼意思? (10)

重定向輸入

輸入的重定向會導致文件描述符n的文本描述符n將被打開以讀取字的擴展名,如果未指定n,則輸入標準輸入(文件描述符0)。

重定向輸入的一般格式是:

      [n]<word

重定向輸出

輸出的重定向會導致文件的名稱由單詞的擴展名開始寫入文件描述符n,如果未指定n,則標準輸出(文件描述符1)。 如果文件不存在,則創建該文件; 如果它確實存在,則它被截斷為零大小。

重定向輸出的一般格式是:

      [n]>word

移動文件描述符

移動文件描述符重定向操作符

      [n]<&digit-

如果未指定n,則將文件描述符數字移至文件描述符n或標準輸入(文件描述符0)。 數字複製到n後關閉。

同樣,重定向操作符

      [n]>&digit-

如果未指定n,則將文件描述符數字移動到文件描述符n或標準輸出(文件描述符1)。

參考:

man bash
鍵入/^REDIRECT以定位到redirection部分,了解更多..

在線版本在這裡:
http://www.gnu.org/software/bash/manual/bashref.html#Redirections

PS:

很多時候, man是學習linux的強大工具

https://code.i-harness.com

在Unix shell中,如果我想將stderrstdout組合到stdout流中進行進一步操作,我可以在命令結尾附加以下內容:

2>&1

所以,如果我想在g ++的輸出中使用“head”,我可以這樣做:

g++ lots_of_errors 2>&1 | head

所以我只能看到前幾個錯誤。

我總是無法記住這一點,而且我經常不得不去查看它,主要是因為我沒有完全理解這個特殊技巧的語法。 有人可以分解這個並且逐字解釋什麼是“2>&1”嗎?


關於重定向的一些技巧

關於這個的一些語法特性可能具有重要的行為。 有一些關於重定向, STDERRSTDOUT和參數排序的小樣本。

1 - 覆蓋或追加?

符號>意味著重定向

  • >表示將整個完整文件發送 ,覆蓋目標(如果存在)(請參閱#3後面的noclobber bash功能)。
  • >>意指如果存在,除了追加到目標外。

無論如何,如果文件不存在,文件將被創建。

2 - shell命令行依賴於順序!

為了測試這個,我們需要一個簡單的命令來發送兩個輸出

$ ls -ld /tmp /tnt
ls: cannot access /tnt: No such file or directory
drwxrwxrwt 118 root root 196608 Jan  7 11:49 /tmp

$ ls -ld /tmp /tnt >/dev/null
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt 2>/dev/null
drwxrwxrwt 118 root root 196608 Jan  7 11:49 /tmp

(當然,你沒有一個名為/tnt的目錄)。 那麼,我們有它!

所以讓我們看看:

$ ls -ld /tmp /tnt >/dev/null
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt >/dev/null 2>&1

$ ls -ld /tmp /tnt 2>&1 >/dev/null
ls: cannot access /tnt: No such file or directory

最後一個命令行將STDERR轉儲到控制台,它似乎不是預期的行為...但是...

如果您想對一個輸出進行一些後期過濾 ,則可以使用另一個或兩個輸入:

$ ls -ld /tmp /tnt | sed 's/^.*$/<-- & --->/'
ls: cannot access /tnt: No such file or directory
<-- drwxrwxrwt 118 root root 196608 Jan  7 12:02 /tmp --->

$ ls -ld /tmp /tnt 2>&1 | sed 's/^.*$/<-- & --->/'
<-- ls: cannot access /tnt: No such file or directory --->
<-- drwxrwxrwt 118 root root 196608 Jan  7 12:02 /tmp --->

$ ls -ld /tmp /tnt >/dev/null | sed 's/^.*$/<-- & --->/'
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt >/dev/null 2>&1 | sed 's/^.*$/<-- & --->/'

$ ls -ld /tmp /tnt 2>&1 >/dev/null | sed 's/^.*$/<-- & --->/'
<-- ls: cannot access /tnt: No such file or directory --->

請注意,本段中的最後一條命令行與之前的paraghaph中的命令行完全相同,在這裡我寫的看起來並不是預期的行為 (因此,這甚至可能是預期的行為)。

那麼有一些關於重定向的技巧, 在兩個輸出上做不同的操作

$ ( ls -ld /tmp /tnt | sed 's/^/O: /' >&9 ) 9>&2  2>&1  | sed 's/^/E: /'
O: drwxrwxrwt 118 root root 196608 Jan  7 12:13 /tmp
E: ls: cannot access /tnt: No such file or directory

注意: &9描述符會自發發生,因為) 9>&2

附錄:nota! 使用新版本的bash ( >4.0 ),有一個新功能和更具性感的語法來完成這種事情:

$ ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /')
O: drwxrwxrwt 17 root root 28672 Nov  5 23:00 /tmp
E: ls: cannot access /tnt: No such file or directory

最後是這樣的級聯輸出格式:

$ ((ls -ld /tmp /tnt |sed 's/^/O: /' >&9 ) 2>&1 |sed 's/^/E: /') 9>&1| cat -n
     1  O: drwxrwxrwt 118 root root 196608 Jan  7 12:29 /tmp
     2  E: ls: cannot access /tnt: No such file or directory

附錄:nota! 相同的新語法,兩種方式:

$ cat -n <(ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /'))
     1  O: drwxrwxrwt 17 root root 28672 Nov  5 23:00 /tmp
     2  E: ls: cannot access /tnt: No such file or directory

STDOUT通過一個特定的過濾器, STDERR到另一個,最後兩個輸出合併通過第三個命令過濾器。

3 - 關於noclobber選項和>| 句法

這是關於覆蓋

set -o noclobber指示bash 覆蓋任何現有文件, >| 語法讓你通過這個限制:

$ testfile=$(mktemp /tmp/testNoClobberDate-XXXXXX)

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:15 CET 2013

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:19 CET 2013

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:21 CET 2013

每次都會覆蓋文件,現在就是:

$ set -o noclobber

$ date > $testfile ; cat $testfile
bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
Mon Jan  7 13:18:21 CET 2013

$ date > $testfile ; cat $testfile
bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
Mon Jan  7 13:18:21 CET 2013

通過>|

$ date >| $testfile ; cat $testfile
Mon Jan  7 13:18:58 CET 2013

$ date >| $testfile ; cat $testfile
Mon Jan  7 13:19:01 CET 2013

取消設置此選項和/或詢問是否已設置。

$ set -o | grep noclobber
noclobber           on

$ set +o noclobber

$ set -o | grep noclobber
noclobber           off

$ date > $testfile ; cat $testfile
Mon Jan  7 13:24:27 CET 2013

$ rm $testfile

4 - 最後一招和更多...

為了重定向給定命令的輸出,我們看到正確的語法可能是:

$ ls -ld /tmp /tnt >/dev/null 2>&1

對於這種特殊情況,有一個快捷語法: &> ...或>&

$ ls -ld /tmp /tnt &>/dev/null 

$ ls -ld /tmp /tnt >&/dev/null 

注意:如果2>&1存在, 1>&2也是一個正確的語法:

$ ls -ld /tmp /tnt 2>/dev/null 1>&2

4b-現在,我會讓你考慮一下:

$ ls -ld /tmp /tnt 2>&1 1>&2  | sed -e s/^/++/
++/bin/ls: cannot access /tnt: No such file or directory
++drwxrwxrwt 193 root root 196608 Feb  9 11:08 /tmp/

$ ls -ld /tmp /tnt 1>&2 2>&1  | sed -e s/^/++/
/bin/ls: cannot access /tnt: No such file or directory
drwxrwxrwt 193 root root 196608 Feb  9 11:08 /tmp/

4c-如果您對更多信息感興趣

你可以點擊閱讀精細手冊:

man -Len -Pless\ +/^REDIRECTION bash

在bash控制台中;-)


2是控制台標準錯誤。

1是控制台標準輸出。

這是標準的Unix,Windows也遵循POSIX。 例如,當你跑步

perl test.pl 2>&1

標準錯誤被重定向到標準輸出,所以你可以看到兩個輸出在一起。

perl test.pl > debug.log 2>&1

執行後,您可以在debug.log中看到所有輸出,包括錯誤。

perl test.pl 1>out.log 2>err.log

然後標準輸出到out.log,標準錯誤到err.log。

我建議你試著去理解這些。


2>&1是一個POSIX shell構造。 這裡是一個細分,按令牌標記:

2 :“ 標準錯誤 ”輸出文件描述符。

>&複製輸出文件描述符運算符( 輸出重定向運算符>的變體)。 給定[x]>&[y] ,將由x表示的文件描述符設為輸出文件描述符y的副本。

1標準輸出 ”輸出文件描述符。

表達式2>&1文件描述符2>&1複製到位置2 ,因此執行環境中寫入2 (“標準錯誤”)的任何輸出將轉到原來由1 (“標準輸出”)描述的同一文件。

進一步解釋:

文件描述符 :“每進程唯一的非負整數,用於標識用於文件訪問目的的打開文件。”

標準輸出/錯誤 :請參閱shell文檔Redirection部分中的以下註釋:

打開的文件由從零開始的十進制數表示。 最大的可能值是實現定義的; 但是,所有實現應支持至少0到9(包含),供應用程序使用。 這些數字被稱為“文件描述符”。 值0,1和2具有特殊意義和常規用途,並且由某些重定向操作暗示; 它們分別被稱為標準輸入,標準輸出和標準錯誤。 程序通常從標準輸入中獲取輸入,並在標準輸出中寫入輸出。 錯誤消息通常寫在標準錯誤上。 重定向操作符可以在前面加上一個或多個數字(不允許插入字符)來指定文件描述符編號。


假設你的系統中不存在/foo ,並且/tmp確實......

$ ls -l /tmp /foo

將打印/tmp的內容並打印/foo的錯誤消息

$ ls -l /tmp /foo > /dev/null

會將/tmp的內容髮送到/dev/null並打印/foo的錯誤消息

$ ls -l /tmp /foo 1> /dev/null

將完全相同(注意1

$ ls -l /tmp /foo 2> /dev/null

將打印/tmp的內容並將錯誤消息發送到/dev/null

$ ls -l /tmp /foo 1> /dev/null 2> /dev/null

將發送列表以及錯誤消息到/dev/null

$ ls -l /tmp /foo > /dev/null 2> &1

是速記


從程序員的角度來看,這恰恰意味著:

dup2(1, 2);

查看手冊頁

理解2>&1副本也解釋了為什麼...

command >file 2>&1

...不一樣...

command 2>&1 >file

第一個會將兩個流發送到file ,而第二個會將錯誤發送到stdout ,並將普通輸出發送到file


數字指的是文件描述符(fd)。

  • 零是stdin
  • 一個是stdout
  • 兩個是stderr

2>&1將fd 2重定向到1。

這適用於任何數量的文件描述符,如果程序使用它們。

你可以看看/usr/include/unistd.h如果你忘了它們:

/* Standard file descriptors.  */
#define STDIN_FILENO    0   /* Standard input.  */
#define STDOUT_FILENO   1   /* Standard output.  */
#define STDERR_FILENO   2   /* Standard error output.  */

也就是說,我已經編寫了C工具,它們使用非標准文件描述符進行自定義日誌記錄,所以除非將其重定向到文件或其他東西,否則不會看到它。


文件描述符1是標準輸出(標準輸出)。
文件描述符2是標準錯誤(stderr)。

這裡有一種方法來記住這個構造(儘管它不完全準確):首先, 2>1可能看起來是將stderr重定向到stdout的一種好方法。 但是,它實際上會被解釋為“將stderr重定向到名為1的文件”。 &表示接下來是文件描述符而不是文件名。 所以構造變成: 2>&1


該構造將標準錯誤流( stderr )發送到標準輸出( stdout )的當前位置 - 此貨幣問題似乎被其他答案忽略了。

您可以使用此方法將任何輸出句柄重定向到另一個輸出句柄,但它通常用於將stdoutstderr流引導到單個流中進行處理。

一些例子是:

# Look for ERROR string in both stdout and stderr.
foo 2>&1 | grep ERROR

# Run the less pager without stderr screwing up the output.
foo 2>&1 | less

# Send stdout/err to file (with append) and terminal.
foo 2>&1 |tee /dev/tty >>outfile

# Send stderr to normal location and stdout to file.
foo >outfile1 2>&1 >outfile2

請注意,最後一個不會stderr指向outfile2它會將它重定向到參數遇到時的stdoutoutfile1 ), 然後stdout重定向到outfile2

這允許一些非常複雜的欺騙。


這就像將錯誤壓縮到標準輸出或終端一樣。 即。 cmd不是命令$ cmd 2> filename cat filename命令未找到

發送到文件的錯誤就像發送到終端的2>&1錯誤那樣





redirect