2012-08-06 86 views
29

我認爲它與父進程有關,創建新的子進程並沒有tty。任何人都可以解釋罩下的細節嗎?即bash的相關工作模型,過程創建等?什麼是「bash:在這個shell中沒有任何控制」意思?

它可能是一個非常廣泛的話題,所以指向帖子的鏈接也非常感謝。我Google搜索了一段時間,所有的結果都是關於非常具體的情況,沒有一個是關於背後的故事。現場提供更多的上下文,以下是得到的「慶典:在這個殼無作業控制」 shell腳本。

#! /bin/bash 

while [ 1 ]; do 
    st=$(netstat -an |grep 7070 |grep LISTEN -o | uniq) 
    if [ -z $st ]; then 
     echo "need to start proxy @$(date)" 
     bash -i -c "ssh -D 7070 -N [email protected] > /dev/null" 
    else 
     echo "proxy OK @$(date)" 
    fi 
    sleep 3 
done 

這行:

bash -i -c "ssh -D 7070 -N [email protected] > /dev/null"

就是「擊:這個殼無作業控制」從何而來。

+2

我無法從你的問題告訴你是否要在一般的外殼上作業控制信息,或解釋爲什麼在某些情況下工作控制不可用。 – kojiro 2012-08-06 00:46:49

+0

他們兩人:)它可能是一個非常廣泛的話題,所以指向職位的人也非常感激。我谷歌搜索了一段時間,所有的結果都是關於非常具體的情況,沒有一個是關於幕後的故事。 – luanjunyi 2012-08-06 03:39:32

+0

是否有你啓動一個新shell來啓動SSH的原因?從命令行運行你的腳本不會給我「無工作控制」,儘管它只是掛在SSH執行上,實際上它應該這樣做。所以從技術上講,「其他」不會被打到。你從哪裏運行這個腳本? crontab的? – favoretti 2012-08-06 06:54:34

回答

16

其中一種可能的選擇是不能訪問tty。

引擎蓋下:

  1. 慶典檢查會話是否是互動的,如果沒有 - 沒有工作 控制。
  2. 如果設置了forced_interactive,則檢查連接到tty的stderr是否爲 會被跳過,並且bash會再次檢查是否可以在 打開/dev/tty進行讀寫訪問。
  3. 然後它檢查是否使用了新的線條規則,如果沒有,則作業控制也被禁用。
  4. 如果(且僅當)我們只將過程組設置爲我們的PID,從而成爲過程組領導,並且終端與我們的(新)過程組不在同一過程組中,則設置終端的過程組到我們的(新)流程組。如果失敗,請將我們的過程組重新設置爲原來的狀態(以便我們仍可以從終端讀取)並關閉作業控制。
  5. 如果以上全部失敗,您會看到該消息。

我部分引用了bash源代碼中的註釋。

[編輯]

按照問題筆者的額外要求:

http://tiswww.case.edu/php/chet/bash/bashtop.html在這裏,你可以找到自己的bash。

如果您可以閱讀C代碼,請獲取源代碼壓縮包,在其中您會發現job.c - 這將爲您解釋更多「底層」的內容。 :)

19

作業控制是shell和tty驅動程序中的一組功能,它允許用戶從單個交互式shell管理多個作業。

作業是單個命令或管道。如果您運行ls,那是一份工作。如果您運行ls|more,那仍然只是一項工作。如果您運行的命令啓動它自己的子進程,那麼它們也將屬於同一個作業,除非它們被有意分離。

如果沒有作業控制,您可以通過將&添加到命令行中來將作業置於後臺。這就是你所有的控制。

作業控制,您還可以:

  1. 掛起正在運行的前臺作業與按Ctrlž
  2. 繼續在前臺掛起的作業與fg
  3. 繼續暫停作業與bg
  4. 的背景與帶來正在運行的後臺作業前景0

shell維護一個作業列表,通過運行jobs命令可以看到。每個人都被分配一個工作號(與構成工作的過程的PID不同)。您可以使用以%爲前綴的作業編號作爲參數fgbg以選擇作業爲前景或背景。 shell的內建kill命令也可以接受%jobnumber表示法。這可能很方便,因爲作業編號從1開始分配,所以它們比PID短。

也有快捷鍵%+爲先前前景化工作的最近前景化工作,%-,這樣你就可以來回切換迅速兩份工作按Ctrl之間,ž其次fg %-(暫停當前一個,恢復另一個),而不必記住數字。或者你可以使用命令本身的開始。如果您已暫停ffmpeg命令,則恢復該命令與fg %ff一樣簡單(假定沒有其他活動作業以「ff」開頭)。作爲最後一個捷徑,您不必輸入fg。只要輸入%-作爲一個命令前面的工作前景。

「但爲什麼我們需要這個?」我可以聽到你問。 「如果我想運行另一個命令,我可以啓動另一個shell。」誠然,有多種多任務處理方式。在正常的日子裏,我的登陸shell在tty1到tty10上運行(是的,超過6個,你只需要激活它們),其中一個將運行一個屏幕會話,其中4個屏幕,另一個可能有一個ssh運行在其上有另一個屏幕會話在遠程機器上運行,加上我的X會話有3或4個xterm。我仍然使用工作控制。

如果我在viless或​​或任何其他互動的東西中間,我需要運行其他幾個快捷命令來決定如何進行,按Ctrlž,運行命令,和fg是自然而快速的。 (在很多情況下,一個交互式程序有一個!鍵綁定爲你運行一個外部命令;我認爲這並不好,因爲你沒有得到shell的歷史,命令行編輯器和完成系統的好處。)當我看到有人啓動輔助xterm/screen /無論運行哪一個命令,看它兩秒鐘,然後退出時,我感到很傷心。

現在關於你的腳本。總的來說,它似乎沒有寫得很好。有問題的線路:

bash -i -c "ssh -D 7070 -N [email protected] > /dev/null" 

令人困惑。我無法弄清楚爲什麼ssh命令被傳遞到一個單獨的shell而不是直接從主腳本執行,更不用說爲什麼有人添加了-i-i選項告訴shell以交互方式運行,這會激活作業控制(等等)。但它並沒有真正被交互使用。無論背後單獨的殼和-i的目的是什麼,關於工作控制的警告是一個副作用。我猜測這是一個破解ssh的一些不受歡迎的功能的黑客。這是當你這樣做的時候,你應該評論它。

+0

謝謝@Alan。該腳本的目的是持續監視SSH隧道是否打開,如果沒有,則創建一個。我的瀏覽器使用這個隧道的襪子代理。我絕不是一個有能力的bash編碼器。整個腳本是通過嘗試錯誤構建的。我使用了'bash -i',希望啓動ssh命令是類似fork的,而不是exec,就像原來的監視過程停止了一樣。請糾正我一個更好的解決方案。目前這個腳本除了生成'無作業控制'消息外還可以正常工作。 – luanjunyi 2012-08-07 05:04:53

+1

當你在一行上只有ssh -D 7070 -N [email protected]>/dev/null'時,它做了什麼不同的操作(除了不打印「no job control warning」) ,沒有'bash -i -c'? – 2012-08-07 07:19:03

2

我在自己的嵌入式系統上遇到了一個問題,通過運行帶有「setsid」的getty進程來擺脫「無作業控制」錯誤,該進程根據其聯機幫助頁啓動具有新會話標識的進程。

問候, 海科

+3

我不認爲這真的回答了這個問題,至多這應該是一個評論。 – meskobalazs 2015-02-10 13:22:41

5

您可能需要啓用作業控制:

#! /bin/bash 
set -m