当我获取 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键不起作用
当 cron 运行时,bash 脚本中的一个特定命令不起作用,所有其他命令都可以