代码之家  ›  专栏  ›  技术社区  ›  Sander Marechal

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

  •  11
  • Sander Marechal  · 技术社区  · 14 年前

    我正在编写bash脚本,将输出从另一个命令重定向到正确的位置。基本上,当从shell/commandline调用脚本时,我希望将输出发送到STDOUT。但是,当bash脚本从其他应用程序(例如,另一个bash脚本、某个应用程序,或者在我的例子中从我的awesome窗口管理器中的awesome prompt插件)执行时,我想将输出重定向到其他地方。

    bash中有没有任何方法可以查看如何调用脚本?

    4 回复  |  直到 14 年前
        1
  •  23
  •   Dennis Williamson    14 年前

    试试这个:

    ps -o stat= -p $PPID
    

    如果结果包含“s”(小写),则它要么是从命令行运行,要么是从脚本中后台运行。要区分这两种情况:

    ps -o stat= -p $$
    

    将包含一个“+”如果它不是背景。

    这是一张桌子:

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

    其中,(&)表示子脚本是background,而&表示运行它的父脚本(即“script”所指的)是background。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 聚苯乙烯 是一个包含BSD功能的混合体。

        2
  •  8
  •   thkala jaxb    14 年前

    我相信你真正想知道的是stdout是否是一个终端。如果是这样,那么您可以(几乎)安全地假设它是一个交互式会话请尝试以下代码片段:

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

    这个 [[ -t 1 ]] 上面的命令检查文件描述符1(即stdout)是否是终端。

    编辑:

    请注意,如果您将输出管道传输到其他程序,这将指示非终端stdout。在这种情况下,您可能需要一个更通用的条件,该条件还将检查标准输入(文件描述符0):

    [[ -t 0 || -t 1 ]]
    
        3
  •  1
  •   Brian Mains    13 年前

    这是我从另一篇关于这个主题的文章中改编的一个函数。它将所有父进程与 $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
    }
    
        4
  •  -1
  •   laher    14 年前

    你可以用$PPID

    有点像

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

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

    然后,可以根据父元的值设置一些if语句。

    高温高压