putenv(string $assignment): bool添加 assignment 到服务器环境变量。 环境变量仅存活于当前请求期间。 在请求结束时环境会恢复到初始状态。getenv(?string $name = null, bool $local_only = false): string|array|false参数:namestring 形式的变量名或为 null。local_only当设置为 true 时,仅返回由操作系统或 putenv() 设置的本地环境变量。这只在 name 是 string 时才生效。警告:如果 PHP 运行在诸如 Fast CGI 之类的 SAPI 中,即使已使用putenv()设置了同名的本地环境变量,此函数也始终返回 SAPI 设置的环境变量的值。使用此local_only 参数可返回本地设置的环境变量的值。
<?phpvar_dump(getenv("A",true));var_dump(getenv("A"));var_dump(putenv("OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-agent.otel.svc.cluster.local:4317"));var_dump(putenv("A=http://otel-agent.otel.svc.cluster.local:4317"));////var_dump(getenv("OTEL_EXPORTER_OTLP_ENDPOINT", true));var_dump(getenv("OTEL_EXPORTER_OTLP_ENDPOINT"));var_dump(getenv("A",true));var_dump(getenv("A"));//var_dump($_SERVER)其中OTEL_EXPORTER_OTLP_ENDPOINT环境变量,已经在容器启动时注入(值为111111),环境变量A是代码注入环境变量
场景1:直接php执行脚本[root@php-test-58fcfcdccb-clkdl web]# php74 index.php bool(false)bool(false)bool(true)bool(true)string(45) "http://otel-agent.otel.svc.cluster.local:4317"string(45) "http://otel-agent.otel.svc.cluster.local:4317"string(45) "http://otel-agent.otel.svc.cluster.local:4317"string(45) "http://otel-agent.otel.svc.cluster.local:4317"场景2:执行curl请求,通过nginx 入口访问[root@php-test-58fcfcdccb-clkdl web]# curl 127.0.0.1/index.phpbool(false)bool(false)bool(true)bool(true)string(45) "http://otel-agent.otel.svc.cluster.local:4317"string(45) "http://otel-agent.otel.svc.cluster.local:4317"string(45) "http://otel-agent.otel.svc.cluster.local:4317"string(45) "http://otel-agent.otel.svc.cluster.local:4317"场景3:执行curl 请求,通过fast-cgi方式,现有php定时任务执行的方式[root@php-test-58fcfcdccb-clkdl web]# SCRIPT_NAME=/data/apps/business/web/index.php SCRIPT_FILENAME=/data/apps/business/web/index.php REQUEST_METHOD=GET QUERY_STRING=xml cgi-fcgi -bind -connect /var/run/php-fpm.sockContent-type: text/html; charset=UTF-8bool(false)bool(false)bool(true)bool(true)string(45) "http://otel-agent.otel.svc.cluster.local:4317"string(6) "111111" #这就是定时任务报错的问题点,没有读到代码更新后的值,导致运行失败,实际定时任务就是这种请求方式运行的string(45) "http://otel-agent.otel.svc.cluster.local:4317"string(45) "http://otel-agent.otel.svc.cluster.local:4317"当我手动在系统层export 环境变量A的值[root@php-test-58fcfcdccb-clkdl web]# export A='abcdefg'结果:三种场景的执行结果如下:[root@php-test-58fcfcdccb-clkdl web]# php74 index.php string(7) "abcdefg"string(7) "abcdefg"bool(true)bool(true)string(45) "http://otel-agent.otel.svc.cluster.local:4317"string(45) "http://otel-agent.otel.svc.cluster.local:4317"string(45) "http://otel-agent.otel.svc.cluster.local:4317"string(45) "http://otel-agent.otel.svc.cluster.local:4317"[root@php-test-58fcfcdccb-clkdl web]# curl 127.0.0.1/index.phpbool(false)bool(false)bool(true)bool(true)string(45) "http://otel-agent.otel.svc.cluster.local:4317"string(45) "http://otel-agent.otel.svc.cluster.local:4317"string(45) "http://otel-agent.otel.svc.cluster.local:4317"string(45) "http://otel-agent.otel.svc.cluster.local:4317"[root@php-test-58fcfcdccb-clkdl web]# SCRIPT_NAME=/data/apps/business/web/index.php SCRIPT_FILENAME=/data/apps/business/web/index.php REQUEST_METHOD=GET QUERY_STRING=xml cgi-fcgi -bind -connect /var/run/php-fpm.sockContent-type: text/html; charset=UTF-8bool(false)string(7) "abcdefg"bool(true)bool(true)string(45) "http://otel-agent.otel.svc.cluster.local:4317"string(6) "111111"string(45) "http://otel-agent.otel.svc.cluster.local:4317"string(7) "abcdefg"
php针对环境变量存储有两个区域:
SAPI 表 (Request Params): 类似于 HTTP 请求头,由 Web Server(Nginx 或 cgi-fcgi)传给 FPM。优先级高。
OS Environ (System Env): 进程级别的系统环境变量。 putenv修改的是这里。优先级低。
在 PHP 的 getenv 实现中: 参数为true 指的是 仅限本地进程(OS 层面) 的环境变量(即 C 语言层面的 environ)。 不带参数 (默认false) 指的是 SAPI 提供的变量(即 FastCGI 参数)优先,如果没有再去找本地进程的。
场景1 获取环境变量值正常,原因分析: CLI 模式 (Scenario 1) 架构:Shell -> PHP 进程。 机制:PHP 是直接作为一个普通的操作系统进程运行的。 数据源:它没有所谓的“SAPI 请求参数表”(因为它不是在处理 Web 请求,没有 Nginx/FastCGI 协议给它传参)。 getenv 的行为:在 CLI 模式下,PHP 的 getenv() 函数就是直接包装了底层的 C 语言 getenv()。 流程: putenv 修改底层 OS 变量。 getenv 读取底层 OS 变量。 两者读写的是同一块内存区域,所以完全同步,立刻生效。
场景2 (Nginx) 正常,原因分析: 环境现状: 容器启动时有 OTEL=111111 (在 OS Environ 中)。 请求传输: 浏览器 -> Nginx -> FPM。 关键点: Nginx 的配置文件里,通常只写了 fastcgi_param SCRIPT_FILENAME ... 等标准头。Nginx 并没有把系统里的 OTEL 变量作为 fastcgi_param 发送给 FPM。 PHP 内部状态: SAPI 表:空(没有 OTEL)。 OS Environ:111111。 代码执行: putenv("OTEL=http://..."): 修改 OS Environ 为 http://...。 getenv("OTEL"): 先查 SAPI 表(空)-> 再查 OS Environ(找到 http://...)。 结果: 这里读到了新值。
为什么 场景3 (cgi-fcgi) 异常? (111111) 环境现状: Shell 环境里有 OTEL=111111。 请求传输: cgi-fcgi 启动。这也正是 cgi-fcgi 的特性:它会自动把当前 Shell 里的所有环境变量,全部打包成 fastcgi_param 发送给 FPM。 PHP 内部状态: SAPI 表:包含 OTEL=111111 (作为请求参数传进来了)。 OS Environ:包含 111111 (FPM 进程继承的)。 代码执行: putenv("OTEL=http://..."): 修改 OS Environ 为 http://...。注意:这不会影响 SAPI 表。 getenv("OTEL"): 先查 SAPI 表(发现了 OTEL=111111) -> 直接返回。 结果: 这里读到的是旧值。
supervisorctl操作#Reread(重新读取配置) 哪怕你改了文件,Supervisord 内存里还是旧的。这步让它去读文件,找出哪些变了(Available),哪些没变。supervisorctl reread#Update(更新并重启变更的服务) 这步会对比配置差异,只重启那些配置发生变化的服务组或进程,完全不影响其他没改动的服务。supervisorctl update