2017-02-07 67 views
0

内工作。如果我有一个简单的bash脚本set_token.shEVAL命令不循环

#!/bin/bash 

output='export AWS_ACCESS_KEY_ID="111" 
export AWS_SECRET_ACCESS_KEY="222" 
export AWS_SESSION_TOKEN="333"' 

echo "$output" | while read line; do eval $line; done 

执行的set_token.sh没有成功设置3个的环境变量。但是,如果我分别在每行上运行eval,它就可以工作。

$ eval 'export AWS_ACCESS_KEY_ID="111"' 
$ eval 'export AWS_SECRET_ACCESS_KEY="222"' 
$ eval 'export AWS_SESSION_TOKEN="333"' 

这是为什么?

+5

您在管道中设置子shell环境中的变量;见[BashFAQ 24](http://mywiki.wooledge.org/BashFAQ/024)。 –

+0

@Tony Vu:你打算让我们明确你的要求吗?你的问题解决了还是卡住了? – Inian

+1

修复[BashFAQ#24](http://mywiki.wooledge.org/BashFAQ/024)后,执行脚本将设置三个变量...并退出,新分配的变量随着死亡而消失它们被设置的shell。export一个变量修改* child *进程的环境,而不是父进程。 –

回答

3

可以达到预期的效果没有一个循环,并没有eval

​​

<()构造是一个过程替换。它执行里面的命令,创建一个FIFO(特殊的先入先出文件),然后转换成一个实际的文件路径(指向FIFO),source可以读取。

当然,您也可以将实际作业存储在文件中,而不是将它们放在output变量中。

source config_file 

source命令(或它的更标准的形式.)从文件中读取的命令和在当前shell执行它们,而无需启动一个单独的进程或子外壳,在源文件,以便变量分配工作。对于配置文件很有用,但是当然你必须确保没有人可以在这些文件中放置任意命令,因为这会带来安全风险。

重要

如果你想将声明中的脚本(set_token.sh你的情况),这个脚本必须进行采购(即source.执行),而不是与bash或通过调用执行它直接(如果它是可执行的)。除source.之外的任何方法都将启动子进程,并且子进程无法分配变量,之后父进程将看到该变量。采购并不会创建一个单独的流程,这就是分配工作的原因。 export关键字将使分配仅对子进程可见,它们无法使分配对父进程可见。

+0

谢谢,但它没有工作 –

+2

@TonyVu请参阅我添加到我的答案的重要部分,我强烈怀疑解释为什么它不适合你(因为这项技术本身有效,这是毫无疑问的)。 – Fred

+1

嗨@Fred,使用源或。作品。 –

1

不确定为什么你想在这种情况下使用eval。为什么不更直接设置的变量是这样的:

export AWS_ACCESS_KEY_ID="111" 
export AWS_SECRET_ACCESS_KEY="222" 
export AWS_SESSION_TOKEN="333" 

你的循环在副壳(因为echo "$output" | ...)上运行,这就是为什么你的变量外可见。这不是eval不工作!别担心 - 这发生在很多人身上。

如果您在使用循环和eval坚持,你可以使用进程替换< <(command)

while read line; do eval $line; done < <(printf "%s\n" "$output") 
+0

'++'为正确的方式,顺便说一句嵌入你的答案在我的,强调不使用'eval'并推荐其他方式。 – Inian

+0

谢谢。 在我的情况下,变量是动态生成的。为了简单起见,我只是使用了输出。这似乎是正确的原因,但流程替换对我来说仍然不起作用。 –

+0

@TonyVu:那你还在找什么? – Inian

0

Fred's helpful answer包含一个可行的解决方案和良好的指针(和原始方法的问题在Bash FAQ #24 - "I set variables in a loop that's in a pipeline. Why do they disappear after the loop terminates?"解释)。

这就是说,在您的具体方案 - 假设你愿意接受使用eval的风险 - 你可以将它直接你多行字符串:

#!/bin/bash 

output='export AWS_ACCESS_KEY_ID="111" 
export AWS_SECRET_ACCESS_KEY="222" 
export AWS_SESSION_TOKEN="333"' 

# This defines all 3 AWS_* environment variables. 
eval "$output" 

重申弗雷德点:对于环境变量采取在当前壳效应,必须脚本(使用内置.或它的(有效)别名source):

. ./set_token.sh