【问题标题】:Using sed to get an env var from /proc/*/environ weirdness with \x00使用 sed 从 /proc/*/environ 怪异的 \x00 获取环境变量
【发布时间】:2026-01-06 23:20:02
【问题描述】:

我正在尝试通过其他一些进程环境来获得特定的环境变量。

所以我一直在尝试类似的 sed 命令:

sed -n "s/\x00ENV_VAR_NAME=\([^\x00]*\)\x00/\1/p" /proc/pid/environ

但我得到了完整的环境文件作为输出。如果我只用一个静态字符串替换 \1,我会得到那个字符串加上整个环境文件:

sed -n "s/\x00ENV_VAR_NAME=\([^\x00]*\)\x00/BLAHBLAH/p" /proc/pid/environ

我应该只是在最后一个例子中得到“BLAHBLAH”。如果我摆脱空字符并使用其他一些测试数据集,则不会发生这种情况。

这导致我尝试将 \x00 转换为 \x01,这似乎确实有效:

cat /proc/pid/environ | tr '\000' '\001' | sed -n "s/\x01ENV_VAR_NAME=\([^\x01]*\)\x01/\1/p"

我在这里遗漏了一些关于 sed 的简单内容吗?还是我应该坚持这种解决方法?

【问题讨论】:

    标签: linux bash sed environment-variables


    【解决方案1】:

    尽管问题很老且已回答,但我添加了一个非常简单的单行器,可能更简单地获取文本输出和进一步处理:

    strings /proc/$PID/environ
    

    【讨论】:

    • 这是一个被严重低估的答案,可以很容易地输入| grep -E '^(ENV_NAME)='
    • 简直太棒了!
    【解决方案2】:

    您可以使用 gawk 处理列表,将记录分隔符设置为 \0,将字段分隔符设置为 =

    gawk -v 'RS=\0' -F= '$1=="ENV_VAR_NAME" {print $2}' /proc/pid/environ
    

    或者您可以在循环中使用read 来读取每个以 NUL 分隔的行。例如:

    while read -d $'\0' ENV; do declare "$ENV"; done < /proc/pid/environ
    
    echo $ENV_VAR_NAME
    

    (在子 shell 中执行此操作以避免破坏您自己的环境。)

    【讨论】:

    • 这也解决了我在匹配文件中第一个没有 \x01 的环境变量时摸索的问题。非常感谢。
    • 你拯救了我的一天。我认为这是将动态变量值传递给 systemd 启动的服务的唯一方法。
    • awk 如果变量值包含 = 不起作用?例如:awk -v 'RS=\0' -F= '$1=="LS_COLORS" {print $2}' &lt; /proc/self/environ
    • 不是我的意思,假设你有这个变量:FAIL=2+2=4
    【解决方案3】:
    cat /proc/PID/environ  | tr '\0' '\n' | sed 's/^/export /' ; 
    

    然后根据需要复制和粘贴。

    【讨论】:

    • 此代码在包含换行符的变量上失败 - 但它很短。
    【解决方案4】:

    许多用 C 语言编写的程序往往会因带有嵌入 NUL 的字符串而失败,因为 NUL 会终止 C 风格的字符串。除非专门写来处理它。

    我在命令行中使用 xargs 处理 /proc/*/environ:

    xargs -n 1 -0 < /proc/pid/environ
    

    这为您提供了每行一个 env var。如果没有命令, xargs 只会回显参数。然后,您可以通过管道轻松地在其上使用 grep、sed、awk 等。

    xargs -n 1 -0 < /proc/pid/environ | sed -n 's/^ENV_VAR_NAME=\(.*\)/\1/p'
    

    我经常使用它,因此我有一个 shell 函数:

    pidenv() 
    { 
        xargs -n 1 -0 < /proc/${1:-self}/environ
    }
    

    这会为您提供特定 pid 的环境,如果没有提供参数,则为 self。

    【讨论】:

    • 非常酷。我从来没有想过在这种角色中使用 xargs。但是,我在开始时确实避免了这种类型的解决方案,因为我想避免其中包含 \n 的 env var 值的任何问题。
    • xargs 允许您通过在每个参数上运行脚本或程序来轻松处理多行值,而不仅仅是回显它。这样,每个参数都可以独立处理,因为每次调用脚本时,它都会显示一个值,而不管其中的行数。
    • 不错! xargs 还有一个很好的修剪空白的副作用。回声'foo' | xargs | wc -c #=> 4
    • 顺便说一句,如果你想要的是一个空格分隔行中的所有env(适合执行命令),你可以这样做:xargs -n 1 -0 printf "%s " &lt; /proc/pid/environ &amp;&amp; echo
    • BusyBox xargs 似乎支持-0 选项,但在默认配置中可能未启用。 (这可能与那些运行嵌入式 Linux 的人有关。)
    【解决方案5】:

    由于某种原因,sed 与 \0 不匹配 .

    % echo -n "\00" | xxd
    0000000: 00                                       .
    % echo -n "\00" | sed 's/./a/g' | xxd
    0000000: 00                                       .
    % echo -n "\01" | xxd                
    0000000: 01                                       .
    % echo -n "\01" | sed 's/./a/g' | xxd
    0000000: 61                                       a
    

    解决方案:不要使用 sed 或使用您的解决方法。

    【讨论】: