我们有两个bash脚本来启动应用程序。第一个(Start-App.sh)设置环境,第二个(startup.sh)来自我们试图不进行大量编辑的第三方。如果有人在第一个脚本之前运行第二个脚本,则应用程序无法正确显示。
有没有办法确保只能从Start-App.sh脚本调用startup.sh?
它们都位于同一目录中,并通过Red Hat Linux上的bash运行。
答案 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)
[ $(basename "$0") = "Start-App.sh" ] || exit
与所有其他解决方案一样,它不是100%防弹,但这涵盖了我遇到的最常见的实例,用于防止意外地直接运行脚本而不是从另一个脚本调用它。
与其他方法不同,这种方法:
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
回顾一下:最直接的方法是在第二个脚本中添加至少一行或两行,这有望不算“重编辑”。
答案 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