exec內建外殼(第一個細微差別)

exec內建外殼(第一個細微差別)

我試圖將程式(Steam)的所有輸出重定向到 /dev/null,這樣它就不會顯示在終端中。

這是我嘗試過的: steam & > /dev/null 2>/dev/nullsteam & > /dev/null 2>&1

兩者都不會抑制它的消息(據我所知。)

我的理解是 & 將進程與終端分離,並且 > 重定向輸入/輸出,預設/空白 > 是標準輸出,2> 是標準錯誤。還有比這兩個更多的輸出嗎?如果我將所有輸出都重定向掉,為什麼我仍然可以看到輸出?

答案1

嘗試:

steam 2>&1 > /dev/null &

2>&1將 stderr 重定向到 stdout,並將> /dev/nullstdout 重定向到/dev/null.

後台&進程放錯地方了。它必須位於該行的末尾。如果放置在之後steam但之前>,則不會steam重定向任何內容,儘管該進程將正確後台運行。

答案2

這個特殊問題steam恰好是一個特殊情況,有時需要一些特殊的理解和處理。運行steam時是一個包裝腳本,包含以下內容:

#!/bin/bash
# default to minimize on close, so we never have a running steam process
# in the background because of a broken Tray Icon on some desktops/WMs
#export STEAM_FRAME_FORCE_CLOSE=${STEAM_FRAME_FORCE_CLOSE:-0}
exec /usr/lib/steam/steam "$@"

請注意,它使用exec內建的 shell,並使用 傳遞所有參數$@

因此,雖然 shell 輸出重定向的常用解決方案類似於@Adobe 和@Gary 的回答,這種特殊類型的案件通常需要更細緻的方法並了解幕後發生的事情。為什麼所有可能的輸出重定向方法和操作順序steam有時不能按預期工作,有一些微妙之處。

exec內建外殼(第一個細微差別)

POSIX 標準定義了一種行為exec命令。 Bash 透過以下方式提供此功能exec外殼內置。這會影響標準 IO 重定向和子進程樹,這取決於它的呼叫方式。 筆記:雖然這在技術上並不適用於 OP 的特定用例和列出的命令,但我將其包含在這裡,因為這是一個需要注意的常見陷阱和警告。

來自 IEEE 標準。 1003.1,2004 年版:

exec 公用程式應按照作為命令一部分的任何重定向指定的方式開啟、關閉和/或複製檔案描述符。

如果在沒有命令或參數的情況下指定 exec,並且使用關聯的重定向語句開啟任何編號大於 2 的檔案描述符,則未指定當 shell 呼叫另一個實用程式時這些檔案描述符是否保持開啟狀態。擔心子 shell 可能濫用開啟的檔案描述符的腳本始終可以明確關閉它們,如以下範例之一所示。

如果用command指定exec,則用command取代shell,而不建立新進程。如果指定了參數,則它們應是命令的參數。重定向會影響目前的 shell 執行環境。

exec /usr/lib/steam/steam "$@"包裝器腳本中的行將替換/usr/bin/steam執行/bin/bashshell(按照“shebang 行”),而不創建新的子進程$@。 ,值得注意的是,傳入一些輸出重定向運算子作為參數(例如透過錯誤的引號"'透過eval轉義字元\)可能會提供將 shell 重定向運算子注入到腳本中的機會,這樣exec呼叫可能會影響標準。2>&1>somefile"$@"​的是要小心哪個bash 進程或子shell 正在評估這些參數。

Unix 輸出重新導向:stdin, stdout, &stderr

大多數UnixREPLshell 有類似的重定向方法標準IO流stdinstdout, 和stderr。這包括但不限於:POSIX sh、Bash、Z Shell zsh、Korn Shell ksh、C Shell csh、Dashdash等。

出於 OP 問題的目的,我們將僅關注 Bash,因為/usr/bin/steam包裝器腳本以 Bash 開頭“舍邦「 線:#!/bin/bash

在 Bash 中,前 3 個檔案描述符 ( fd's) 始終定義如下,索引從零開始0

  • stdin=fd 0
  • stdout=fd 1
  • stderr=fd 2

任何命令的輸出都可以使用重定向Bash 中的輸出重定向運算子(Bash 參考手冊:§ 3.6 重定向)。對此的基本介紹可以在這篇文章中找到:Bash 重定向與描述符的樂趣。為了透過視覺輔助工具獲得更直觀的解釋,請參閱這篇優秀文章(強烈推薦!

操作順序(第二個細微差別):

以下各項之間存在微妙的操作順序:

  • 重定向運算符><>><<&>&>>X<&YX>&YX>|YX<&Y-X<>Y, ETC...)

……以及:

來自Bash 參考手冊 § 3.6 重定向

重定向按照它們出現的順序從左到右進行處理。

[...剪...]

請注意,重定向的順序很重要。例如,命令

ls > dirlist 2>&1

將標準輸出(檔案描述符 1)和標準錯誤(檔案描述符 2)定向到檔案目錄列表,而命令

ls 2>&1 > dirlist

僅將標準輸出定向到檔案 dirlist,因為在標準輸出重定向到 dirlist 之前,標準錯誤是標準輸出的副本。

&類似地,和 其他控制操作符也有操作順序。

來自Bash 參考手冊:2.4 指令列表

清單是由運算子 ' ;'、' &'、' &&' 或 ' ' 之一分隔的一個或多個管道的序列,並且可以選擇以 ' '、' ' 或 '||之一終止。;&newline

在這些列表運算符中,“ &&”和“ ||”具有相同的優先級,其次是“ ;”和“ &”,它們具有相同的優先權。

一系列的一個或多個換行符號可能出現在list分隔命令中,相當於分號。

最後,特別是關於以下內容的部分&

如果命令由控制運算子「&」終止,則 shell 會在子 shell 中非同步執行該命令。這稱為執行命令背景,這些被稱為非同步命令。 shell 不等待指令完成,回傳狀態為0( true)。當作業控制未啟動時(參見作業控制),非同步指令的標準輸入,在沒有任何明確重定向的情況下,從 重定向/dev/null

為什麼OP的指令沒有達到預期的效果

嘗試的前兩個命令是:

  • steam & > /dev/null 2>/dev/null
  • steam & > /dev/null 2>&1

這些沒有執行預期的重新導向stdoutstderr預期的原因是由於上述原因運算順序/運算符優先級上面列出的規則。具體來說,&運算符按從左到右的順序首先出現。它應用於第一個單詞,即命令steam,並將其發送到後台運行非同步命令stdin連接到/dev/null,同時stdout,並stderr保持連接到控制偽終端 /pty。這將在下面進一步解釋。

但首先...

更多連鎖exec混亂!

相關內容