.bashrc 中的 shopt -s extdebug 在脚本文件中不起作用

shopt -s extdebug in .bashrc not working in script files

我正在编写一个 bash 脚本 (echoo.sh),目的是在命令执行之前回显命令。我在 .bashrc 中获取了这个脚本 (echoo.sh)。但是它不会使用 bash shebang 执行脚本文件 (tmp.sh) 中的命令 运行。以下是我目前的代码

echoo.sh

#!/usr/bin/env bash
shopt -s extdebug; get_hacked () {
    [ -n "$COMP_LINE" ] && return  # not needed for completion
    [ "$BASH_COMMAND" = "$PROMPT_COMMAND" ] && return # not needed for prompt
    local this_command=$BASH_COMMAND;
    echo $this_command;
};
trap 'get_hacked' DEBUG

当我打开 shell 和 运行 任何命令时 - 它有效。但对于脚本文件中的内容,它不起作用。

一些进一步的尝试:

  1. 我尝试在脚本文件 (tmp.sh) 中获取 .bashrc 文件 - 没用。
  2. 我在 tmp.sh 中采购了 echoo.sh,它起作用了。

所以,我正在努力理解

  1. 如果我只是在 .bashrc 中为脚本中 运行s 的内容提供我的脚本,为什么它不起作用?
  2. 为什么在#2 有效时不进一步尝试#1。

最后,我该怎么做才能使我不必在所有脚本文件中获取 echoo.sh 源代码来使其工作。可以在一个地方获取我的脚本并更改一些设置,使其适用于所有场景。

I source this script (echoo.sh) inside .bashrc. But it does not execute for commands run in script file(tmp.sh) with the bash shebang

是的,不会,因为您正在以非交互方式调用 shell!

shell 可以交互式或非交互式生成。当 bash 作为交互式登录被调用时 shell 它首先从文件 /etc/profile 中读取并执行命令,如果该文件存在的话。读取该文件后,它会依次查找 ~/.bash_profile~/.bash_login~/.profile,并从第一个存在且可读的文件开始读取和执行命令。

当启动非登录 shell 的交互式 shell 时,bash~/.bashrc 读取并执行命令(如果该文件存在)。

当您 运行 带有解释器集的 shell 脚本时,它会打开一个新的非交互式子 shell 并且没有选项 -i 在 shell 选项中设置。

仔细观察 ~/.bashrc 你会发现一行字

# If not running interactively, don't do anything
[[ "$-" != *i* ]] && return

这意味着在您调用的脚本中,例如考虑下面的情况,我使用 -c 选项显式生成非交互式 shell,而 -x 只是为了启用调试模式

bash -cx 'source ~/.bashrc'
+ source /home/foobaruser/.bashrc
++ [[ hxBc != *i* ]]
++ return

这意味着 ~/.bashrc 的其余部分因为这个守卫而没有被执行。但是这里有一个这样的选项可以用来读取这种非交互式情况下的启动文件,如 BASH_ENV 环境变量所定义的那样。行为就像执行了这一行

if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi

您可以定义一个文件并将其值传递给本地环境变量

echo 'var=10' > non_interactive_startup_file
BASH_ENV=non_interactive_startup_file bash -x script.sh

或者完全 运行 你的 shell 脚本就像生成了一个交互式非登录 shell 一样。 运行 带有 -i 标志的脚本。重新使用上面的示例,现在传递 -i 标志,将获取 ~/.bashrc 文件。

bash -icx 'source ~/.bashrc'

您也可以在将 bash 中的解释器 she-bang 设置为 #!/bin/bash -i

时设置此选项

所以根据以上推论来回答你的问题,

  1. Why doesn't it work if I just source my script in .bashrc for stuff that runs in scripts?

不会,因为 ~/.bashrc 无法从非交互式启动的 shell 获得。通过将 -i 传递给脚本来绕过它,即 bash -i <script>

  1. Why doesn't further try #1 work when #2 does.

因为您完全依赖于阅读 ~/.bashrc。当您在 tmp.sh 中获取 echoo.sh 时,其所有 shell 配置都反映在 tmp.sh

启动的 shell 中