如何编写一个Bash脚本来设置全局环境变量?

64

最近我写了一个脚本来设置一个环境变量,看一下:

#!/bin/bash

echo "Pass a path:"
read path
echo $path

defaultPath=/home/$(whoami)/Desktop

if [ -n "$path" ]; then
    export my_var=$path
else
    echo "Path is empty! Exporting default path ..."
    export my_var=$defaultPath
fi

echo "Exported path: $my_var"

它完美地运作,但问题是my_var只能在本地环境(也就是我运行脚本的控制台窗口)中使用。

如何编写一个脚本,允许我导出可以在全局范围内看到的全局环境变量?


1
类似的问题已经被问过了。请参考https://dev59.com/knM_5IYBdhLWcg3wPAjT - Maciej
@Maciej指向的https://dev59.com/knM_5IYBdhLWcg3wPAjT帖子表明,您不应该**运行**修改环境变量的脚本;相反,您应该**source**它。下面和周围答案中显示的点**.**是`source`命令的别名。显然,不要将其与表示参数而不是命令的当前目录的点混淆。 - XavierStuvw
只是一个提示,你必须在 export my_var 和路径之间加上等号。我曾尝试在那里使用空格(可能是因为我学的是老派方法?或者那是另一种 shell 的语法?),只有当我用 = 替换空格时才能使其正常工作。谢谢! - skittlebiz
13个回答

162

只需在你的Shell脚本前加上"."(点空格)即可运行脚本。

这将导致脚本在原始Shell中运行指令。因此,变量在脚本执行结束后仍然存在。

例如:

cat setmyvar.sh
export myvar=exists

. ./setmyvar.sh

echo $myvar
exists

3
好的,我会尽力进行翻译。以下是翻译的内容:Bingo. 这解决了问题,即在调用 shell 中设置环境变量的问题。 - Tim Stewart
被接受的答案是由David W.提供的,为寻求更全面解释的人提供了更多的信息。将此注释添加到答案中可能会更好,但这应该足以指引那些匆忙的人朝着正确的方向前进。 - Fernando Cordeiro

58

每个 shell 都有自己的环境变量。没有一个“通用”的环境变量会自动出现在所有控制台窗口中。在一个 shell 中创建的环境变量不能在另一个 shell 中访问。

限制更多的是,如果一个 shell 生成一个子 shell,那么该子 shell 可以访问父 shell 的环境变量,但如果该子 shell 创建一个环境变量,则无法在父 shell 中访问它。

如果所有的 shell 都需要访问相同的变量集,你可以创建一个“启动”文件来为你设置这些变量。在 BASH 中,这是通过 $HOME/.bash_profile 文件(或者通过 $HOME/.profile 如果不存在 $HOME/.bash_profile)或通过 $HOME/.bashrc 完成的。其他 shell 也有它们自己的一组启动文件。一个用于登录,一个用于不带登录的 shell(就像 bash 一样,第三个用于非交互式 shell)。查看 manpage 以了解使用哪些启动脚本以及执行顺序。

你可以尝试使用共享内存,但我认为这仅在进程运行时有效,因此,即使你找到了一种设置共享内存的方法,只要该命令完成,共享内存就会消失。(除了命名管道,我很少使用共享内存)。否则,没有真正的方法可以在一个 shell 中设置环境变量,并使另一个 shell 自动接收它。你可以尝试使用命名管道或将该环境变量写入文件以供其他 shell 使用。

想象一下如果有人可以在我的不知情的情况下更改一个 shell 的环境会发生什么问题。


