You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Bash脚本的sudo heredoc中设置变量的方法求助

解决sudo切换用户后脚本变量无法正确设置的问题

这个问题的核心是here-document(即<< EOF这种输入重定向)的变量解析时机在搞鬼,我来给你拆解清楚并解决:

为什么你的代码会失效?

当你使用<< EOF而没有给EOF加引号时,当前执行sudo的shell会先解析所有的变量引用(比如${V})和命令替换(比如$(ls)),再把解析后的内容传给sudo -u other_user bash执行。

举个例子看你的第一个代码块:

sudo -u other_user bash << EOF
V=test
echo "${V}"
EOF

当前shell会先解析${V},而此时你的当前shell里根本没设置过V变量,所以解析后echo "${V}"就变成了echo "",传给子shell后自然输出空。

第二个代码块里的$(ls)也是一样,它会先在当前用户的环境下执行ls,而不是切换到other_user后执行,然后把结果赋值给当前shell的V(但你没在当前shell定义V,最后还是输出空)。

两种有效的解决方案

方案1:用单引号包裹EOF(推荐)

给EOF加上单引号'EOF',这样当前shell会完全不解析here-document里的内容,直接把原内容传给sudo后的bash执行,变量和命令替换都会在目标用户的shell环境里处理:

基础示例修正后:

sudo -u other_user bash << 'EOF'
V=test
echo "${V}"
EOF

执行后会输出test,符合预期。

贴近实际的场景代码修正后:

sudo -u other_user bash << 'EOF'
cd
V=$(ls)
echo "${V}"
EOF

这时候cd会切换到other_user的家目录,$(ls)会列出该目录下的文件,V会被正确赋值并输出。

方案2:转义变量和命令替换

如果你不想给EOF加引号,可以手动转义所有需要在子shell里解析的变量和命令替换,在前面加反斜杠\:

基础示例:

sudo -u other_user bash << EOF
V=test
echo "\${V}"
EOF

实际场景示例:

sudo -u other_user bash << EOF
cd
V=\$(ls)
echo "\${V}"
EOF

这种方式也能达到效果,但如果脚本里有大量变量和命令替换,写起来会很繁琐,所以更推荐方案1。

总结

本质是要区分当前shell的解析阶段和目标用户shell的执行阶段,通过单引号包裹EOF或者转义的方式,让变量和命令替换在目标用户的shell环境里被处理,就能解决变量未设置的问题了。

内容的提问来源于stack exchange,提问作者Ryan Haining

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:31:20