【问题标题】:$0 doesn't work when I source a bash script当我获取 bash 脚本时,$0 不起作用
【发布时间】:2014-03-14 13:41:45
【问题描述】:

我有一个简单的脚本 test.sh

#!/bin/bash
echo $0

当我从 csh 终端运行以下命令时:

bash -c 'test.sh'

那么输出就是test.sh

但是当我跑步时:

bash -c 'source test.sh'

输出为bash

有人知道在这种情况下如何打印脚本名称吗?

【问题讨论】:

  • 您可以执行 ps -o "%a" -p "$$" 而不是 echo $0 之类的操作并解析输出,但不确定为什么您在获取文件时尝试具有相同的行为。
  • 当您调用一个全新的 shell 时,采购的目的是什么?
  • 我正在我的脚本中导出环境变量。我想从 csh 终端获取它,所以我运行: bash -c 'source test.sh;执行 csh'
  • 那行不通——当您使用bash 命令时,它会创建一个子进程,因此它定义的任何环境变量都不会成为调用脚本环境的一部分。 (顺便说一句,bash -c 'test.sh' 版本实际上创建了 两个 子进程。)本质上没有办法从 csh 获取 bash 脚本——source 的重点是它以相同的方式运行脚本shell(而不是子shell),而 bash 与 csh 不同。
  • 那么实现这一点的唯一方法就是在 c-shell 中重写脚本?

标签: bash csh


【解决方案1】:

当使用源代码运行脚本时,它在现有 shell 中运行,脚本创建或修改的任何变量在脚本完成后仍然可用。相反,如果脚本仅作为文件名运行,则将生成一个单独的子 shell(具有一组完全独立的变量)来运行脚本。

你也想修改shell脚本

这不起作用的原因与您不能使用子 shell 修改父 shell 的环境相同。子进程的环境是私有的,不能影响其父进程的环境。

完成您尝试的唯一方法可能是让 make 组合一个标准输出流,其中包含一个 shell 变量分配列表。然后可以将标准输出用作父“源”或“。”的输入。命令。使用诸如 make 之类的“嘈杂”程序来执行此操作将非常具有挑战性。

【讨论】:

    【解决方案2】:

    如果您试图从 csh 访问在 bash shell 脚本中定义的会话变量,则必须在启动 csh 之前调用 bash 脚本。

    一个会话被继承到子进程中,就像这样,一旦 csh '启动',csh.SESSION 和 csh.SESSION_INHERITED 就会合并:

    bash/
    ├── csh
    │   ├── SESSION
    │   └── SESSION_INHERITED
    └── SESSION
    

    无法从 csh shell 中访问 bash.SESSION,因为这会将 init 运行级别暴露给任何子进程。它是 fork,在生成期间会复制环境。

    因此,您可以从 bash 运行:source test.sh; csh。这会将 test.sh 的导出暴露给 csh - 但它是一个静态导出,不能在 csh 中以编程方式修改。

    因为它非常抽象,所以没有 100% 理解您的问题。但是希望这会有所帮助:)

    【讨论】:

      【解决方案3】:
      #!/bin/bash
      declare -r SCRIPT_NAME=$(readlink -f ${BASH_SOURCE[0]})
      

      【讨论】:

        【解决方案4】:

        使用 $BASH_SOURCE。从手册页:

        BASH_SOURCE
               An  array  variable whose members are the source filenames where
               the corresponding shell function names  in  the  FUNCNAME  array  
               variable  are  defined.   The  shell function ${FUNCNAME[$i]} is
               defined  in  the  file  ${BASH_SOURCE[$i]}   and   called   from   
               ${BASH_SOURCE[$i+1]}.
        

        您可以简单地引用 $BASH_SOURCE 而不是 ${BASH_SOURCE[0]},因为在没有索引的情况下取消引用 bash 中的数组变量会给您第一个元素。

        这是我的脚本中的一种常见模式,允许不同的行为进行采购和执行脚本:

        foo() {
            some cool function
        }
        
        if [[ "$BASH_SOURCE" == "$0" ]]; then
            # actually run it
            foo "$@"
        fi
        

        【讨论】:

          【解决方案5】:

          当您使用 source 或 . ,您在此 Shell 中运行脚本。您的脚本与 Shell 共享变量,包括 $0.当您运行 Shell 时,您输入了 'bash',因此 $0 是 bash,并且脚本使用它。这就是它显示 bash强文本 的原因。 如果您想要一个新的 $0,请改用 './script_name.sh'!

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-06-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多