有没有办法在Linux中使用C来设置环境变量?我尝试了setenv()和putenv(),但它们似乎不适合我。
setenv()
putenv()
beq87vna1#
我在这里要做一个大胆的猜测,但这些函数看起来不起作用的正常原因不是因为它们不起作用,而是因为用户并不真正理解环境变量是如何工作的。例如,如果我有一个程序:
int main(int argc, char**argv) { putenv("SomeVariable=SomeValue"); return 0; }
然后我从shell运行它,它不会修改shell的环境--子进程没有办法这样做。这就是为什么修改环境的shell命令是内置的,也是为什么你需要source一个脚本,其中包含你想添加到你的shell的变量设置,而不是简单地运行它。
source
6jjcrrmo2#
任何UNIX程序都在一个独立于启动它的进程的进程中运行;这是一个“子”进程。当一个程序启动时--无论是在命令行还是其他方式--系统都会创建一个新的进程,这个进程(或多或少)是父进程的副本。这个副本包括父进程中的环境变量,这是子进程“继承”其父进程的环境变量的机制。(这是这里其他答案所说的)也就是说,一个进程只会设置它自己的环境变量。其他人已经提到了获取shell脚本,作为在当前进程中设置环境变量的一种方法,但是如果您需要以编程方式在当前(shell)进程中设置变量,那么有一种稍微间接的方法是可能的。请考虑以下内容:
% cat envs.c # include <stdio.h> int main(int argc, char**argv) { int i; for (i=1; i<argc; i++) { printf("ENV%d=%s\n", i, argv[i]); } } % echo $ENV1 % ./envs one two ENV1=one ENV2=two % eval `./envs one two` % echo $ENV1 one %
内置的eval计算它的参数,就像在shell提示符下键入该参数一样。csh样式变体作为练习保留!
eval
e4yzc0pl3#
由setenv()/putenv()设置的环境变量将被设置给执行这些函数的进程,并将被它启动的进程继承。但是,它不会被 * 广播 * 到执行程序的shell中。为什么我的setenv() Package 器不起作用?
mlnl4t2r4#
环境块是进程本地的,并且被复制到子进程。所以如果你改变变量,新的值只影响你的进程和改变后产生的子进程。当然它不会改变你启动的shell。
brvekthn5#
不是这个问题的答案,只是想说putenv是危险的,请改用setenv。
putenv
setenv
putenv(char *string)是危险的,因为它所做的只是将键值对字符串的地址附加到environ数组中。因此,如果我们随后修改string所指向的字节,所做的更改将影响进程环境。
putenv(char *string)
environ
string
# include <stdlib.h> int main(void) { char new_env[] = "A=A"; putenv(new_env); // modifying your `new_env` also modifies the environment // vairable new_env[0] = 'B'; return EXIT_SUCCESS; }
由于environ只存储string参数的地址,因此string必须是静态的,以防止出现悬空指针。
# include <stdlib.h> void foo(); int main(void) { foo(); return EXIT_SUCCESS; } void foo() { char new_env[] = "A=B"; putenv(new_env); }
当foo函数的堆栈帧被释放时,new_env的字节消失了,并且存储在environ中的地址变成了悬空指针。
foo
new_env
5条答案
按热度按时间beq87vna1#
我在这里要做一个大胆的猜测,但这些函数看起来不起作用的正常原因不是因为它们不起作用,而是因为用户并不真正理解环境变量是如何工作的。例如,如果我有一个程序:
然后我从shell运行它,它不会修改shell的环境--子进程没有办法这样做。这就是为什么修改环境的shell命令是内置的,也是为什么你需要
source
一个脚本,其中包含你想添加到你的shell的变量设置,而不是简单地运行它。6jjcrrmo2#
任何UNIX程序都在一个独立于启动它的进程的进程中运行;这是一个“子”进程。
当一个程序启动时--无论是在命令行还是其他方式--系统都会创建一个新的进程,这个进程(或多或少)是父进程的副本。这个副本包括父进程中的环境变量,这是子进程“继承”其父进程的环境变量的机制。(这是这里其他答案所说的)
也就是说,一个进程只会设置它自己的环境变量。
其他人已经提到了获取shell脚本,作为在当前进程中设置环境变量的一种方法,但是如果您需要以编程方式在当前(shell)进程中设置变量,那么有一种稍微间接的方法是可能的。
请考虑以下内容:
内置的
eval
计算它的参数,就像在shell提示符下键入该参数一样。csh样式变体作为练习保留!e4yzc0pl3#
由setenv()/putenv()设置的环境变量将被设置给执行这些函数的进程,并将被它启动的进程继承。但是,它不会被 * 广播 * 到执行程序的shell中。
为什么我的setenv() Package 器不起作用?
mlnl4t2r4#
环境块是进程本地的,并且被复制到子进程。所以如果你改变变量,新的值只影响你的进程和改变后产生的子进程。当然它不会改变你启动的shell。
brvekthn5#
不是这个问题的答案,只是想说
putenv
是危险的,请改用setenv
。putenv(char *string)
是危险的,因为它所做的只是将键值对字符串的地址附加到environ
数组中。因此,如果我们随后修改string
所指向的字节,所做的更改将影响进程环境。由于
environ
只存储string
参数的地址,因此string
必须是静态的,以防止出现悬空指针。当
foo
函数的堆栈帧被释放时,new_env
的字节消失了,并且存储在environ
中的地址变成了悬空指针。