bash 在 ~/.bashrc 中设置的变量并在 shellscript 中访问它们

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17219174/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 05:44:48  来源:igfitidea点击:

variables set in ~/.bashrc and accessing them in shellscript

bash

提问by Preexo

I have this at the very top of my .bashrc, beforethe return for non-interactive shells

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

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

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

I have a script test.sh in my homedirectory with this:

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

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

I execute test.sh. The output:

我执行 test.sh。输出:

A

B

2 Questions:

2 问题:

  • Why don't I see the value of $FOO?
  • Why don't I see the "HELLO WORLD"?
  • 为什么我看不到 $FOO 的值?
  • 为什么我看不到“你好世界”?

edit:I thought the script with #!/bin/bash triggers a subshell which will call the .bashrc again, am I that wrong?

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

edit:Even If I do call the script from another host I won't see any values. Not even then , the .bashrc will be executed???

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

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

采纳答案by chepner

.bashrcis only sourced automatically for non-login interactive shells. Often, you would put . .bashrcnear the beginning of your .bash_loginfile, to ensure that .bashrcis sourced for both login and non-login interactive shells.

.bashrc仅针对非登录交互式 shell 自动获取。通常,您会将文件放在. .bashrc靠近.bash_login文件开头的位置,以确保该文件.bashrc适用于登录和非登录交互式 shell。

.bashrcis not sourced automatically for non-interactive shells, such as those started when you execute a shell script.

.bashrc不会自动为非交互式 shell 提供源,例如在执行 shell 脚本时启动的那些。

Since you export FOOfrom .bashrc, the fact that test.shsees FOOhaving a null value tells me that you are running the script from a login shell. Does echo $FOOfrom the prompt print BAR? I would be surprised if it did and test.shdid not.

由于您FOO从导出.bashrc,因此test.sh看到FOO具有空值的事实告诉我您正在从登录外壳运行脚本。是否echo $FOO从提示打印BAR?如果它做了和test.sh没有,我会感到惊讶。

回答by chepner

When you logged in again, the bashrc was run in your new login shell, and the shell script inheritedthe variable from the login shell. That's what "environment variable" means: it's a variable that is passed to child processes.

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

Scripts do run in a separate process, but I wouldn't use the word "subshell" for those. I reserve that for things like ( cmd1 ; cmd2 )which creates a subshell to run the stuff in parentheses. Running a shell script causes a fresh execof the interpreter, which is an important difference as seen here:

脚本确实在一个单独的进程中运行,但我不会使用“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: /'

回答by hek2mgl

The answer is simple. Solution in the right order:

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

Why don't I see the "HELLO WORLD"?

为什么我看不到“你好世界”?

Note that the .bashrcwill not being parsed on every command or when starting a sub shell. It will only get parsed on a new shell. From the man page:

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

When an interactive shell that is not a login shell is started, bash reads and executes commands from /etc/bash.bashrc and ~/.bashrc, if these files exist.

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

So, I guess your .bashrcwon't get processed. Have you tried source ~/.bashrcbefore executing your script? Also you can just open a new terminal.

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

Why don't I see the value of $FOO?

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

If bashrcwill get parsed it would work as expected.

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



General advice: If you are using a variable in a shell command, like echo, use parentheses around the variable's name to make sure the content of the variable will not being treated as an shell option. So

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

echo $FOO

should be

应该

echo "$FOO"

回答by rectummelancolique

From my man bash:

从我的man bash

If the program is a file beginning with #!, the remainder of the first line specifies an interpreter for the program. The shell executes the specified interpreter on operating systems that do not handle this executable format themselves. The arguments to the interpreter consist of a single optional argument following the interpreter name on the first line of the program, followed by the name of the program, followed by the command arguments, if any.

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

So I guess a good lawyer could argue that bash can interpret bash and therefore does not execute another interpreter.

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