4

在返回非交互式 shell之前,我在 .bashrc 的最顶部有这个

FOO="BAR"; export FOO
echo "HELLO WORLD"

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

我的主目录中有一个脚本 test.sh:

#!/bin/bash
echo "A"
echo $FOO
echo "B"

我执行 test.sh。输出:

A

B

2个问题:

  • 为什么我看不到 $FOO 的价值?
  • 为什么我没有看到“HELLO WORLD”?

编辑:我认为带有 #!/bin/bash 的脚本会触发一个子shell,它将再次调用 .bashrc,我错了吗?

编辑:即使我确实从另一台主机调用脚本,我也不会看到任何值。即便如此,.bashrc 也会被执行???

ssh remotehost "/home/username/test.sh"
4

4 回答 4

4

.bashrc仅针对非登录交互式 shell 自动获取。通常,您会将文件放在文件. .bashrc的开头附近.bash_login,以确保它.bashrc来自登录和非登录交互式 shell。

.bashrc对于非交互式 shell,例如在执行 shell 脚本时启动的 shell,不会自动获取。

由于您 export FOOfrom ,因此看到具有 null 值.bashrc的事实告诉我您正在从登录 shell 运行脚本。是否从提示打印?如果它有和没有,我会感到惊讶。test.shFOOecho $FOOBARtest.sh

于 2013-06-20T18:46:38.623 回答
3

当您再次登录时,bashrc 在您的新登录 shell 中运行,并且 shell 脚本从登录 shell继承了变量。这就是“环境变量”的意思:它是一个传递给子进程的变量。

脚本确实在单独的进程中运行,但我不会使用“subshel​​l”这个词。我将其保留为诸如( cmd1 ; cmd2 )创建子shell以运行括号中的内容之类的东西。运行 shell 脚本会导致exec解释器的更新,这是一个重要的区别,如下所示:

x=foo # not exported
export y=bar

(
  # This subshell is a copy of the existing shell process, including the
  # non-exported variables, so x is still foo here.
  echo x is $x
  echo y is $y
  # But it's a copy, so modifications do not propagate to the parent.
  x=blah
  y=blah
) | sed 's/^/SUBSHELL: /'

# Back in the parent shell, x and y have not become blah.
echo PARENT: x is $x
echo PARENT: y is $y

# This is not a "subshell" but a new shell. It inherits the exported
# variable y, but not x. Running a shell script resembles this.
sh -c 'echo x is $x ; echo y is $y' | \
sed 's/^/NEWSHELL: /'
于 2013-06-21T08:55:02.367 回答
1

答案很简单。按正确顺序解决:

为什么我没有看到“HELLO WORLD”?

请注意,.bashrc不会在每个命令或启动子 shell 时解析。它只会在新的 shell 上被解析。从手册页:

当一个不是登录 shell 的交互式 shell 启动时,bash 会从 /etc/bash.bashrc 和 ~/.bashrc(如果这些文件存在)读取并执行命令。

所以,我想你.bashrc不会得到处理。您source ~/.bashrc在执行脚本之前尝试过吗?您也可以只打开一个新终端。

为什么我看不到 $FOO 的价值?

如果bashrc将被解析,它将按预期工作。


一般建议:如果您在 shell 命令中使用变量,例如echo,请在变量名称周围使用括号以确保变量的内容不会被视为 shell 选项。所以

echo $FOO

应该

echo "$FOO"
于 2013-06-20T16:48:49.443 回答
1

从我的man bash

如果程序是以#! 开头的文件,则第一行的其余部分指定程序的解释器。shell 在自己不处理这种可执行格式的操作系统上执行指定的解释器。解释器的参数由程序第一行解释器名称后面的单个可选参数组成,然后是程序名称,然后是命令参数(如果有)。

所以我想一个好的律师可能会争辩说 bash 可以解释 bash 因此不会执行另一个解释器。

于 2013-06-20T16:53:12.880 回答