2
一个 shell 在没有知情和同意的情况下更改另一个 shell 确实是不好的。但是,原始问题虽然标题措辞不当,但是询问如何在“运行脚本”的控制台窗口中更改变量,即在其知情和同意下进行操作,这是合法且有用的。JDembinski 的回答展示了如何实现。 - Tim Stewart
2
可以使用系统范围的环境文件,例如 /etc/environment/etc/profile/etc/profile.d//etc/bash.bashrc。在我的情况下,我使用 /etc/environment 存储 cron 任务的变量。 - antonbormotov
1
这不应该是被接受的答案。它没有给出一个有用的回答,而JDembinski的回答则做到了。 - bravery
@bravery,我同意你的观点,但是这个答案涵盖了更多内容,并且包含了更深入的解释。在我看来,这两个答案互相补充。由于这个答案远比JDembinski的回答完整,我认为把所有的功劳都归给他是不公平的,尽管我很喜欢他的补充。 - Fernando Cordeiro

10

实际上我找到了一种方法来实现这个(在我的情况下是使用一个bash脚本来设置一些安全凭证)

我只需从脚本中调用bash,生成的shell现在具有输出值。

export API_USERNAME=abc
export API_PASSWORD=bbbb
bash

现在,使用~/.app-x-setup.sh调用该文件将为我设置这些环境变量并提供交互式shell。

4
你可以选择将其作为资源而非执行它。这样你就会得到一个嵌套的shell。 - grepsedawk

7
以下内容摘自David W.的答案第二段:“如果一个shell产生了一个子shell,那么子shell可以访问父shell的环境变量,但是如果这个子shell创建了一个环境变量,它在父shell中是不可访问的。”
如果用户需要让父shell访问您的新环境变量,请在父shell中输入以下命令:
source <your_subshell_script>

或者使用快捷方式
. <your_subshell_script>

即使没有人重视它,在我看来,这是对问题最好的解决方案。 - Michael Hecht

4

您需要在位于/home/$USER/.profile的.profile文件中添加变量。

您可以使用以下命令来完成:

echo 'TEST="hi"' >> $HOME/.profile

也可以使用emacs编辑文件来进行设置。 如果您想要为所有用户设置此变量,则必须编辑/etc/profile (root)


虽然很可爱,但根本不起作用 :( 我的意思是,这个:echo 'TEST="hi"' >> $HOME/.profile 不起作用 :/ - Katie

3

将其写入临时文件,例如 ~/.myglobalvar,并从任何地方读取

echo "$myglobal" > ~/.myglobalvar

3

实际上,在UNIX中不存在全局环境。

每个进程都有一个环境,最初是从父进程继承而来的,但在初始创建后,它是本地的。

你只能修改自己的环境,除非你使用调试器深入挖掘进程。


2

环境变量始终“本地”于进程执行,export命令允许为子进程设置环境变量。您可以查看.bashrc以在bash shell启动时设置环境变量。您正在尝试的似乎不可能实现,因为进程无法修改(或访问?)另一个进程的环境变量。


那么唯一的解决方案就是将 my_var 添加到 .bashrc 中吗?是否可以使用 bash 脚本来实现呢? - Katie
你可以在 .bashrc 文件中添加一行来源化一个文件,该文件将由脚本生成。 - Nahuel Fouilleul

1

~/.bin/SOURCED/lazy脚本用于将数据保存和加载为系统的平面文件。

[ ! -d ~/.megadata ] && mkdir ~/.megadata

function save_data {
[ -z "$1" -o -z "$2" ] && echo 'save_data [:id:] [:data:]' && return
local overwrite=${3-false}
[ "$overwrite" = 'true' ] && echo "$2" > ~/.megadata/$1 && return
[ ! -f ~/.megadata/$1 ]   && echo "$2" > ~/.megadata/$1 || echo ID TAKEN set third param to true to overwrite
}

save_data computer engine
cat ~/.megadata/computer
save_data computer engine
save_data computer megaengine true

function get_data {
[ -z "$1" -o -f $1 ] && echo 'get_data [:id:]' && return


[ -f ~/.megadata/$1 ]   && cat ~/.megadata/$1 || echo ID NOT FOUND
:
}

get_data computer
get_data computer

1

您可以更新 ~/.bashrc 或 ~/.bash_profile 文件,这些文件用于初始化环境。


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