访问没有赋值的Linux环境变量



我编写了一些小的方便函数,通过包装std::getenvsetenvenviron来处理C++中的环境变量。除了设置和获取环境变量外,我还提供了检查当前环境是否包含某个变量的功能。

#include <cstdlib>
#include <unistd.h>
template <typename VAR_TYPE>
void set(const std::string& variableName, VAR_TYPE varValue, bool overwrite = false) {
if (!setenv(variableName.c_str(), std::string(variableValue).c_str(), overwrite)) {
if (errno == ENOMEM) {
throw std::bad_alloc();
} else if (errno == EINVAL) {
throw std::invalid_argument("Variable name invalid: "  + variableName);
} else {
throw std::runtime_error("Failed to set environment variable " + variableName);
}
}
}
std::string load(const std::string& variableName, const std::string& defaultValue = "") {
if (const char* envVariable = std::getenv(variableName)) {
return std::string(envVariable);
}
return defaultValue;
}
bool contains(const std::string& variableName) {
for (char** currentEnviron = environ; *currentEnviron; currentEnviron++) {
if (!std::strncmp(variableName.c_str(), *currentEnviron, variableName.length())) {
return true;
}
}
return false;
}

但是,根据定义,这只允许访问NAME=VALUE形式的环境变量。

bash中,我可以执行以下操作:

$> export SOME_VAR
$> export -p | grep SOME_VAR
declare -x SOME_VAR

显然,SOME_VAR是在某个地方定义的,即使我没有给它赋值。然而,当我运行printenv时,它使用了我在包装中使用的相同方法,SOME_VAR没有列出。我看过/proc/self/environ,但它只列出了具有赋值的变量。

我的问题是:

  1. 定义为SOME_VAR_WITH_VALUE=42SOME_VAR_WITHOUT_VALUE的环境变量之间有什么区别
  2. 在C/C++中是否有可能访问没有值的环境变量

Shell有内部和导出环境变量的概念。

ABC=xyz这样的shell命令设置一个内部变量(可以在使用set的Bash中看到(。

要导出内部变量,可以使用export命令。

export ABC=xyz将创建一个内部变量导出它(使用env可以看到导出的变量(。

export ABC本身不定义任何变量,它只是标记要导出的ABC定义时

举个例子:

$ ABC=xyz
$ set | grep ABC
ABC=xyz
$ env | grep ABC

现在有了export:

$ export ABC
$ set | grep ABC
$ env | grep ABC
$ ABC=xyz
$ set | grep ABC
ABC=xyz
$ env | grep ABC
ABC=xyz

请注意变量在设置时是如何导出的。所以export ABC纯粹是一个shell特性,它不会修改环境。没有API。

要设置具有空值的环境变量,请使用export ABC="":

$ export ABC=""
$ env | grep ABC
ABC=

首先尝试这个:

export SOME_VAR
set | grep SOME_VAR

第二行将不返回任何内容。这是因为第一行没有定义SOME_VAR

至于你的两个问题:

  1. CCD_ 23无明显作用。它不会创建没有值的变量,也不会更改已设置变量的值
  2. 环境变量总是有一个值,但该值可能是空字符串。如果您尝试访问不存在的变量,您将得到NULL

最终,bash只是另一个Linux程序。所涉及的魔法是有限的。它可以更改libcenviron变量,但也可以有自己的内部变量。如果在/proc/sef/environ中看不到SOME_VAR_WITHOUT_VALUE,则可以推断它是某种bash内部变量。

注意,bash和大多数Linux程序一样,可以并行运行多次。环境在进程之间是分开的。因此,即使在C中,也不能直接访问任何bash环境变量。当您的流程启动时,bash会将其环境复制到您的环境中,这是您在利用这一事实。但env -i your_process甚至会阻止这种情况。

最新更新