【问题标题】:Execute a process with the same environment variable than another process [duplicate]执行与另一个进程具有相同环境变量的进程[重复]
【发布时间】:2020-09-02 15:39:18
【问题描述】:

我想制作一个脚本,允许我执行从任何 PID 继承环境变量的命令。 这是我制作的脚本:

#!/bin/sh

VARS=$(cat -A /proc/1/environ | tr "^@" "\n")
COMMAND=""

# sh compatible loop on a variable containing multiple lines
printf %s "$VARS" | while IFS='\n' read -r var
do
    if [ "$var" != "" ]; then
        export "$var"
    fi
done

exec "$@"

虽然导出的变量可用于子进程(由exec 创建),但显然情况并非如此,因为sh my_script.sh printenv 不显示/proc/1/environ 中的环境变量。

我还尝试了以下脚本:

#!/bin/sh

VARS=$(cat -A /proc/1/environ | tr "^@" "\n")
COMMAND=""

# sh compatible loop on a variable containing multiple lines
printf %s "$VARS" | while IFS='\n' read -r var
do
    if [ "$var" != "" ]; then
        # Replace 'VAR=var' by 'VAR="var"' for eval
        # sed replace only the first occurence of the '=' due of the missing /g parameter
        escaped=$(echo $var | sed -e 's/=/="/')\"
        COMMAND="${COMMAND} ${escaped}"
    fi
done

COMMAND="${COMMAND} $@"
eval $COMMAND

但是,即使评估的命令看起来像 VAR=value my_commandeval 似乎也不会导出变量。

我应该如何满足我的需求?

提前致谢

【问题讨论】:

  • 替换 NUL 字符我想你想要tr "\0" "\n"
  • 管道连接到您的while read 循环是问题所在。见BashFAQ #42
  • @CharlesDuffy 我尝试使用命名管道(根据 BashFAQ 中兼容的解决方法 POSIX),但我仍然看不到我的环境变量。我的新代码是:bash #!/bin/sh VARS=$(cat /proc/1/environ | tr "\n" " " | tr "\0" "\n") mkfifo mypipe echo "$VARS" > mypipe & # sh compatible loop on a variable containing multiple lines while IFS='\n' read -r var do if [ "$var" != "" ]; then export "$var" fi done < mypipe rm mypipe exec "$@"
  • 一方面,IFS='\n' 设置了两个分隔符,反斜杠和n;它没有设置换行文字。不过,老实说,如果你只有sh,我会用完全不同的语言——C、Go、Python 等——而不是构建一个无法正确处理所有环境变量的有缺陷的版本。
  • 也就是说,等我喝完咖啡坐在电脑前,我会回来仔细看看。

标签: linux shell


【解决方案1】:

应该可以工作(在 RHEL 7 上测试)

#!/bin/bash

locPROC=$1
locCMD=$2

if [[ -z $locPROC || -z $locCMD ]]; then
        exit
fi

if [[ -r /proc/${locPROC}/environ ]]; then
    while IFS= read -r -d '' line; do
        #Making sure it's properly quoted
        locVar="${line/=/=\"}\""
        #You probably don't want to mess with those
        if [[ ${locVar:0:1} != "_" && ${locVar} != A__z* ]]; then
            eval "$locVar"
            eval "export ${locVar%%=*}"
        fi
    done < "/proc/${locPROC}/environ"

    $locCMD
else
    echo "Environment file is either inexistant or unreadable"
fi

已编辑:根据 cmets(仍在使用 eval...必须阅读更多内容:))

【讨论】:

  • &lt;&lt;&lt; 是一个不幸的决定。使用while IFS= read -r -d '' line; dodone &lt;"/proc/$locPROC/environ" 更可靠——那么你就不用依赖cat -A 处理东西,而是可以让bash 直接读取原始格式的NUL 分隔文件。
  • 此外,与使用 eval 相比,还有 很多 更好、更安全的方法来执行间接分配。您不希望以前以类似于 myVar='$(rm -rf ~)' 的方式设置的变量在您尝试分配时导致 rm 运行。
  • 玩 IFS 是我最讨厌的事情之一……但是,如果您认为它更好,那么您对查尔斯的了解比我多。 eval 在整个字符串上,包括“=”,不是吗,不是值……但是 Bash 中的间接赋值又不是我的强项(实际上认为这不可能像 Ksh 中的“nameref”) .
  • bash 从 4.2 版开始就有 namerefs;但是即使没有它们,您也可以进行间接分配,例如printf -v "$varname" %s "$value"。见BashFAQ #6
  • ...并回复:更改IFSwhile IFS= read ... 方法将更改范围限定为read,因此它不会影响任何其他代码。
猜你喜欢
  • 1970-01-01
  • 2016-10-20
  • 1970-01-01
  • 2010-09-17
  • 2021-11-04
  • 1970-01-01
  • 2011-06-20
  • 1970-01-01
  • 2020-10-29
相关资源
最近更新 更多