为啥在从 C# 创建的进程中运行 bash 命令时我的 $PATH 不同?
Posted
技术标签:
【中文标题】为啥在从 C# 创建的进程中运行 bash 命令时我的 $PATH 不同?【英文标题】:Why is my $PATH different when running bash commands inside a process created from C#?为什么在从 C# 创建的进程中运行 bash 命令时我的 $PATH 不同? 【发布时间】:2021-07-14 07:14:51 【问题描述】:我在 CentOS 上有一个 .NET 5 程序,它使用 .service 文件从 systemd 服务启动。它需要通过命令行执行另一个程序,所以我写了这些代码:
var processStartInfo = new ProcessStartInfo()
FileName = "/bin/bash",
Arguments = "-c \"echo $PATH\"",
WorkingDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
;
var process = Process.Start(processStartInfo);
process.WaitForExit();
当从 CentOS 的终端执行时,echo $PATH
返回/usr/lib64/qt-3.3/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/home/test_user/.local/bin:/home/test_user/bin
。
但是使用上面的代码运行echo $PATH
给我/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
为什么 2 个 $PATH 值不同?
搜索 $PATH 给了我一些关于 /etc/profile
、~/.bash_profile
、/etc/bash.bashrc
和 ~/.bashrc
的结果,但我不确定如何解释这些文件。
【问题讨论】:
在您从 C# 中启动 bash 进程的方式中,它是一种非交互式、非登录调用。在您的终端中,它是一个交互式外壳。你没有说你是如何配置你的终端的,所以我不知道它是登录还是非登录调用。所有这些都会影响执行哪些启动文件。但是,PATH
应该在环境中。如果您从终端启动了 C# 程序,它应该继承 PATH,因此错误可能在其他地方。你没有说你是如何运行你的程序的。
@user1934428 在 CentOS 上的应用程序启动器中,我选择 Konsole 来启动终端。 C# 程序通过 systemd 服务使用 .service 文件启动,其中 ExecStart=/usr/bin/dotnet /var/www/my-program/MyProgram.dll, User=root。我不确定其中任何一个是否会被视为“登录调用”。
至少它解释了为什么 PATH 没有被调用。至少它是一个非交互式调用,并且您的.bashrc
不会被处理。请参阅 bash 手册页的 INVOCATION
部分,了解 bash 进程启动时会发生什么。
@user1934428 我对交互式 shell 描述并不完全清楚。所以我使用 Konsole 是在调用一个交互式 shell,但是像我的代码一样从 C# 启动是在调用一个非交互式 shell?我也尝试查看 $BASH_ENV 的值,但 echo $BASH_ENV
给了我一个空行。
很可能,是的。为什么它应该是交互式的?您可以(如手册页中所述)打印变量$-
。如果它包含字母i
,则您处于交互式外壳中。 BASH_ENV
始终为空,除非您在某处明确设置它,但我不明白您为什么要这样做。我不明白你想从打印它中获得什么......
【参考方案1】:
问题是上面的代码调用了一个非交互式shell,而不是像使用系统控制台时那样的交互式shell。 From GNU's Bash Reference Manual, section 1.2:
Shell 可以交互或非交互方式使用。在互动 模式,它们接受从键盘输入的输入。执行时 shell 以非交互方式执行从文件中读取的命令。
交互式和非交互式 shell 在启动时检查 $PATH
值的方法不同,如第 6.2 节所述。作为交互式 shell,Bash 可以从 etc/profile
、~/.bash_profile
、~/.bash_login
和 ~/.profile
读取以检查 $PATH
值,但作为非交互式 shell,Bash 只接受环境变量 BASH_ENV
中的任何内容用作$PATH
值:
以非交互方式调用
当 Bash 以非交互方式启动时, 运行一个 shell 脚本,例如,它在 环境,如果它出现在那里就扩展它的价值,并使用 扩展值作为要读取和执行的文件的名称。
【讨论】:
以上是关于为啥在从 C# 创建的进程中运行 bash 命令时我的 $PATH 不同?的主要内容,如果未能解决你的问题,请参考以下文章
Json String Parsing 在从 MSDOS 运行时有效,但在 Windows 上的 Ubuntu 上的 Bash 中无效 [重复]