Contents

在.bashrc中包含其他文件

1. 概述

我们知道.bashrc 文件将在 Bash shell 交互启动时执行。

它初始化一个交互式 shell 会话。通常,.bashrc文件是放置别名和预定义函数的好地方

在这个快速教程中,让我们看看如何在*.bashrc*文件中包含其他文件。

2. 问题介绍

有时,为了更容易维护,我们可能希望将一些 Bash 设置或函数保存在单独的文件中,并将它们包含在*.bashrc*中。

但是,如果我们没有正确包含文件,这将失败。让我们看一个例子来快速理解问题。

2.1.附加脚本文件

假设我们有一个脚本文件additional_script.sh

$ cat /home/kent/bin/additional_script.sh
#!/bin/bash
echo "Loading the additional_script.sh file"
CONF_LOADED=true
alias lecho="echo 'Linux Rocks!'"
#function to print local times of 3 citites
function world_clock {
  echo "New York Time:" $(TZ="America/New_York" date +"%F %H:%M:%S")
  echo "Paris Time   :" $(TZ="Europe/Paris" date +"%F %H:%M:%S")
  echo "HongKong Time:" $(TZ="Asia/Hong_Kong" date +"%F %H:%M:%S")
}
echo "additional_script.sh loaded."

additional_script.sh文件中,我们定义了一个变量、一个别名和一个函数。

2.2. 尝试在*$HOME/.bashrc文件中包含additional_script.sh*

现在,让我们让additional_script.sh文件可执行并在*$HOME/.bashrc*文件中附加一行:

$ tail -1 ~/.bashrc
/home/kent/bin/additional_script.sh

接下来,让我们启动一个新的 Bash shell 并检查 Bash 是否包含了additional_script.sh文件:

$ bash
Loading the additional_script.sh file
additional_script.sh loaded.

我们已经看到了日志消息。似乎 Bash 已找到并包含该文件。伟大的!

让我们做一些测试来验证我们定义的变量、别名和函数是否按预期工作:

$ echo $CONF_LOADED
$ lecho
bash: lecho: command not found
$ world_clock
bash: world_clock: command not found

如上面的输出所示,它们都不起作用。

接下来,让我们弄清楚为什么会发生这种情况以及如何解决问题。

3. 在*$HOME/.bashrc文件中正确包含additional_script.sh*

我们已尝试 通过将脚本文件路径附加到 .bashrc文件来将additional_script.sh文件包含在*.bashrc*中。但它没有按预期工作。

当我们调用或包含另一个脚本文件时,这是一个很常见的陷阱。那么接下来,让我们弄清楚它为什么会发生。

3.1. 执行脚本和采购脚本的区别

当 Bash 看到文件名*/home/kent/bin/additional_script.sh*时,它将执行脚本。

此外,**当 Bash 执行一个脚本时,它会在一个新的 shell 进程中运行它。**这个新的 shell 进程是当前 shell 的子进程。因此,我们也可以将这个新的 shell 称为“子shell”。

如果执行的脚本产生输出,则输出将被复制回当前 shell。这就是我们看到日志消息的原因。

但是,如果脚本导致环境发生任何更改,例如更改变量或声明新的别名或函数,这些更改只会在子shell中生效。 在 Bash 执行完脚本后,子 shell 进程将被终止。因此,对子shell 的更改自然也会丢失。这就解释了为什么变量、新别名和函数在我们当前的 shell 中不起作用。

我们想要实现的是将这些对环境的更改应用到当前 shell。因此,*source *命令正是我们正在寻找的。

简单地说,与执行脚本不同,获取脚本将在当前 shell 中运行脚本中的命令。因此,对环境的所有更改都将在当前 shell 中生效

3.2. 使用source命令

我们可以使用两种形式中的任何一种来获取脚本:

source SCRIPT_FILE
. SCRIPT_FILE

两种形式的工作方式完全相同。在本教程中,我们将使用第一个。

现在,让我们使用 source命令修复*$HOME/.bashrc*文件中的问题:

$ tail -1 ~/.bashrc
source /home/kent/bin/additional_script.sh

接下来,让我们启动一个新的 Bash shell 并检查脚本文件是否正确包含:

$ bash
Loading the additional_script.sh file
additional_script.sh loaded.
$ echo $CONF_LOADED
true
$ lecho
Linux Rocks!
$ world_clock
New York Time: 2021-09-26 19:07:22
Paris Time   : 2021-09-27 01:07:22
HongKong Time: 2021-09-26 07:07:22

这一次,正如我们所见,不仅打印了日志消息,而且CONF_LOADED变量、  lecho别名和world_clock函数都已加载到当前 shell。 所以,我们已经解决了这个问题。

4. 错误处理和包含多个文件

到目前为止,我们已经学会了使用source命令在*.bashrc*中包含一个额外的脚本。

**在我们获取文件之前检查文件是否存在是一个很好的做法。**因此,我们可以这样改进 source命令:

if [ -f /home/kent/bin/additional_script.sh ]; 
then
    source /home/kent/bin/additional_script.sh
else
    echo "File Not Found: /home/kent/bin/additional_script.sh"
    # ... other error handlings
fi

此外,我们可能希望在*.bashrc*中包含多个文件。我们可以使用循环和数组来检查并包含它们,而不是多次复制“ if ”块:

files_to_source=("/path/to/script1" "/path/to/script2")
for file_to_source in ${files_to_source[@]}
do 
    if [ -f "$file_to_source" ];
    then
        source "$file_to_source"
        echo "Loaded $file_to_source"
    else
        echo "File Not Found: $file_to_source"
        # ... additional error handlings
    fi
done