当我获取 bash 脚本时,$0 不起作用

Posted

技术标签:

【中文标题】当我获取 bash 脚本时,$0 不起作用【英文标题】:$0 doesn't work when I source a bash script 【发布时间】: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 中重写脚本? 【参考方案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'!

【讨论】:

以上是关于当我获取 bash 脚本时,$0 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

使用内部 bash 脚本时 Inotifywait 不起作用

当我输入'vi .bash_profile'时,ESC键不起作用

为啥这个来自 python 的 bash 调用不起作用?

当 cron 运行时,bash 脚本中的一个特定命令不起作用,所有其他命令都可以

节点命令在 Windows 上的 git bash 终端中不起作用

PHP启动的Bash后台进程不起作用