惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Darknet – Hacking Tools, Hacker News & Cyber Security
Stack Overflow Blog
Stack Overflow Blog
aimingoo的专栏
aimingoo的专栏
The Register - Security
The Register - Security
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
P
Proofpoint News Feed
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
H
Help Net Security
月光博客
月光博客
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Blog — PlanetScale
Blog — PlanetScale
Security Archives - TechRepublic
Security Archives - TechRepublic
MyScale Blog
MyScale Blog
C
Cisco Blogs
Simon Willison's Weblog
Simon Willison's Weblog
P
Privacy & Cybersecurity Law Blog
The GitHub Blog
The GitHub Blog
WordPress大学
WordPress大学
Martin Fowler
Martin Fowler
Hugging Face - Blog
Hugging Face - Blog
P
Privacy International News Feed
G
Google Developers Blog
Recorded Future
Recorded Future
Vercel News
Vercel News
IT之家
IT之家
C
Check Point Blog
G
GRAHAM CLULEY
Recent Announcements
Recent Announcements
M
MIT News - Artificial intelligence
Y
Y Combinator Blog
Project Zero
Project Zero
NISL@THU
NISL@THU
C
Cybersecurity and Infrastructure Security Agency CISA
Hacker News: Ask HN
Hacker News: Ask HN
A
About on SuperTechFans
罗磊的独立博客
T
Troy Hunt's Blog
Know Your Adversary
Know Your Adversary
Scott Helme
Scott Helme
云风的 BLOG
云风的 BLOG
Schneier on Security
Schneier on Security
The Hacker News
The Hacker News
Attack and Defense Labs
Attack and Defense Labs
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Last Week in AI
Last Week in AI
www.infosecurity-magazine.com
www.infosecurity-magazine.com
T
The Blog of Author Tim Ferriss

f2h2h1's blog

使用yii3实现一个微框架 claw养殖技术 计算机网络基础知识 定时任务 ACME的使用经验 magento2加上varnish缓存 开发Magento2的模块 在magento2中使用persisted-query socket编程 一些开发笔记 一段CSDN文章主要内容的油猴脚本 电子邮件的不完整总结 git的笔记 在Windows下配置PHP服务器 终端,控制台和外壳 PHP各种运行方式的不完整总结 把网页导出成PDF 和颜色相关的笔记 HTTP认证方式的不完整总结 SEO的经验 密码学入门简明指南 文件的上传和下载 用纯CSS3实现的滑动按钮 在VSCode里调试PHP Linux的GUI 关于字符编码的一些坑 nc的使用和原理 在Windows下安装Magento2 对JS原型链的理解 使用docker-compose部署magento2 浏览器和服务器通讯方式的不完整总结 观察网站性能 一些关于Linux的笔记 telnet的不完整总结 在Windows下安装pear MySQL的时间类型和时间相关的函数 Windows下通过PEB读取进程的环境变量 关于 在VSCode里使用Xdebug远程调试PHP 在Windows下搭建git服务 使用shell实现的kv数据库 如何完成以xx管理系统为选题的毕业设计 数字号码资源 各种标记语言 使用PowerShell实现的http服务器 kind相关经验 DNSSEC简介 nginx+ffmpeg+websocket实现的直播例子 使用Tesseract识别字符验证码 使用docker部署nuxt FirstData后台的设置 paypal,firtdata,支付宝的不完整接入指南 微信支付的不完整接入指南 用docker-compose部署lnmp环境 mongodb分片 练习
关于环境变量的不完整总结
2023-09-19 · via f2h2h1's blog

关于环境变量的不完整总结

这篇文章最后更新的时间在六个月之前,文章所叙述的内容可能已经失效,请谨慎参考!

环境变量是什么

环境变量(environment variables)

  • 现代操作系统都有环境变量
  • 环境变量是键值对
  • 环境变量的 键 值 都是字符串
  • 程序可以通过系统 API 访问环境变量
  • 环境变量 最早出现在 Version 7 Unix ,然后后续的操作系统都继承了这样的设计
  • 环境变量是进程运行环境的一部分
    • 例如,正在运行的进程可以查询 TEMP 环境变量的值以发现存储临时文件的合适位置,
    • 或者查询 HOME 或 USERPROFILE 变量的值以查找运行该进程的用户所拥有的目录结构。
  • 每个进程都有自己单独的环境变量
  • 环境变量可以修改,但一般只能在当前进程或子进程生效
  • 环境变量由父进程设置
    • 默认情况下会复制父进程的环境变量
    • 父进程也可以单独地设置子进程的环境变量
  • 环境变量的作用
    • 让进程知道当前的运行环境
    • 把数据传递给子进程
    • 存储临时数据
  • 环境变量的作用域
    • 当前进程
      • 当前终端的环境变量实质上就是当前 shell 的环境变量,也是进程的作用域
    • 当前用户
    • 全局
  • 常见的环境变量
    • PATH: 列出 shell 搜索 用户 输入的执行命令所在的目录。
    • HOME: (类Unix系统) 和 userprofile (Microsoft Windows) 表示用户的家目录在文件系统中的位置。
    • TEMP: 进程可以存储临时文件的位置。
    • JAVA_HOME: jdk 目录的路径
  • 伪环境变量 pseudo environment variables
    • 并不真正存储在环境中,而是在请求时计算的
    • 例如 cmd 里的 %CD% %DATE% , bash 里的 $RANDOM
    • 伪环境变量好像只能在 shell 里使用,笔者虽然没有找到更多的资料,但实践的结果确实是这样
      • powershell 里没有 cmd 里的伪环境变量,猜测是使用cmd-let替代了

