Bash

{ echo err >&2; 有什麼區別?回顯 >&1;} |:{ 回顯 >&1;迴聲錯誤>&2;} |: 在 bash 中?

  • November 11, 2022

為什麼命令{ echo err >&2; echo out >&1; } | :可以列印“err”,但第二個不能?

在容器中進行一些測試 debian:11.5(bash/5.1.4), rockylinux:9.0(bash/5.1.8), centos:7.7.1908(bash/4.2.46), centos:8.4.2105(bash/4.4.19) )。

這也發生在主機 centos 8.0.1905、debian 11.4 中。

root@f9e55b2b276a:~# { echo err >&2; echo out >&1; } | :
err
root@f9e55b2b276a:~# { echo out >&1; echo err >&2; } | :
root@f9e55b2b276a:~# 

並且不使用:似乎是正確的

root@f9e55b2b276a:~# { echo out >&1; echo err >&2; } | sed 's/.*/-&-/'
err
-out-
root@f9e55b2b276a:~# 

但在另一台主機 centos 7.7.1908(bash/4.2.46) 中列印

[root@test-1 ~]# { echo out >&1; echo err >&2; } | :
err
[root@test-1 ~]#

和…之間的不同

{ echo err >&2; echo out >&1; } | :

… 和

{ echo out >&1; echo err >&2; } | :

… 是進行兩次echo呼叫的順序。順序僅與第一個執行的速度有關。echo

管道的兩側{ ...; }:是同時啟動的,並且:不會從其標準輸入流中讀取。這意味著管道一旦:終止就會被拆除,這幾乎是立即的。

如果管道被拆除,則沒有echo out >&1可寫入的管道緩衝區。當echo嘗試寫入不存在的管道時,管道的左側因接收到 PIPE 信號而死。

如果它在執行之前死亡echo err >&2,則不會有輸出。

所以:

  • 您將始終得到err輸出,{ echo err >&2; echo out >&1; } | :因為echo err >&2不會關心管道的狀態。
  • 您有時會得到err輸出,{ echo out >&1; echo err >&2; } | : 這取決於之前是否:已終止echo out >&1有機會執行。如果:先終止,由於左側被過早地殺死,將沒有輸出。

我猜大多數人不會在大多數係統上體驗到第二個管道的非確定性行為。不過,您已經找到了顯示這一點的作業系統和 shell 版本的組合。我還在 FreeBSD 上複製了非確定性行為zsh,即使在單個 shell 會話中也是如此(儘管 shell 似乎傾向於一種行為而不是另一種,所以我需要 10 多次嘗試才能最終看到開關)。

引用自:https://unix.stackexchange.com/questions/724429