因此,我需要在 shell 之间共享环境变量,并且所有 shell 都能立即识别变量的更改,就像全局变量一样。但它们必须与主控 PID 相关,因此我可以运行 2 个 shell 脚本,每个脚本都是具有相同全局变量名称的主控,并且它的子级只会更改与其主控 PID 相关的变量。
我用于bash
编写脚本。
我目前的研究有这些:
模块
我读到我可以使用模块项目来实现:http://modules.sourceforge.net/,但我在尝试这样做时遇到了很大的麻烦,似乎缺乏例子?而且“模块”是一个太通用的词,很难用谷歌搜索,因为它与许多其他东西混合在一起......几周后我的手仍然是空的......
简单的文本源文件
我还读到我应该使用一个简单的文本文件作为源脚本文件来存储/更新/读取变量,flock
也使用以避免并发写入。但这样做会带来一些问题,例如 2 个 shell 同时并发更改变量。
或者
我知道,在 shell 读取“全局”变量后,它将保留该值,直到进行另一次读取为止;同时另一个 shell 也可能会改变它......
可能是一个非常快的外部应用程序可以提供这样的存储,那么我们不会尝试使用环境变量作为全局变量?但我的猜测是任何 SQL 解决方案都会太慢......
答案1
您可以使用(include 命令)将环境写入文件export -p
并在其他实例中定期读回。.
但正如您所注意到的,如果存在并发修改,结果将不会很好。
如果您希望修改立即传播,则必须在export
内置函数周围使用包装器,该包装器也将更改传播到其他 shell。在 Linux 上,您可以使用该flock
实用程序。
global_export () {
{
flock 0
. /path/to/env
[ $# -eq 0 ] || export "$@"
export -p >/path/to/env
} </path/to/env
}
global_export
请注意,每当您为导出的变量分配新值时都需要调用。
这是相当笨拙的。很可能有更好的方法来解决您的问题。最明显的方法是让任何使用这些环境变量的命令读取配置文件。
答案2
除了仅使用flock
贾尔斯的答案之外,我还会做类似以下的事情:
注册一个信号处理程序来重新加载文件:
reload_env() {
flock -s 3
. /path/to/env
flock -u 3
}
trap reload_env USR1
写出文件并向SIGUSR1
所有 shell 发送通知它们重新加载文件的函数:
export_env() {
flock 3
export -p >/path/to/env
flock -u 3
fuser -k -USR1 /path/to/env
}
打开该文件,但不对其执行任何操作。这只是为了能够fuser
向该 shell 发出信号:
exec 3>>/path/to/env
顺序有点重要。至少该exec ...
部分必须在该trap ...
部分之后。否则,我们可以打开文件,然后fuser
在注册信号处理程序之前收到调用信号。
注意:代码完全未经测试,但原则成立。
注意2:这个示例代码是针对bash的。
答案3
与fish
外壳一起使用通用作用域变量:
set -U var value
当然,这只适用于fish
同一用户运行的 shell。
如果你想将它绑定到主控PID,将其包含在变量名称中
set -U m${masterpid}var value
答案4
如果 ksh93 是一个选项,那么肯定有一种方法可以使用 getter 和 setter 规则函数来实现您想要的功能,这些函数可以从共享存储中检索变量值或将变量值存储到共享存储中。
与其他有用的fish
通用变量功能不同,您可以访问实现,以便将值共享限制为一组进程,通过用例中的某种机制链接到主 pid,同时保留变量的单个名称。