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

sudo结合bash进程替换失效问题排查及解决方案咨询

问题原因与解决方法

核心原因

你遇到的/dev/stdin: Permission denied错误,本质是bash的source /dev/stdin操作并非直接读取当前进程已打开的标准输入(fd 0),而是尝试打开/dev/stdin这个路径文件。尽管/dev/stdin是全局可读的符号链接,但解析它时需要访问/proc/self/fd/0,而sudo切换到nobody后,bash通过路径打开的方式触发了系统权限检查——这个管道由root进程创建,虽然nobody继承了fd 0,但路径打开的方式绕开了直接使用已打开的文件描述符,最终导致读取失败。

从输出的/proc/3243/fd/0权限可以看到,nobody确实拥有该文件描述符的读取权限,只是source的路径打开方式不适用这种场景。

解决方法

以下是三种可靠的解决方案:

方案1:让bash直接读取标准输入执行

不需要用source /dev/stdin,改用bash -s让bash从标准输入读取命令并执行,直接利用已继承的fd 0,避免路径打开的权限问题:

#! /bin/bash
sudo -u nobody \
    bash -s \
    < <(echo "A=$(ls /root/.profile)")

如果需要验证变量,把验证逻辑也写入输入流:

#! /bin/bash
sudo -u nobody \
    bash -s \
    < <(echo "A=$(ls /root/.profile)"; echo "echo 'A=$A'")

方案2:将内容嵌入bash命令字符串

把要执行的内容直接作为bash -c的命令参数,避免管道传递的权限问题:

#! /bin/bash
content="A=$(ls /root/.profile)"
sudo -u nobody bash -c "$content; echo 'A=$A'"

如果内容包含特殊字符(如引号、空格),用printf "%q"做转义处理:

#! /bin/bash
content="A=$(ls /root/.profile)"
sudo -u nobody bash -c "$(printf "%q" "$content"); echo 'A=$A'"

方案3:临时文件中转(适合长/复杂内容)

将内容写入临时文件,设置nobody可读权限后再source,这种方式最稳妥:

#! /bin/bash
temp_file=$(mktemp)
echo "A=$(ls /root/.profile)" > "$temp_file"
chmod o+r "$temp_file"
sudo -u nobody bash -c "source $temp_file; echo 'A=$A'"
rm -f "$temp_file"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 09:54:24