在 Unix 系统通过初始化脚本启动时,环境变量通常会在此时被初始化,因此会被系统中的其它进程所继承。

在 Windows 系统中,环境变量存储在 Windows 注册表中。

  • 环境变量保存在这几个位置,大多数情况下只需要修改 CurrentControlSet 就可以了
    • HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
    • HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Volatile Environment
    • HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Session Manager\Environment
    • HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Session Manager\Volatile Environment
    • HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Control\Session Manager\Environment
    • HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Control\Session Manager\Volatile Environment
    • HKEY_USERS\用户的sid\Environment
    • HKEY_USERS\用户的sid\Volatile Environment
  • 大多数情况下关注 Environment 就可以了
  • Volatile Environment 是一些和用户相关的变量,会跟随用户改变而改变,例如 userprofile
  • 对于环境变量而言,注册表中有两种类型
    • REG_SZ
    • REG_EXPAND_SZ
    • 具体区别是
      • REG_SZ 类型的键值中存在的可扩展占位符 %xxx% 不会被系统解释;
      • REG_EXPAND_SZ 类型的键值中存在的 %xxx% 的部分会被系统解释。
    • 好像是只要用户新建或修改过的环境变量,类型都会是 REG_EXPAND_SZ
  • 可以通过直接读写注册表里的值来修改环境变量 (可能会因为权限不足而失败)

在 cmd 里操作环境变量

  1. 查看全部环境变量
    set
    
  2. 设置环境变量
    set example=testvar
    
  3. 输出环境变量
    echo %path%
    
    • 访问环境变量和访问普通变量是一样的
    • 环境变量名大小写不敏感
  4. 删除环境变量
    set example=
    
  5. 修改环境变量
    • 可以直接覆盖原本的环境变量
    • 可以先删除再新建
  6. 给 path 添加新的路径
    set path=%path%;C:\Tools
    

cmd 里修改环境变量只影响当前的进程

在 powershell 里操作环境变量

PowerShell 提供了几种不同的方法来使用和管理环境变量

  • 使用 variable 语法
  • cmdlet
  • .NET 类

使用 variable 语法

  1. 查看全部环境变量
    ls Env:
    
  2. 设置环境变量
    $Env:example = "testvar"
    
  3. 输出环境变量
    echo $Env:example
    
    • 访问环境变量和访问普通变量是一样的
    • 环境变量名大小写不敏感
  4. 删除环境变量
    del Env:example
    
  5. 修改环境变量
    • 可以直接覆盖原本的环境变量
    • 可以先删除再新建
  6. 给 path 添加新的路径
    $Env:Path += ';C:\Tools'
    

cmdlet

  1. 查看全部环境变量
    Get-Item -Path Env:\*
    
  2. 设置环境变量
    New-Item -Path Env: -Name example -Value 'testvar'
    或
    Set-Item -Path Env:example -Value 'testvar'
    
  3. 输出环境变量
    Get-Item -Path Env:\example
    Get-Item -Path Env:\example | Select-Object -Property Value
    Get-Item -Path Env:\example | Select-Object -ExpandProperty Value
    
  4. 删除环境变量
    Remove-Item -Path Env:example
    
  5. 修改环境变量
    修改值
    Set-Item -Path Env:example -Value 'testvar2'
    重命名
    Rename-Item -Path Env:example -NewName example
    
  6. 给 path 添加新的路径
    Set-Item -Path Env:\Path -Value $Env:Path';C:\Tools'
    Set-Item -Path Env:\Path -Value ((Get-Item -Path Env:\Path | Select-Object -ExpandProperty Value)+';C:\Tools')
    

.NET 类

  1. 查看全部环境变量
    [Environment]::GetEnvironmentVariables()
    
  2. 设置环境变量
    [Environment]::SetEnvironmentVariable('example', 'testvar')
    
  3. 输出环境变量
    [Environment]::GetEnvironmentVariable('example')
    
  4. 删除环境变量
    [Environment]::SetEnvironmentVariable('example', '')
    
  5. 修改环境变量
    • 可以直接覆盖原本的环境变量
    • 可以先删除再新建
  6. 给 path 添加新的路径
    [Environment]::SetEnvironmentVariable('path', [Environment]::GetEnvironmentVariable('path') + ';C:\Tools')
    

保存环境变量的修改

Environment 能修改全局的或当前用户的环境变量,其它两种方法在默认情况下都是修改当前进程的环境变量。修改全局的环境变量可能会遇到权限的问题。

[Environment]::SetEnvironmentVariable('example', 'testvar', [EnvironmentVariableTarget]::Process)
[Environment]::SetEnvironmentVariable('example', 'testvar', [EnvironmentVariableTarget]::User)
[Environment]::SetEnvironmentVariable('example', 'testvar', [EnvironmentVariableTarget]::Machine)

