![Linux程序设计(第4版)](https://wfqqreader-1252317822.image.myqcloud.com/cover/825/26211825/b_26211825.jpg)
4.2 环境变量
我们在第2章讨论过环境变量。这是一些能用来控制shell脚本和其他程序行为的变量。你还可以用它们来配置用户环境。例如,每个用户有一个环境变量HOME,它定义了用户的家目录,即该用户会话的默认开始位置。正如你已看到的,你可以在shell提示符中检查环境变量:
![](https://epubservercos.yuewen.com/08DD0E/14642180305205206/epubprivate/OEBPS/Images/figure_0139_0003.jpg?sign=1738880750-IwTpomZFXCf70EULfORlHEvYrKlNQrtd-0-3a74d3b8a27f4819b03a3ca48260c022)
你也可以使用shell的set命令来列出所有的环境变量。
UNIX规范为各种应用定义了许多标准环境变量,包括终端类型、默认的编辑器、时区等。C语言程序可以通过putenv和getenv函数来访问环境变量。
![](https://epubservercos.yuewen.com/08DD0E/14642180305205206/epubprivate/OEBPS/Images/figure_0139_0004.jpg?sign=1738880750-hyVxkuF9MMbFzXCS0JngD2VX7LoTzKWh-0-cff0fb65038dc20cb2d4f43c95905632)
环境由一组格式为“名字=值”的字符串组成。getenv函数以给定的名字搜索环境中的一个字符串,并返回与该名字相关的值。如果请求的变量不存在,它就返回null。如果变量存在但无关联值,它将运行成功并返回一个空字符串,即该字符串的第一个字节是null。由于getenv返回的字符串是存储在getenv提供的静态空间中,所以如果想进一步使用它,你就必须将它复制到另一个字符串中,以免它被后续的getenv调用所覆盖。
putenv函数以一个格式为“名字=值”的字符串作为参数,并将该字符串加到当前环境中。如果由于可用内存不足而不能扩展环境,它会失败并返回-1。此时,错误变量errno将被设置为ENOMEM。
在下面的实验中,你将编写一个程序来打印所选的任意环境变量的值。如果给程序传递第二个参数,你还将设置环境变量的值。
实验getenv和putenv
(1)紧接在main函数声明后的几行代码用于确保程序environ.c被正确调用,它只带有一个或两个参数:
![](https://epubservercos.yuewen.com/08DD0E/14642180305205206/epubprivate/OEBPS/Images/figure_0139_0005.jpg?sign=1738880750-PPHuWaPlRY2NApeYz7j5UsAy8jNKi1OX-0-ab605911679288b7f1b31572d74a9b8e)
(2)然后,调用getenv从环境中取出变量的值:
![](https://epubservercos.yuewen.com/08DD0E/14642180305205206/epubprivate/OEBPS/Images/figure_0140_0002.jpg?sign=1738880750-QD3wr9wfxgd5A7PIO4vdfq11SUzLlUde-0-a57d63070e2aa5bceca2e97a60e4c083)
(3)接下来,检查程序调用时是否有第二个参数。如果有,则通过构造一个格式为“名字=值”的字符串并调用putenv来设置变量的值:
![](https://epubservercos.yuewen.com/08DD0E/14642180305205206/epubprivate/OEBPS/Images/figure_0140_0003.jpg?sign=1738880750-IzNtJwQoNfQQA1FoSWXnNWkbsKEl0gxq-0-87d41b01e98101543747d10379201153)
(4)最后,再次调用getenv来查看变量的新值:
![](https://epubservercos.yuewen.com/08DD0E/14642180305205206/epubprivate/OEBPS/Images/figure_0140_0004.jpg?sign=1738880750-YFMjN7JEiouexQvl1xRv9mgjGIamXDVP-0-8cd2f1759ee3f93a36e240f07cb1a95b)
运行这个程序,你可以查看和修改环境变量:
![](https://epubservercos.yuewen.com/08DD0E/14642180305205206/epubprivate/OEBPS/Images/figure_0140_0005.jpg?sign=1738880750-mE2dumPvIe7dBYo4P5nv1ATGBpNuB38Q-0-2d6031241bb1a2828c3edf596b9d8a4b)
注意:环境仅对程序本身有效。你在程序里做的改变不会反映到外部环境中,这是因为变量的值不会从子进程(你的程序)传播到父进程(shell)。
4.2.1 环境变量的用途
程序经常使用环境变量来改变它们的工作方式。用户可以通过以下方式设置环境变量的值:在默认环境中设置、通过登录shell读取的.profile文件来设置、使用shell专用的启动文件(rc)或在shell命令行上对变量进行设定。例如:
![](https://epubservercos.yuewen.com/08DD0E/14642180305205206/epubprivate/OEBPS/Images/figure_0141_0002.jpg?sign=1738880750-a4JGrwjP27VlGKOwPYOGOV9RzrZ7eBYU-0-89db4edaa8efe4a6d8f98d16d0458db0)
shell将行首的变量赋值作为对环境变量的临时改变。在上面的第二个例子中,程序environ将运行在一个变量FRED有一个赋值的环境中。
举个例子,在CD数据库应用程序的未来版本中,你可以通过改变一个环境变量,比如CDDB,来指定所用的数据库。这样,每个用户就能指定自己的默认值,或者在每次运行时使用shell命令来设定:
![](https://epubservercos.yuewen.com/08DD0E/14642180305205206/epubprivate/OEBPS/Images/figure_0141_0003.jpg?sign=1738880750-lhoZo9ooO0QxLPVeqkMkCJb4HBxSreX8-0-8c483600bdc8a2b2e502b4b324d6711d)
或
![](https://epubservercos.yuewen.com/08DD0E/14642180305205206/epubprivate/OEBPS/Images/figure_0141_0004.jpg?sign=1738880750-ACCeI79a5pnGRl9lh6nuQpYgQriFEqbP-0-c8dd75b334cdc46c32bce6f5e5ef8192)
环境变量是一把双刃剑,使用它的时候要小心!与命令行选项相比,它们对用户来说更加“隐蔽”,这样就使得程序的调试变得更加困难。从某种意义上来说,环境变量就像全局变量一样,它们会改变程序的行为,产生不可预期的结果。
4.2.2 environ变量
正如你已看到的,程序的环境由一组格式为“名字=值”的字符串组成。程序可以通过environ变量直接访问这个字符串数组。environ变量的声明如下所示:
![](https://epubservercos.yuewen.com/08DD0E/14642180305205206/epubprivate/OEBPS/Images/figure_0141_0005.jpg?sign=1738880750-fjU89sk698FKUAuTuqHXPjUpz5UJf62W-0-8e3f68fc68f0dd70632bb5852613ec91)
实验environ变量
下面这个程序showenv.c使用environ变量打印环境变量:
![](https://epubservercos.yuewen.com/08DD0E/14642180305205206/epubprivate/OEBPS/Images/figure_0141_0006.jpg?sign=1738880750-nKQxZRKIYreSBVdvlERYRceU1FZ8icQC-0-54a9752cf7be1fa3dc766ddc5256fafc)
当在Linux系统中运行该程序时,你将得到如下的输出(略做删减)。这些变量的数目、出现顺序和值取决于操作系统的版本、所用的shell以及程序运行时的用户设置。
![](https://epubservercos.yuewen.com/08DD0E/14642180305205206/epubprivate/OEBPS/Images/figure_0142_0002.jpg?sign=1738880750-1g17lgbpLPZKJq5ZEAJSQxnYiYM7mQC6-0-cf2e6e63527823e7f6865c58d4e90ccf)
实验解析
这个程序遍历environ变量(一个以null结尾的字符串数组),并打印出整个环境。