2010-11-23 136 views
8

我正在編寫一個bash腳本以將輸出從另一個命令重定向到正確的位置。基本上,當從shell /命令行調用腳本時,我想將輸出發送到STDOUT。但是,當bash腳本從其他應用程序(例如另一個bash腳本,某些應用程序或我的Awesome Window Manager中的awesome-prompt插件)執行時,我想將輸出重定向到其他位置。檢查bash腳本是從shell還是其他腳本/應用程序調用

在bash中有什麼方法可以查看腳本是如何被調用的?

+1

查看它的另一種方法是,爲什麼不使用管道輸出本身的包裝腳本?所以,真棒窗口管理器調用script-wrapper.sh,這包含行「./script.sh >> awesome.log」 – laher 2010-11-23 23:22:03

+1

作爲shell腳本的用戶,我更喜歡當腳本不要太聰明。如果我想在一個文件中輸出,我完全有能力把它放在一個文件中。爲腳本提供封裝或標誌以將輸出發送到文件(例如`-o filename`)將是理想的 - 容易,但明確。 – 2010-11-24 16:50:18

+0

好點,但我希望這很簡單。有問題的命令是Taskwarrior。我只想輸入'task add blah blah`,不用擔心輸入的地方。如果我需要每次輸入一系列重定向或選項,我不會使用它,因爲它不夠方便。 – 2010-11-26 00:53:56

回答

16

試試這個它既可以從命令行運行,也可以從腳本中運行。將這兩者區分開來:

ps -o stat= -p $$ 

如果沒有背景,將包含「+」。

這裏有一個表:

Run   $$ $PPID 
CL   S+ Ss 
CL&   S  Ss+ 
Script  S+ S+ 
Script&  S  S 
Script(&) S  Ss 
Script&(&) S  NULL 

凡(&)意味着子腳本中背景和&意味着父腳本(這是「腳本」指)跑它轉到後臺運行。 CL表示命令行。 NULL意味着ps輸出一個null,並且$PPID是「1」。

man ps

s is a session leader 
    + is in the foreground process group 

應當注意的是,這個答案是基於GNU ps,但該男子頁BSD(包括OS X)表示了類似的功能。 GNU ps是一個包含BSD功能的混合體。

-1

你可以使用$ PPID

喜歡的東西

PARENT=`ps --no-heading -o %c -p $PPID` 
    echo $PARENT 

這將設置父變量,父進程名稱,然後將其打印到屏幕上。

然後,您可以把一些如果基於$父母的價值陳述

HTH

+0

我測試了這個,不管是直接運行它還是從其他* bash *腳本打印「bash」 – ndemou 2016-01-11 08:12:28

7

我相信,你真的想知道什麼是標準輸出是一個終端或沒有。如果是,那麼你可以(幾乎)安全地假設它是一個交互式會話。嘗試下面的代碼片斷:

if [[ -t 1 ]]; then 
     echo "Terminal" 
else 
     echo "Not-a-terminal" 
fi 

上述[[ -t 1 ]]命令是什麼檢查,如果文件描述符1(即標準輸出)是終端或沒有。

編輯:

請注意,這將表明一個非終端的標準輸出,如果您管道輸出到其他程序。如果結果中含有「S」

ps -o stat= -p $PPID 

(小寫):在這種情況下,你可能需要一個更靈活的條件,也將檢查標準輸入(文件描述符0):

[[ -t 0 || -t 1 ]] 
1

這是我改編自另一篇關於這個話題的帖子。它將所有頂級過程的頂級過程與$shells變量中列出的項目進行匹配。完成後$iscli被設置爲0或1.如果它被設置爲0,那麼你知道它是從shell運行的,或者你認爲shell足夠用於此目的。如果它設置爲1,那麼你知道有一個程序涉及到未被批准。我使用這個腳本來運行在shell和PHP中,當我想要爲每個腳本提供不同的輸出時。

在您需要$iscli以獲得一個值之前,您當然需要先不帶任何參數調用該函數。

function top_level_parent_pid { 

    scriptname="${0##*/}" 
    shells="^bash|^init|^screen|^sh|^ssh|^su|${scriptname}" 

    pid=${1:-$$} 
    pidname="`ps --no-heading -o %c -p ${pid}`" 
    stat=($(</proc/${pid}/stat)) 
    ppid=${stat[3]} 
    ppidname="`ps --no-heading -o %c -p ${ppid}`" 
    isclitest="`echo "${ppidname}" | grep -iv -E "${shells}"`" 

    until [ "${ppid}" -eq "1" ] || [ "${iscli}" = "1" ]; do 

      if [[ -n "${isclitest}" ]]; then 

        iscli="1" 

       else 

        iscli="0" 


        top_level_parent_pid ${ppid} 
      fi 
    done 
}