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

Posted

技术标签:

【中文标题】如何编写 bash 脚本来设置全局环境变量?【英文标题】:How to write a bash script to set global environment variable? 【发布时间】:2012-09-03 07:41:28 【问题描述】:

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

#!/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 仅在本地可用,我的意思是在我运行脚本的控制台窗口中。

如何编写一个脚本来导出随处可见的全局环境变量?

【问题讨论】:

已提出类似问题。见***.com/questions/1464253/… @Maciej 所指的***.com/questions/1464253/… 帖子表明您没有运行 修改环境变量的脚本;您改为 source 它。下面和周围的答案中显示的点 .source 命令的别名。显然,不要与当前目录的点混淆,它表示参数而不是命令。 请注意,export my_var 和路径之间必须有等号。我正在尝试在那里使用空格(也许是老学校教我的?或者这可能是另一个 shell 的语法?),只有当我用 =Thanks 替换空格后它才能工作! 【参考方案1】:

只需运行前面带有“.”(点空格)的 shell 脚本。

这会导致脚本在原始 shell 中运行指令。因此脚本完成后变量仍然存在

例如:

cat setmyvar.sh
export myvar=exists

. ./setmyvar.sh

echo $myvar
exists

【讨论】:

宾果游戏。这解决了问题中描述的问题(在调用shell中设置环境变量)。 但是,问题中提到了global,而这并不是……【参考方案2】:

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

它更加严格。如果一个 shell 生成一个子 shell,则该子 shell 可以访问父 shell 的环境变量,但如果该子 shell 创建了一个环境变量,则无法在父 shell 中访问它。

如果您的所有 shell 都需要访问同一组变量,您可以创建一个 startup 文件来为您设置它们。这在 BASH 中通过 $HOME/.bash_profile 文件(如果 $HOME/.bash_profile 不存在,则通过 $HOME/.profile)或通过 $HOME/.bashrc 完成。其他 shell 有自己的一组启动文件。一种用于登录,一种用于在没有登录的情况下生成的 shell(和 bash 一样,第三种用于非交互式 shell)。请参阅手册页以准确了解使用了哪些启动脚本以及它们的执行顺序)。

您可以尝试使用共享内存,但我相信只有在进程运行时才有效,因此即使您找到了设置共享内存的方法,它也会在该命令完成后立即消失。 (除了命名管道,我很少使用共享内存)。否则,真的没有办法在一个 shell 中设置环境变量并让另一个 shell 自动拾取它。您可以尝试使用named pipes 或将该环境变量写入文件以供其他shell 获取。

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

【讨论】:

一个外壳在不知情或不同意的情况下更改另一个外壳确实很糟糕。但是最初的问题虽然标题措辞不好,但询问如何更改控制台窗口中“运行脚本”的变量,即在其知情和同意的情况下,这是合法且有用的。 JDembinski 的回答说明了如何。 可以使用系统范围的环境文件,例如/etc/environment/etc/profile/etc/profile.d//etc/bash.bashrc。就我而言,我使用/etc/environment 来存储cron 任务的变量。 这不应该是公认的答案。它没有用有用的答案解决问题,而 JDembinski 的答案却可以。【参考方案3】:

实际上我找到了一种方法来实现这一点(在我的例子中是使用 bash 脚本来设置一些安全凭证)

我只是从脚本内部调用 bash,然后生成的 shell 现在具有导出值

export API_USERNAME=abc
export API_PASSWORD=bbbb
bash

现在使用 ~/.app-x-setup.sh 调用该文件将为我提供一个带有这些环境值设置的交互式 shell

【讨论】:

或者你可以直接获取它而不是执行它。现在你有了一个嵌套的 shell。【参考方案4】:

您必须在位于 /home/$USER/.profile 的 .profile 中添加变量

你可以用这个命令做到这一点:

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

例如,或者通过使用 emacs 编辑文件。 如果你想为所有用户设置这个变量,你必须编辑 /etc/profile (root)

【讨论】:

