Bash:只允许脚本通过从另一个脚本调用来运行

时间:2016-03-28 15:37:48

标签: linux bash shell sysadmin

我们有两个bash脚本来启动应用程序。第一个(Start-App.sh)设置环境,第二个(startup.sh)来自我们试图不进行大量编辑的第三方。如果有人在第一个脚本之前运行第二个脚本,则应用程序无法正确显示。

有没有办法确保只能从Start-App.sh脚本调用startup.sh?

它们都位于同一目录中,并通过Red Hat Linux上的bash运行。

8 个答案:

答案 0 :(得分:2)

您可以通过键入startup.sh使chmod -x startup.sh不可执行。这样,用户只需输入./startup.sh就无法运行它。

然后从Start-App.sh,通过显式调用shell来调用脚本:

sh ./startup.sh arg1 arg2 ...

bash ./startup.sh arg1 arg2 ...

您可以通过检查startup.sh的第一行来查看它应该运行的shell,它应该如下所示:

#!/bin/bash

答案 1 :(得分:2)

  

有没有办法确保只能从Start-App.sh脚本调用startup.sh?

确保?没有。如果没有在所有编辑startup.sh,那就更不用了。但你可以相当接近。

以下是三个建议 - 您可以使用其中一个,也可以使用它们的任意组合。

最简单,也可能是最好的方法是在startup.sh的顶部添加一行:

[ -z $CALLED_FROM_START_APP ] && { echo "Not called from Start-App.sh"; exit 42; }

然后从Start-App.sh调用它,如此:

export CALLED_FROM_START_APP=yes
sh startup.sh

当然,你可以自己设置这个环境变量,所以它实际上不会确保任何东西,但我希望你的工程人员足够成熟,不要这样做。

您还可以从startup.sh删除执行权限:

$ chmod a-x startup.sh

这将阻止人们使用sh startup.sh,因此这里有一个非常小的保证;但它可能会阻止自动完成oopsies,它会将文件标记为“不打算执行” - 如果我看到一个只有一个可执行.sh文件的目录,我会尝试运行那个一个,而不是其中一个。

最后,您可以重命名startup.sh脚本;例如,您可以将其重命名为do_not_run,或通过将其重命名为.startup来“隐藏”它。这个可能不会干扰这个脚本的操作(虽然我不能检查这个)。

答案 2 :(得分:2)

TL; DR:

[ $(basename "$0") = "Start-App.sh" ] || exit

解释

与所有其他解决方案一样,它不是100%防弹,但这涵盖了我遇到的最常见的实例,用于防止意外地直接运行脚本而不是从另一个脚本调用它。

与其他方法不同,这种方法:

  • 不依赖于为每个包含/源代码脚本手动设置文件名(即对文件名更改具有弹性)
  • 在所有使用bash附带的主要* nix发行版中表现一致
  • 没有引入不必要的环境变量
  • 不依赖于单个父脚本
  • 通过明确调用bash(例如bash myscript.sh
  • 来阻止运行脚本

基本思想是在脚本的顶部有这样的东西:

[ $(basename "$0") = $(basename "$BASH_SOURCE") ] && exit

$0返回执行链开头的脚本名称

$BASH_SOURCE将始终指向当前正在执行的代码所在的文件(如果没有文件,则为空,例如将文本直接传递给bash)

basename仅返回主文件名而没有任何目录信息(例如basename "/user/foo/example.sh"将返回example.sh)。这很重要,因此您不会因为比较example.sh./example.sh而导致误报。

要使其适应仅允许在问题中来自某个特定文件时运行,并向最终用户提供有用的错误消息,您可以使用:

[ $(basename "$0") = "Start-App.sh"  ] || echo "[ERROR] To start MyApplication please run ./Start-App.sh" && exit

正如答案开头所提到的,这不是一种严肃的安全措施,但我猜这不是你想要的。

答案 3 :(得分:1)

您可以在第一个脚本中设置环境变量,然后在运行第二个脚本之前检查是否正确设置了该环境变量。

答案 4 :(得分:1)

另一种方法是检查父进程并找到调用脚本。这还需要在第二个脚本中添加一些代码。

例如,在被调用的脚本中,您可以检查其退出状态并终止。

ps $PPID | tail -1 | awk '$NF!~/parent/{exit 1}'

答案 5 :(得分:1)

正如其他人所指出的,简短的回答是“不”,虽然你可以整天玩权限,但这仍然不是防弹的。既然你说你不介意编辑(只是没有大量编辑)第二个脚本,那么实现这个目标的最好方法就是:

1)在父/第一个脚本中,使用其PID导出环境变量。这成为父PID。例如,

# bash store parent pid
export FIRST_SCRIPT_PID = $$

2)然后非常简单地,在第二个脚本中,检查调用PID是否与已知的可接受父PID匹配。例如,

# confirm calling pid
if [ $PPID != $FIRST_SCRIPT_PID ] ; then
    exit 0
fi

查看这些链接herehere以供参考。

回顾一下:最直接的方法是在第二个脚本中添加至少一行或两行,这有望不算“重编辑”。

答案 6 :(得分:1)

您可以创建一个脚本,让我们将其称为check-if-my-env-set,其中包含

#! /bin/bash

source Start-App.sh
exec /bin/bash $@

并使用该脚本替换startup.sh上的 shebang (请参阅this

#! /abs/path/to/check-if-my-env-set
#! /bin/bash
...

然后,每次运行startup.sh时,确保正确设置了环境。

答案 7 :(得分:0)

据我所知,没有办法以不可能绕过它的方式这样做。

但是,您可以通过使用权限停止大多数尝试。

更改startup.sh文件的所有者:

sudo chown app_specific_user startup.sh

startup.sh只能由所有者执行:

chmod u+x startup.sh

startup.sh

运行app_specific_user作为Start-App.sh
sudo -u app_specific_user ./startup.sh