如何检测shell脚本是否从另一个shell脚本调用

7

有没有办法检测一个shell脚本是直接调用还是从另一个脚本中调用。

parent.sh

#/bin/bash
echo "parent script"
./child.sh

child.sh

#/bin/bash
echo -n "child script"
[ # if child script called from parent ] && \
    echo "called from parent" || \
    echo "called directly" 

结果

./parent.sh
# parent script
# child script called from parent

./child.sh
# child script called directly

你为什么想要这样做?聪明的系统管理员可以轻松编写一些小的C程序来包装内部shell脚本。 - Basile Starynkevitch
./child.sh 会将子脚本作为外部可执行文件运行,拥有自己的解释器,就像任何其他程序调用外部可执行文件一样。当然,你可以做一些丑陋而脆弱的事情,比如在进程树中查找父进程ID,但请再次参考丑陋和脆弱。 - Charles Duffy
1
如果你的真正目标是不同的,例如检测交互式调用与脚本调用,则有更好的方法可以做到这一点(例如,脚本调用通常不会具有TTY,除非该父脚本本身被用户调用)。同样,如果您想支持类似于非交互式批处理模式的东西,良好的形式是使切换明确,如果不是通过参数,则通过环境变量,可以选择在没有TTY的情况下自动启用。 - Charles Duffy
1个回答

4
你可以像这样使用child.sh:
#/bin/bash
echo "child script"

[[ $SHLVL -gt 2 ]] &&
  echo "called from parent" ||
  echo "called directly"

现在运行它:

# invoke it directly
./child.sh
child script 2
called directly

# call via parent.sh
./parent.sh
parent script
child script 3
called from parent

$SHLVL 在父 shell 中设置为 1,当您的脚本被另一个脚本调用时,将会被设置为大于 2(取决于嵌套层数)。


1
如果父Shell是zsh Shell,则无法工作。 - Basile Starynkevitch
2
嗯,是的,这是基于“bash”标签的。 - anubhava
2
不能保证交互式 shell 的 SHLVL 值为 1;它可能已经更高了。例如:我的外部 shell 的 SHLVL 值为 1,但我从 tmux 中执行实际工作,在其中它的值会从 2 开始。 - Charles Duffy
我没有使用tmux,因为我在OSX上使用iTerm,但我会看看是否可以安装它。 - anubhava

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接