在 windows 修改环境变量最保险的方式还是通过这里修改

此电脑 -> 属性 -> 高级系统设置 -> 环境变量

使用 wmic 操作环境变量

  1. 查看全部环境变量

    wmic ENVIRONMENT
    wmic ENVIRONMENT where "username='<system>'"
    
  2. 设置环境变量

    wmic ENVIRONMENT create name="JAVA_HOME",username="<system>",VariableValue="%javaPath%"
    
  3. 输出环境变量

    wmic ENVIRONMENT where "name='Path' and username='<system>'"
    
  4. 删除环境变量

    wmic ENVIRONMENT where "name='JAVA_HOME' and username='<system>'" delete
    

使用 wmic 修改环境变量时要注意作用域,如果没有指定 username ,可能会把所有用户和系统全局的环境变量一起修改。

其实 windows 里还有很多奇技淫巧可以修改环境变量

在 bash 里操作环境变量

  1. 查看全部环境变量
    printenv
    或
    export -p
    
  2. 设置环境变量
    export example=testvar
    
  3. 输出环境变量
    echo $PATH
    或
    printenv PATH
    
    • 访问环境变量和访问普通变量是一样的
    • 环境变量名大小写敏感
  4. 删除环境变量
    export -n example
    
  5. 修改环境变量
    • 可以直接覆盖原本的环境变量
    • 可以先删除再新建
  6. 给 path 添加新的路径
    export PATH=$PATH:/usr/local/nginx/sbin
    
    • 在 Linux 或 macOS 上,使用冒号 (:) 而不是分号 (;)

保存环境变量的修改

  • bash 修改的环境变量只在当前 shell 有效, shell 关闭后就会失效
  • 修改用户的环境变量
    1. 修改这个文件
      ~/.bashrc
      
    2. 修改环境变量时,大致需要这样修改,因为是脚本文件所以就是在脚本里添加 export 命令来修改环境变量
      # 添加一个新的环境变量
      export example=testvar
      # 给 path 添加新的路径
      export PATH=$PATH:/usr/local/nginx/sbin
      
    3. 修改 ~/.bashrc 后,运行这句命令就能生效
      source ~/.bashrc
      
  • 修改系统的环境变量
    1. 修改这个文件
      /etc/bashrc (redhat)
      /etc/bash.bashrc (debian)
      
    2. 又或者直接修改这个文件 /etc/environment
      • /etc/environment 是纯文本文件,不是脚本,不能用变量
      • /etc/bash.bashrc , /etc/profile 这类是 shell 脚本
    3. 修改系统的环境变量则需要重启系统才能生效
    4. 修改这个文件 /etc/profile 也可以达到类似的效果
      • /etc/profile 是用户登录时执行的脚本
      • (但这里其实是有一点坑的,因为有些 shell 脚本执行时可能不需要登录用户)
  • liunx 环境变量的修改本质上是修改各种配置脚本
    • 各种配置脚本有不一样的加载顺序 (可以参考这篇文章《终端,控制台和外壳》)
    • 各种配置脚本在不同的发行版里可能会有不同的文件名
    • source 命令的作用是在当前 shell 中执行脚本,不会启动新的 shell
    • export 命令的作用是设置或显示环境变量, export 可新增,修改或删除环境变量,供后续执行的程序使用

在 c 语言里操作环境变量

c 里有一系列的函数来操作环境变量

char *getenv(const char *name);
int putenv(char *string);
int setenv(const char *envname, const char *envval, int overwrite);
int unsetenv(const char *name);
char *secure_getenv(const char *name);
int clearenv(void);
  • 这些函数都在在头文件 stdlib.h 中声明
  • 全局变量 char **environ 和 main 函数的第三个参数 char* envp[] 都保存有完整的环境变量
    • 全局变量 char **environ 在头文件 unistd.h 中声明
  • 只有 getenv 是 ascii c
  • putenv, setenv, unsetenv 这三个函数和 environ envp 都是来自 posix
  • secure_getenv 和 clearenv 来自 gun c
  • 笔者其实没多少心思区分哪个函数来自哪个标准,反正用 gcc 编译时都能用。

例子

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
extern char **environ;
int main(int argc, char* argv[], char* envp[])
{
    for (int i = 0; envp[i] != NULL; ++i)
    {
        printf("%s\n", envp[i]);
    }
    printf("****\n");

    for (char **var = environ; *var != NULL; ++var)
    {
        printf("%s\n", *var);
    }
    printf("****\n");
    
    printf("%s\n", getenv("PATH"));
    printf("****\n");
    
    putenv("TEST=123");
    printf("%s\n", getenv("TEST"));
    printf("****\n");

    int overwrite = 1;
    setenv("TEST", "321", overwrite);
    printf("%s\n", getenv("TEST"));
    printf("****\n");
    
    unsetenv("TEST");

    clearenv();

    return 0;
}

其它语言操作环境变量也会有相应的语法,只要看一下文档就好了。

查看某个进程的环境变量

参考