代码之家  ›  专栏  ›  技术社区  ›  Birchlabs

序列化环境变量的子集

  •  1
  • Birchlabs  · 技术社区  · 7 年前

    全面的

    Tomcat建议您的所有环境定制都应该由 "$CATALINA_HOME/bin/setenv.sh" .

    setenv.sh

    首先,请注意 docker run -e

    🍔 docker run -eMY_VAR=SUP alpine env
    PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    HOSTNAME=a528b6fc264b
    MY_VAR=SUP
    no_proxy=*.local, 169.254/16
    HOME=/root
    

    如果我们想复制 把那个env变成 setenv。上海 ,简单到:

    SETENV="/usr/local/tomcat/bin/setenv.sh"
    echo '#!/bin/sh' > "$SETENV"
    echo 'export -p' >> "$SETENV"
    env >> "$SETENV"
    

    但是复制 有点违背了 --也就是说,给你的tomcat进程一个 清洁的 环境,仅 故意的


    因此,我们可以就“哪些环境变量是我们想要传递的对象”达成一致 setenv。上海 “。所有内容都带有前缀 MY_ .

    现在

    env | grep '^MY_' | sed 's/^MY_/EXPORT /'
    

    这让我们非常接近。输出如下所示:

    🍔 docker run -e MY_VAR=hey alpine sh -c "env | grep '^MY_' | sed 's/^MY_/EXPORT /'" 
    EXPORT VAR=hey
    

    env 命令:只有前缀为的env vars 我的_ . 我们可以将输出重定向到

    我为什么说“非常接近”?看来我们完了,对吗?


    试试这个尺码:

    🍔 docker run -e MY_VAR='multi                                                    
    quote> line  
    quote> string' alpine sh -c "env | grep '^MY_' | sed 's/^MY_/EXPORT /'"
    EXPORT VAR=multi
    

    我们只导出了多行字符串的第一行。

    为方便起见:多行字符串的env输出如下所示:

    🍔 docker run -e MY_VAR='multi
    line
    string' alpine env                                              
    PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    HOSTNAME=0d0afaac6bec
    MY_VAR=multi
    line
    string
    no_proxy=*.local, 169.254/16
    HOME=/root
    

    我犹豫是否尝试使用awk解决这个问题;可能还有一些我没有考虑过的复杂问题。


    编辑 :我疏忽地将其标记为 bash sh 上海 , sed grep awk , 环境

    我保留了 标记,以免惩罚在这是一个 猛击 -唯一的问题。

    但我会优先选择 上海 -兼容的答案,尤其是对于仅适用于BusyBox UNIX UTIL的答案。

    4 回复  |  直到 7 年前
        1
  •  1
  •   Gilles 'SO- stop being evil'    7 年前

    • 枚举环境变量并选择子集。

    您可以使用 export -p 如果您想以可以读回的形式导出所有变量,但解析它以仅选择某些变量比较困难。利用的一种方法 就是取消设置其他变量。这仅在没有任何环境变量是只读的情况下有效,但您可以通过运行单独的shell实例(而不是子shell)来解决这一问题。

    要收集要取消设置的变量列表,只需获取所有环境变量列表的超集,并删除要保留的变量。通过过滤 env 输出我用一个简单的 grep

    由于变量包含一个换行符,后跟一个有效的变量名和一个等号,因此偶尔会出现误报,这只会导致调用 unset

    excluded=$(env | LC_ALL=C sed -n 's/^\([A-Z_a-z][0-9A-Z_a-z]*\)=.*/\1/p' |
               grep -v 'MY_')
    sh -c 'unset $1; export -p' sh "$excluded" >setenv.sh
    

    Dash打印额外的 export PATH (无值)如果 PATH 在调用时在环境中。如果这让你感到困扰,那就换一个 sh -c … (unset PATH; sh -c …) .

        2
  •  1
  •   Charles Duffy    7 年前

    假设GNU grep:

    grep --null '^MY_' </proc/self/environ
    

    ...将以NUL分隔形式发出环境变量(换行符保持不变)。


    类似地,如果您有bash:

    while IFS= read -r -d '' vardef; do
      [[ $vardef = MY_* ]] && printf '%s\0' "$vardef"
    done </proc/self/environ
    

    注意,如果在同一shell会话中设置了这些变量,则可能需要为创建子进程 /proc/self/environ 待更新:

    (while IFS= read -r -d '' vardef; do
       [[ $vardef = MY_* ]] && printf '%s\0' "$vardef"
     done </proc/self/environ)
    
        3
  •  1
  •   anubhava    7 年前

    alpine bash .

    您可以使用此脚本提取所有 MY_*

    docker run -e MY_FOO=bar -e MY_VAR="multi' export MY_INJECTED='val" -e MY_VAR2=$'multi
    0MY_line=val
    string' alpine sh -c "awk -v RS='\06' -F= '/^MY_/{k=\$1; sub(/^[^=]+=/, \"\"); 
    gsub(/\047/, \"\047\\\\\\047\047\"); printf \"export %s=\047%s\047\n\", k, \$0
    }' /proc/self/environ"
    

    这将输出:

    export MY_FOO='bar'
    export MY_VAR='multi'\'' export MY_INJECTED='\''val'
    export MY_VAR2='multi
    0MY_line=val
    string'
    

    awk 作品:

    • -v RS='\6' :将记录分隔符设置为 \6 也适用于nul字节(假设您没有 价值)
    • -F= :将字段分隔符设置为 =
    • /^MY_/ MY_
    • $1 k
    • 使用 sub = 在里面 $0
    • print 格式化输出,以便在 $CATALINA_HOME/bin/setenv.sh 文件
    • \047
        4
  •  0
  •   Nahuel Fouilleul    7 年前

    那么...怎么样

    declare -p ${!MY_*}
    

    declare -p ${!MY_*} | sed -r 's/^declare (-[^ ]*)* MY_/export /'
    

    declare -p ${!MY_*} | sed 's/^declare \(-[^ ]*\)* MY_/export /'
    

    编辑符合posix的版本:

    一些 env printenv 接受 -0 选择结束每个输出线 \0

    env -0  | perl -ne 'BEGIN{$/="\0";$\="\n";$q="\047"}next unless /^MY_/;chomp;s/$q/$q\\$q$q/;s/=/=$q/;s/$/$q/;print'
    

    $/ : input record separator
    $\ : output record separator
    $q : variable to store single quote (\047) because of surrounding single quotes in command
    next : to filter "MY_" variables
    chomp : removes the input separator
    s/// : quote substitution
    

    编辑:posix shell中perl版本的变体

    env -0 | xargs -0 sh -c 'for entry; do [[ $entry = MY_* ]] || continue; printf "%s=\047%s\047\n" "${entry%%=*}" "$(echo "${entry#*=}" | sed '\''s/\x27/\x27\\\x27\x27/g'\'' )"; done' -