如何在Fish shell脚本中设置环境变量

4
在我的 fish shell 脚本 'hoge.fish' 中,我有一段设置环境变量的代码。
#!/usr/local/bin/fish
set -x HOGE "hello"

但是在我执行这个脚本之后,环境变量没有被正确设置,并且没有输出任何内容。
./hoge.fish
echo $HOGE

我尝试了这些代码,但都没有起作用。

set -gx HOGE "hello"
set -gU HOGE "hello"

我该怎么解决这个问题?

  • 操作系统:macOS High Sierra 10.13.6
  • fish 版本: 2.7.1
  • iTerm2 版本: 3.2.0

我运行了 ./hoge.fishecho $HOGE - Keke
请使用-Ux选项。 - Omar Alvarado
3个回答

5
当你运行脚本时,它可能正确地设置了环境变量,但只在你运行脚本时创建的进程中有效......而不是在你运行脚本的父会话中!当脚本退出时,进程及其环境将被销毁。
如果你想在当前环境中更改环境变量,取决于你使用的交互式 shell,你可以使用如下命令: source hoge.fish,它将在当前会话中执行命令而不是子进程,因此环境变量更改将持久存在。

谢谢您的回复。我正在尝试使用fish脚本制作cli,所以我计划将cp hoge.fish /usr/local/bin放在未来,并且我担心如何像source hoge.fish一样运行它?我想像命令一样使用它,例如,在终端中输入$ hoge。或者说通过脚本更改环境变量是不可能的吗? - Keke
不可能的。 - glenn jackman
这并不是不可能的,你只需要将其导出为全局而非全球性的:D,尝试使用-Ux选项。 - Omar Alvarado

1

虽然像原始答案中所述的source是正确的机制,但该答案的OP在评论中提到他们仍然更喜欢可以执行为脚本的解决方案。

只要在脚本中导出变量(set -x),就可以通过在脚本内部使用exec进入另一个fish shell来实现这个目标(但仍不建议这样做):

#!/usr/bin/env fish
set -gx HOGE hello
exec fish

执行./hoge.fish 将会启动一个带有HOGE的fish shell。
需要注意的是:
  • 这将导致两个fish shell进程同时运行,其中一个在另一个内部。第一个(父)是原始的fish shell。它将基于shebang行生成第二个(子)进程,然后被exec行替换为第三个实例。
  • 您可以通过使用exec ./hoge.fish来减少同时运行的shell数量。这将导致shebang脚本替换父进程,然后被脚本末尾的exec行替换。但是,为了实现简单的source所能做到的零附加启动,您仍需要运行fish的启动两次
  • 还要注意新shell的环境不一定与原shell的环境相同。特别是,来自原始shell的局部变量不会存在于exec的shell中。
在某些情况下,这些问题的解决方案值得使用exec来启动新的shell,但大多数情况下,简单的source将更受欢迎。

0
考虑到如果你在 bash shell 中运行它,它不会使用 -U 选项导出变量,因为它表示要导出到 "fish universe" 而非外部。
如果你仍然留在 fish 的 shell 中,你可以这样做:
#!/usr/local/bin/fish
set -Ux HOGE "hello"

这是结果:

Welcome to fish, the friendly interactive shell
Type help for instructions on how to use fish
~/trash $ ./hoge.fish
~/tr ash $ echo $HOGE
hello

请记得保留第一行,这样程序才能正确解释它。


虽然我非常喜欢fish的全局变量,但它们在这里真的不是正确的解决方案。 Fish中的全局变量将在所有运行的shell实例中更新,这可能会产生意想不到的副作用。 正确的方法是source文件,而不是像现有答案所示执行它。 这是一种标准的shell技术,不仅适用于fish,还适用于bash、zsh和大多数其他shell。 - NotTheDr01ds
我认为你是正确的,这是一个解决方法,因为全局变量和通用变量在一起工作时会发生冲突,可以参考此链接 https://github.com/fish-shell/fish-shell/pull/6218 - Omar Alvarado
1
正确 - 当您(a)确信值应该在任何地方相同,并且(b)了解可能与全局变量冲突的情况时,请使用通用变量(可以使用全局变量来正确覆盖通用变量,但如果您没有寻找全局/通用冲突,则可能会使调试问题更加困难)。对于这个特定的问题,我建议坚持使用被“source”的全局变量。 - NotTheDr01ds

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接