我正在编写一个bash脚本,用于将另一个命令的输出重定向到正确的位置。基本上,当从shell /命令行调用脚本时,我想将输出发送到STDOUT。但是,当bash脚本从其他应用程序(例如另一个bash脚本,某个应用程序,或者我的Awesome窗口管理器中的awesome-prompt插件)执行时,我想将输出重定向到其他地方。
bash中是否有任何方式可以查看脚本的调用方式?
答案 0 :(得分:20)
试试这个:
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
其中(&)表示子脚本背景和&表示运行它的父脚本(这是“脚本”所指的)是后台的。 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 :(得分:8)
我相信你真正想知道的是stdout是否是一个终端。如果是,那么你可以(几乎)安全地假设它是一个交互式会话。请尝试以下代码段:
if [[ -t 1 ]]; then
echo "Terminal"
else
echo "Not-a-terminal"
fi
上面的[[ -t 1 ]]
命令检查文件描述符1(即stdout)是否是终端。
编辑:
请注意,如果将输出传输到其他程序,这将指示非终端stdout。在这种情况下,您可能需要一个更通用的条件,它也将检查标准输入(文件描述符0):
[[ -t 0 || -t 1 ]]
答案 2 :(得分: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
}
答案 3 :(得分:-1)
您可以使用$ PPID
像
这样的东西 PARENT=`ps --no-heading -o %c -p $PPID`
echo $PARENT
这会将PARENT变量设置为父进程名称,然后将其打印到屏幕。
然后,您可以根据$ PARENT
的值放置一些if语句HTH