Shell-Script

如何從 shell 腳本輸出中抑制 stdout / stderr?

  • September 20, 2018

我有一個腳本應該停止並恢復在後台執行的程序:

process_id=`ps -eaf | grep -i daemon | grep -v grep | grep -v status | grep -v stop | awk '{print $2}'`
(kill -STOP $process_id) &
... # do something else 
(kill -CONT $process_id) &

這工作正常,但隨後在 STDOUT / STDERR 中出現:

[1]  +  8545 Suspended (signal)            /etc/init.d/...

到目前為止,我試圖:

(kill -STOP $process_id)

(kill -STOP $process_id) & > /dev/null

/etc/init.d/{name_of_the_daemon} start > /dev/null

(kill -STOP $process_id & ) 2>/dev/null 

(kill -STOP $process_id & disown;) 2>/dev/null 

set +m
(kill -STOP $process_id) & 

(kill -STOP $process_id) & 1>&2

這些是我正在做的步驟:

  1. 在 fff 中創建一個文件/etc/init.d/
  2. 從下面粘貼腳本
  3. chmod 755 fff
  4. /etc/init.d/fff 啟動

之後,我收到“暫停”消息……

根據@sourcejedi,我的腳本不是守護程序;當腳本的子程序被掛起時,會出現“掛起”消息

如何僅針對該特定消息抑制 shell 的輸出?

這是我的腳本的一個非常簡單的版本:

#!/bin/bash

pid_script=`ps -eaf | grep -i fff | grep -v grep | grep -v status | grep -v stop | awk '{print $2}'`

case "$1" in
   start)
   ( sleep 3; kill -STOP $pid_script ) &
   sleep 10;
   (sleep 1; kill -CONT $pid_script) &
   ;;
   stop)
   for p in $pid_script # kill all the other processes related with this script (if any)
       do
           kill -9 $p
       done
esac

當您看到 時[1] + 7766 Suspended (signal) ...,這是 shell 列印的一條消息,告訴您它的一個子程序已暫停。

fff範例中,需要考慮兩個 shell 程序。您的初始互動式 shell,以及作為子程序執行的 shell 腳本。

您的腳本會自行暫停。“暫停”消息由互動式外殼列印。因此,這不是您可以在腳本內打開或關閉的選項。

此外,您無法在互動式 shell 中設置選項來打開或關閉此特定消息。無法單獨“抑制”此消息…基本上是因為這絕不是您想要做的:-)。

我認為fff腳本無論如何都不會成功恢復。我認為可以修改它來做到這一點。但是,恢復本身是一個糟糕的主意。當您暫停腳本時,互動式 shell 會再次顯示其命令提示符。即,如果您沒有看到“暫停”消息,那麼您的腳本似乎已經完成。但無論哪種方式,如果您的腳本設法自行恢復,它會嘗試從使用者那里奪回對終端的控制權,無論他們同時開始做什麼。不是很好!


我認為您需要了解,例如,如果您從終端啟動了一個程序並且它是互動式 shell 的子程序,那麼它絕對不是守護程序。

要從終端啟動守護程序,程序必須在啟動期間 fork() 本身。原始程序應該退出,這允許繼續重新父程序的程序,例如(在傳統的 unix 中)到 PID 1 akainit程序。它還必須包括更多步驟,以從終端分離。例如,請參見此處:在 shell 中守護程序?

此外,如果您的系統使用systemd,您需要了解/etc/init.d/需要開始使用遺留腳本systemctl start。Debian 和其他地方的打包init.d腳本包含一個兼容性黑客,可以為您執行此操作。但是您不應該使用該功能。這是混亂的秘訣。您編寫的腳本沒有此功能,因此您必須使用systemctl start fff.

我強烈建議不要嘗試將fff腳本中的遊戲與systemctl start.

實際上systemctl使用不同的方法來啟動後台服務程序。它向 PID 1(init 程序)發送一條消息systemd,然後 PID 1 啟動所請求的程序。如果你定義了一個原生的 systemd 服務,程序就不需要自己守護程序。如果您使用舊版init.d腳本,程序仍然需要自行守護程序,但它唯一實現的就是告訴systemd腳本init.d已完成啟動。(這使得在守護程序中註意到一些啟動失敗成為可能,但不幸的是,許多現有程序在守護程序之後可能會發生啟動失敗)。

您不想擔心是否以及如何systemdinit.d腳本停止和恢復自身做出反應。

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