bash - 判断shell脚本是否被执行 "sourcing"it

标签 bash shell

shell脚本是否可以通过source来测试它是否被执行过? ?也就是说,例如,

$ source myscript.sh
$ ./myscript.sh

myscript.sh 能否区分这些不同的 shell 环境?

最佳答案

我想,山姆想做的事,或许是不可能的。

半生不熟的解决方法在多大程度上是可能的,取决于......

  • ...用户的默认shell,以及
  • ...他们允许使用哪些替代 shell 。

  • 如果我正确理解 Sam 的要求,他想要一个“脚本”,myscript , 那是...
  • ...不能通过调用它的名称直接执行 myscript(即具有 chmod a-x );
  • ...不能通过调用 sh myscript 对用户间接执行或者
    调用 bash myscript
  • ... 只有如果被调用,则运行其包含的函数和命令
    采购它:. myscript

  • 首先要考虑的是这些
  • 直接通过脚本名称 ( myscript ) 调用脚本需要第一行
    脚本如 #!/bin/bash或类似。这将直接决定哪个
    bash 可执行文件(或符号链接(symbolic link))的已安装实例将被调用以运行
    脚本的内容。这将是一个新的 shell 进程。它需要
    脚本文件本身设置了可执行标志。
  • 通过使用脚本的(路径+)名称调用 shell 二进制文件来运行脚本
    参数 ( sh myscript ) 与“1”相同。 -- 除了
    可执行标志不需要设置,第一行用
    也不需要 hashbang
    .唯一需要的是调用
    用户需要对脚本文件的读取权限。
  • 通过获取其文件名 ( . myscript ) 来调用脚本非常适合
    与“1”相同。 -- 除了它不是一个被调用的新shell。一切
    脚本的命令在当前 shell
    中执行, 使用它的环境
    (并且还使用它可能设置的任何(新)变量“污染”其环境或
    改变。 (通常这是一件非常危险的事情:但在这里它可能是
    用于执行 exit $RETURNVALUE在某些条件下....)

  • 对于“1.”:
    轻松实现:chmod a-x myscript会阻止 myscript从存在
    直接可执行。但这不会满足要求“2”。和'3.'。

    对于“2”。和“3.”:
    更难达到。来自 sh myscript 的调用需要阅读
    文件的权限。所以一个明显的出路似乎是 chmod a-r myscript .但是,这也将禁止“3.”:您将无法
    源脚本。

    那么以一种使用 Bashism 的方式编写脚本呢?巴什主义是一种
    做其他 shell 不理解的事情的具体方法:使用
    特定的变量、命令等。这可以在脚本中使用
    发现这种情况并对其“做点什么”(例如“显示警告.txt”,
    “mailto admin”等)。但是在 hell 里没有办法阻止sh或者bash或任何其他 shell 读取并尝试执行以下所有操作
    写入脚本的命令/行,除非您通过调用杀死 shellexit .

    例子:在Bash中,脚本看到的环境知道$BASH ,$BASH_ARGV , $BASH_COMMAND , $BASH_SUBSHELL , BASH_EXECUTION_STRING ……如果
    sh 调用(如果来自 sh 内),正在执行的 shell 将看到
    所有这些$BASH_*作为空的环境变量。再次,这可以使用
    在脚本中发现这种情况并“做某事”......但不是
    防止调用以下命令!

    我现在假设...
  • ...脚本正在使用 #!/bin/bash作为第一行,
  • ...用户已将 Bash 设置为他们的 shell 并在
    下表来自 Bash,这是他们的登录 shell,
  • ... sh可用,它是指向 bash 的符号链接(symbolic link)或 dash .

  • 这意味着可以使用列出的值进行以下调用
    对于环境变量
    vars+invok's   | ./scriptname | sh scriptname | bash scriptname | . scriptname
    ---------------+--------------+---------------+-----------------+-------------
    $0             | ./scriptname | ./scriptname  | ./scriptname    | -bash
    $SHLVL         | 2            | 1             | 2               | 1
    $SHELLOPTS     | braceexpand: | (empty)       | braceexpand:..  | braceexpand:
    $BASH          | /bin/bash    | (empty)       | /bin/bash       | /bin/bash
    $BASH_ARGV     | (empty)      | (empty)       | (empty)         | scriptname
    $BASH_SUBSHELL | 0            | (empty)       | 0               | 0
    $SHELL         | /bin/bash    | /bin/bash     | /bin/bash       | /bin/bash
    $OPTARG        | (empty)      | (empty)       | (emtpy)         | (emtpy)
    

    Now you could put a logic into your text script:

    • If $0 is not equal to -bash, then do an exit $SOMERETURNVALUE.

    In case the script was called via sh myscript or bash myscript, then it will exit the calling shell. In case it was run in the current shell, it will continue to run. (Warning: in case the script has any other exit statements, your current shell will be 'killed'...)

    So put into your non-executable myscript.txt near its beginning something like this may do something close to your goal:

    echo BASH=$BASH
    test x${BASH} = x/bin/bash && echo "$? :    FINE.... You're using 'bash ...'"
    test x${BASH} = x/bin/bash || echo "$? :    RATS !!! -- You're not using BASH and I will kick you out!"
    test x${BASH} = x/bin/bash || exit 42
    test x"${0}" = x"-bash"    && echo "$? :    FINE.... You've sourced me, and I'm your login shell."
    test x"${0}" = x"-bash"    || echo "$? :    RATS !!! -- You've not sourced me (or I'm not your bash login shell) and I will kick you out!"
    test x"${0}" = x"-bash"    || exit 33
    

    关于bash - 判断shell脚本是否被执行 "sourcing"it,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3664225/

    相关文章:

    python - 解析访问日志数据以适合数据库格式

    linux - Sed - 按最后两个字符计算行数

    python - 在另一个脚本终止后运行 python 脚本

    linux - 将包含空格的字符串传递给脚本

    linux - 阻止 'cp' 从 bash 脚本输出文件名

    linux - LD_PRELOAD - shell 扩展问题

    linux - 有没有办法为 X 中生成的应用程序指定窗口偏移量?

    linux - 带有 flock 的简单 cron 无法在 Ubuntu 上运行

    bash - 在 Shell 模板脚本中使用 Terraform 字符串列表作为数组

    mysqldbcompare 失败,模式名称中包含 '-'