繁体   English   中英

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

[英]Bash: Only allow script to run by being called from another script

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

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

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

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

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

sh ./startup.sh arg1 arg2 ...

要么

bash ./startup.sh arg1 arg2 ...

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

#!/bin/bash

有没有办法确保只能从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调用它, 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来“隐藏”它。 可能不会干扰这个脚本的操作(虽然我不能检查这个)。

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

正如答案开头所提到的,这不是任何形式的严肃安全措施,但我猜这不是你想要的东西。

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

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

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

ps $PPID | tail -1 | awk '$NF!~/parent/{exit 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

在这里这里查看这些链接以供参考。

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

你可以创建一个脚本,我们称之为check-if-my-env-set

#! /bin/bash

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

并通过该脚本替换startup.sh上的shebang (请参阅此内容

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

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

据我所知,没有办法以一种无法绕过它的方式来做到这一点。

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

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

sudo chown app_specific_user startup.sh

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

chmod u+x startup.sh

运行startup.sh作为app_specific_userStart-App.sh

sudo -u app_specific_user ./startup.sh

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM