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

Linux下用带美元符号的密码高权限运行C#(.NET6)进程失败求助

在Linux下用含$的密码通过.NET 6以sudo权限运行进程的问题

问题场景

在Linux系统中,尝试使用包含美元符号($)的密码,通过.NET 6的Process类以高权限运行进程,但始终失败,具体尝试过程如下:

第一次尝试:直接调用echo

最初编写了以下代码:

var stInfo = new ProcessStartInfo
{
    FileName = "echo",
    Arguments = " 'pas$word' | sudo -S ping 127.0.0.1",
    UseShellExecute = false,
    RedirectStandardOutput = true,
    RedirectStandardError = true,
    CreateNoWindow = true,
};

结果所有参数都被当作echo的输出,标准输出内容为:

'pas$word' | sudo -S ping 127.0.0.1

第二次尝试:通过bash调用

参考终端中运行/bin/bash -c "echo 'pas\$word' | sudo -S ping 127.0.0.1"的方式,修改代码为:

var stInfo = new ProcessStartInfo
{
    FileName = "/bin/bash",
    Arguments = "-c \"echo 'pas\$word' | sudo -S ping 127.0.0.1\"",
    UseShellExecute = false,
    RedirectStandardOutput = true,
    RedirectStandardError = true,
    CreateNoWindow = true,
};

但依然失败,标准错误输出显示密码验证失败:

[sudo] password for user: Sorry, try again.
[sudo] password for user: 
sudo: no password was provided
sudo: 1 incorrect password attempt

多次参数尝试

尝试了多种Arguments参数组合:

Arguments = "-c \"echo pas$word | sudo -S ping 127.0.0.1\""
Arguments = "-c \"echo 'pas$word' | sudo -S ping 127.0.0.1\""
Arguments = "-c \"echo pas\\$word | sudo -S ping 127.0.0.1\""
Arguments = "-c \"echo 'pas\\$word' | sudo -S ping 127.0.0.1\""
Arguments = "-c \"echo pas\\\\$word | sudo -S ping 127.0.0.1\""
Arguments = "-c \"echo 'pas\\\\$word' | sudo -S ping 127.0.0.1\""

所有尝试均得到相同的错误结果,改用ArgumentList替代Arguments也无法解决问题。

更新:排除$符号问题

将密码改为不含美元符号的内容后,仍然出现相同的密码验证错误,说明问题并非来自美元符号的转义,而是密码注入到进程的方式存在问题。

解决方法

方法1:通过StandardInput直接写入密码

不要用管道拼接命令,而是启动sudo进程后,通过StandardInput直接写入密码,避免shell转义和管道的问题:

var stInfo = new ProcessStartInfo
{
    FileName = "sudo",
    Arguments = "-S ping 127.0.0.1",
    UseShellExecute = false,
    RedirectStandardOutput = true,
    RedirectStandardError = true,
    RedirectStandardInput = true, // 必须开启输入重定向
    CreateNoWindow = true,
};

using var process = Process.Start(stInfo);
// 写入密码,注意要加换行符,sudo需要回车确认
process.StandardInput.WriteLine("pas$word");
process.StandardInput.Flush();

// 读取输出和错误
var output = process.StandardOutput.ReadToEnd();
var error = process.StandardError.ReadToEnd();
process.WaitForExit();

这种方式绕过shell命令解析,直接和sudo进程交互,能准确传递包含特殊字符的密码。

方法2:配置sudo免密(生产环境谨慎使用)

如果不需要每次输入密码,可以修改sudoers文件,让特定用户或命令无需密码验证:

  1. 运行sudo visudo编辑sudoers文件
  2. 添加一行规则,比如允许当前用户无密码运行ping命令:
    your_username ALL=(ALL) NOPASSWD: /usr/bin/ping
    
  3. 保存退出后,直接调用sudo ping 127.0.0.1即可,无需输入密码。

方法3:使用bash -c时的正确转义

如果一定要用bash管道的方式,需确保C#字符串中的转义正确传递到bash。正确的参数写法:

// 普通字符串转义
Arguments = "-c \"echo \\\"pas\\$word\\\" | sudo -S ping 127.0.0.1\"";
// 或用逐字字符串避免C#转义
Arguments = @"-c ""echo 'pas$word' | sudo -S ping 127.0.0.1""";

不过这种方式依然存在shell解析风险,不如直接写入StandardInput可靠。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 03:42:50