在shell中有许多方法能够修改环境变量,例如export,set等命令;要永久修改环境变量,也可以将 export 相关语句添加到用户的 ~/.bashrc 或 ~/.bash_profile 文件中;这些文件会在每次打开新的Shell会话时被执行,当执行新的程序时,当前shell作为父进程的环境变量会被子进程继承。
在shell命令行中可以直接使用export命令对环境变量进行删改;
| export [-fnp][变量名称]=[变量设置值]
参数说明: -f 代表[变量名称]中为函数名称。 -n 删除指定的变量。变量实际上并未删除,只是不会输出到后续指令的执行环境中。 -p列出所有的shell赋予程序的环境变量。 |
如果是在原有基础上进行添加的话,参考如下,先获取PATH的值,然后添加上需要的环境变量。
| # 将/tmp/hello的路径加入到PATH,从而可以在任何地方直接使用hello命令。
export PATH=$PATH:/tmp/hello |
当然,给子进程添加环境变量还有一种更简单的方式,直接在shell命令前通过name=value 的形式,向进程的环境变量表中添加环境变量,这种方式只对该次执行的程序有效,不会永久修改系统的环境变量。
用法如下:
| NAME=value ./test |
在当前路径下执行测试程序test的时候,以 name=value 的形式在其路径前面加上环境变量NAME=value;如果是需要添加多个环境变量,则在./test 前面放置多对 name=value 即可,用空格作为分隔。
C 语言函数库中也提供了相当多的方法用于添加、修改环境变量,如 putenv()、setenv()函数等等。
1.putenv
putenv()函数用于增加或修改当前的环境变量。string的格式为“name=value”。如果当前环境变量没有该名称的环境变量,则增加这个新的环境变量;如果已经存在,则使用新值。
1)头文件
#include <stdlib.h>
2)函数原型
int putenv(char *string);
3)参数
string:参数 string 是一个字符串指针,指向name=value(即环境变量名=环境变量值)形式的字符串。
4)返回值
函数成功时返回零,如果发生错误则返回非零。如果发生错误,则设置errno来指示原因。
该函数调用成功之后,参数 string 所指向的字符串就成为了进程环境变量的一部分了,换言之,putenv()函数将设定 environ 变量(字符串数组)中的某个元素(字符串指针)指向该 string 字符串,而不是指向它的复制副本,这里需要注意!因此,不能随意修改参数 string 所指向的内容,这将影响进程的环境变量,出于这种原因,参数 string 不应为自动变量(即在栈中分配的字符数组)。
看似功能很简单,但实际上使用这个接口时,却很容易犯错。请看下面的代码:
5)示例:通过putenv()函数添加环境变量
| #include <stdlib.h>
#include <stdio.h> static void set_env_string(void){ char test_env[] = "test_env=test"; if (putenv(test_env)) printf("fail to putenv\n"); printf("1. The test_evn string is %s\n", getenv("test_env")); } static void show_env_string(void){ printf("2. The test_env string is %s\n", getenv("test_env")); } int main(int argc, char *argv[]){ set_env_string(); show_env_string(); return 0; } |
6)运行结果
| 1. The test_evn string is test
2. The test_env string is (null) |
7)代码解析
前后两次通过getenv()获取环境变量不一致的原因,在于使用putenv()添加环境变量时,参数直接被当作环境变量的一部分了。这就是需要注意的点,putenv() 函数直接使用传入的字符串,并不会复制它。传入的内容在函数退出时失效或被修改,则环境变量的值也会变得不确定。对于本例而言,test_env 是一个局部变量,函数返回后这块内存可能会被释放或被其他数据覆盖,这导致环境变量的值丢失或被篡改。在执行set_env_string结束的时候,test_env已经不存在了,因此,在进入show_env_string的时候,就无法得到正确的值了。
在更现代的代码中,建议使用 setenv() 代替 putenv(),因为 setenv() 可以更好地处理内存管理,且避免了直接修改传入字符串的风险。
322