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文件,让特定用户或命令无需密码验证:
- 运行
sudo visudo编辑sudoers文件 - 添加一行规则,比如允许当前用户无密码运行
ping命令:your_username ALL=(ALL) NOPASSWD: /usr/bin/ping - 保存退出后,直接调用
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
相关产品推荐
相关产品推荐

