检查bash脚本是从shell还是其他脚本/应用程序调用

问题描述:

我正在编写一个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

试试这个它既可以从命令行运行,也可以从脚本中运行。将这两者区分开来:

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功能的混合体。

你可以使用$ PPID

喜欢的东西

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

这将设置父变量,父进程名称,然后将其打印到屏幕上。

然后,您可以把一些如果基于$父母的价值陈述

HTH

+0

我测试了这个,不管是直接运行它还是从其他* bash *脚本打印“bash” – ndemou 2016-01-11 08:12:28

我相信,你真的想知道什么是标准输出是一个终端或没有。如果是,那么你可以(几乎)安全地假设它是一个交互式会话。尝试下面的代码片断:

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 ]] 

这是我改编自另一篇关于这个话题的帖子。它将所有*过程的*过程与$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 
}