它会很可爱,但它根本不起作用:(我的意思是,这个:echo 'TEST="hi"' >> $HOME/.profile 不起作用:/【参考方案5】:

在 UNIX 中确实没有全局环境。

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

您只能修改自己的,除非您使用调试器在过程中进行挖掘。

【讨论】:

【参考方案6】:

以下内容摘自 David W. 回答的第 2 段:“如果一个 shell 生成一个子 shell,则该子 shell 可以访问父 shell 的环境变量,但如果该子 shell 创建了一个环境变量,则它在父壳。”

如果用户需要让父 shell 访问您的新环境变量,只需在父 shell 中发出以下命令:

source <your_subshell_script>

或使用快捷方式

. <your_subshell_script>

【讨论】:

【参考方案7】:

将它写入一个临时文件,比如说 ~/.myglobalvar 并从任何地方读取它

echo "$myglobal" > ~/.myglobalvar

【讨论】:

【参考方案8】:

环境变量对于进程执行总是“本地”的,导出命令允许为子进程设置环境变量。您可以查看 .bashrc 以在 bash shell 的开头设置环境变量。您尝试做的事情似乎不可能,因为一个进程无法修改(或访问?)另一个进程的环境变量。

【讨论】:

所以唯一的解决办法就是在.bashrc中添加my_var?是否可以使用 bash 脚本来实现? 您可以在 .bashrc 中添加一行来获取将由脚本生成的文件【参考方案9】:

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

【讨论】:

【参考方案10】:

看看你的 shell 的加载行为(在手册页中有解释,通常是指 .XXXshrc 或 .profile)。一些配置文件在交互式 shell 的登录时加载,一些配置文件在每次运行 shell 时加载。将变量放在后者中可能会导致您想要的行为,例如始终使用该不同的 shell(例如 bash)设置变量。

【讨论】:

【参考方案11】:

如果您需要在 shell 脚本中动态设置和引用环境变量,有一种变通方法。自己判断是否值得做,但在这里。

该策略涉及使用“set”脚本动态编写“load”脚本,该脚本具有设置和导出环境变量的代码。然后,需要引用该变量的其他脚本会定期执行“加载”脚本。顺便说一句,同样的策略可以通过写入和读取文件而不是变量来完成。

这是一个简单的例子...

Set_Load_PROCESSING_SIGNAL.sh

#!/bin/bash
PROCESSING_SIGNAL_SCRIPT=./Load_PROCESSING_SIGNAL.sh
echo "#!/bin/bash" > $PROCESSING_SIGNAL_SCRIPT
echo "export PROCESSING_SIGNAL=$1" >> $PROCESSING_SIGNAL_SCRIPT
chmod ug+rwx $PROCESSING_SIGNAL_SCRIPT

Load_PROCESSING_SIGNAL.sh(在上面运行时动态创建)

#!/bin/bash
export PROCESSING_SIGNAL=1

你可以用 Test_PROCESSING_SIGNAL.sh

#!/bin/bash
PROCESSING_SIGNAL_SCRIPT=./Load_PROCESSING_SIGNAL.sh
N=1
LIM=100
while [ $N -le $LIM ]
do
# DO WHATEVER LOOP PROCESSING IS NEEDED
echo "N = $N"
sleep 5
N=$(( $N + 1 ))

# CHECK PROCESSING_SIGNAL
source $PROCESSING_SIGNAL_SCRIPT
if [[ $PROCESSING_SIGNAL -eq 0 ]]; then
# Write log info indicating that the signal to stop processing was detected
# Write out all relevent info
# Send an alert email of this too
# Then exit
echo "Detected PROCESSING_SIGNAL for all stop. Exiting..."
exit 1
fi
done

【讨论】:

【参考方案12】:

~/.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

【讨论】:

【参考方案13】:

也许有点跑题了,但是当你真的需要它来临时设置它来执行一些脚本并最终在这里寻找答案时:

如果您需要运行具有某些环境变量的脚本,而这些环境变量在执行后不需要保留,您可以执行以下操作:

#!/usr/bin/env sh

export XDEBUG_SESSION=$(hostname);echo "running with xdebug: $XDEBUG_SESSION";$@

在我的示例中,我只是将 XDEBUG_SESSION 与主机名一起使用,但您可以使用多个变量。用分号将它们分开。执行如下(假设你调用了脚本debug.sh并把它和你的php脚本放在同一目录下):

$ debug.sh php yourscript.php

【讨论】:

以上是关于如何编写 bash 脚本来设置全局环境变量?的主要内容,如果未能解决你的问题,请参考以下文章

Bash编程013——环境变量

如何在linux环境下添加python模块路径

如何使用定时全局变量影响 bash while 循环?

如何在 bash 中获取 csh 脚本来设置环境 [关闭]

shell脚本中的全局环境变量

bash shell中的环境变量