13.18 查看指定进程的环境变量 https://scz.617.cn/unix/202210251438.txt Q: 用如下命令启动Firefox后,想确认SSLKEYLOGFILE位于目标进程环境变量中 SSLKEYLOGFILE=$HOME/src/sslkey.log firefox A: scz 2022-10-25 获取PID ps auwx | grep firefox pidof firefox 显示指定PID的环境变量 strings /proc//environ | grep SSLKEYLOGFILE xargs -0 -n 1 echo < /proc//environ | grep SSLKEYLOGFILE xargs -0 -L 1 -a /proc//environ | grep SSLKEYLOGFILE sed 's/\x00/\n/g' /proc//environ | grep SSLKEYLOGFILE cat /proc//environ | tr '\0' '\n' | grep SSLKEYLOGFILE ps wwe -p | tr ' ' '\n' | grep SSLKEYLOGFILE ww表示"unlimited width",e表示显示环境变量。显然strings最简单。 检查所有Firefox进程的环境变量 -------------------------------------------------------------------------- for pid in $(pidof firefox) do echo $pid ps wwe -p $pid | tr ' ' '\n' | grep SSLKEYLOGFILE done -------------------------------------------------------------------------- for pid in $(pidof firefox); do echo $pid;ps wwe -p $pid | tr ' ' '\n' | grep SSLKEYLOGFILE; done -------------------------------------------------------------------------- for pid in $(pidof firefox); do echo $pid;strings /proc/$pid/environ | grep SSLKEYLOGFILE; done -------------------------------------------------------------------------- A: scz 2022-10-30 参看proc(5) /proc/[pid]/environ 进程启动时会分配一块内存,将execve(2)的envp[]所指向的初始环境变量复制进去, 各条环境变量之间以\0分隔,这块内存通过proc伪文件系统展现给用户态。进程可以 调用prctl(2)的PR_SET_MM_ENV_START修改这块内存位置,/proc/[pid]/environ会反 映这种变化。进程启动之后,若调用putenv(3)或直接修改environ(7)中的环境变量, 相应变动并不自动反映到/proc/[pid]/environ中,后者大多数时候只是初始静态备 份。 SSLKEYLOGFILE=$HOME/src/sslkey.log opera for pid in $(pidof opera); do echo $pid;strings /proc/$pid/environ | grep -i SSLKEYLOGFILE; done Opera启动后应该改动过环境变量,上述命令无输出。 观察Opera各进程的/proc/$pid/environ for pid in $(pidof opera); do echo $pid;xxd -l 0x40 -g 1 /proc/$pid/environ; done 从上述命令输出看,Opera可能调用过prctl(PR_SET_MM_ENV_START),且新区域并未 实际存放环境变量。此时无法通过/proc/[pid]/environ检查Opera的环境变量,替代 方案是用GDB。 ps auwx | grep opera pidof opera gdb -q -nx -x ./gdbinit_x64.txt -x ./gdbhelper.py -p (gdb) info address environ environ是导出的全局变量,初值等于envp,但随后实时指向环境变量区域。 -------------------------------------------------------------------------- # # https://sourceware.org/gdb/onlinedocs/gdb/Command-and-Variable-Index.html # https://sourceware.org/gdb/onlinedocs/gdb/Command-Files.html # define GetStrArray set $array = (char **)$arg0 set $i = 0 set $str = $array[$i] while $str x/s $str set $i = $i + 1 set $str = $array[$i] end end # # 显示所有环境变量 # GetStrArray environ -------------------------------------------------------------------------- define FindStrFromArray set $array = (char **)$arg0 set $magic = $arg1 set $i = 0 set $str = $array[$i] while $str if $_regex($str,$magic) x/s $str loop_break end set $i = $i + 1 set $str = $array[$i] end end # # 查找特定环境变量 # FindStrFromArray environ "SSLKEYLOGFILE=" -------------------------------------------------------------------------- (gdb) sp GetStrArray environ | grep SSLKEYLOGFILE 0x3138002149c0: "SSLKEYLOGFILE=/home/scz/src/sslkey.log" (gdb) x/s *((char **)environ+37) (gdb) x/s ((char **)environ)[37] 0x1e44002149c0: "SSLKEYLOGFILE=/home/scz/src/sslkey.log" 有时可用"x/10s *(char **)environ"这类命令快速批量查看环境变量,但该用法不 等价于"GetStrArray environ";不只是数目问题,"x/10s"假设各条环境变量之间只 有一个\0,若不符合假设,输出非预期,"x/10s"可用于Firefox,不适用于Opera。 (gdb) show environment (gdb) sp show environment | grep USER 上述命令显示GDB进程的环境变量,不是被调试进程的,不要掉坑里了。