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

M1 Mac上.NET Process.Start执行bash脚本远慢于终端问题

.NET Process调用bash脚本在M1 Mac上耗时过长问题解决

问题背景

  • 编写的bash脚本在终端执行耗时不足2秒,但通过.NET的Process.Start调用时,M1 Mac上耗时约30秒,Linux部署后执行正常。
  • 脚本内容:
#!/bin/bash
date >> test.db
tac /Users/user/Desktop/catalina.out.2022-06-17-06H30M | grep [Info] | grep -m 1000 "Duration: " >> test.txt
date >> test.db
  • .NET调用代码:
DateTime start = DateTime.Now;

Process myProc = new Process();
myProc.StartInfo.RedirectStandardOutput = true;
myProc.StartInfo.FileName = "/opt/homebrew/bin/bash";
myProc.StartInfo.Arguments = $"-c \"/Users/user/Desktop/test.sh \"";
myProc.Start();
this.result = await myProc.StandardOutput.ReadToEndAsync();
myProc.WaitForExit();

DateTime end = DateTime.Now;
TimeSpan duration = end - start;
this.duration = duration.TotalSeconds.ToString();

核心原因

M1 Mac上,.NET Process在处理非交互式bash进程的输出缓冲时存在阻塞:

  1. 脚本所有输出均写入文件,无stdout输出,但.NET仍开启了RedirectStandardOutput并等待读取,触发不必要的缓冲等待。
  2. bash在非终端环境下默认使用块缓冲,而非终端的行缓冲,导致进程结束前缓冲区未刷新,.NET端持续等待。

解决方案

方案1:关闭不必要的输出重定向

脚本无stdout输出,无需开启RedirectStandardOutput,直接移除相关配置:

Process myProc = new Process();
// 移除 RedirectStandardOutput = true
myProc.StartInfo.FileName = "/opt/homebrew/bin/bash";
myProc.StartInfo.Arguments = $"-c \"/Users/user/Desktop/test.sh\"";
myProc.Start();
myProc.WaitForExit();

方案2:直接执行脚本而非通过bash -c

利用脚本的#!/bin/bash shebang,直接调用脚本文件,避免bash -c的额外处理:

Process myProc = new Process();
myProc.StartInfo.FileName = "/Users/user/Desktop/test.sh";
myProc.StartInfo.UseShellExecute = false; // 必须设置为false以直接执行可执行文件
myProc.Start();
myProc.WaitForExit();

方案3:强制bash无缓冲输出

使用stdbuf命令强制bash的stdout/stderr无缓冲,避免阻塞:

myProc.StartInfo.FileName = "/usr/bin/stdbuf";
myProc.StartInfo.Arguments = $"-o0 -e0 /opt/homebrew/bin/bash -c \"/Users/user/Desktop/test.sh\"";

-o0表示stdout无缓冲,-e0表示stderr无缓冲,确保进程输出立即刷新。

方案4:同时处理stdout和stderr(若需保留重定向)

如果必须开启输出重定向,需同时读取stdout和stderr,避免因stderr缓冲满导致进程阻塞:

Process myProc = new Process();
myProc.StartInfo.RedirectStandardOutput = true;
myProc.StartInfo.RedirectStandardError = true;
myProc.StartInfo.FileName = "/opt/homebrew/bin/bash";
myProc.StartInfo.Arguments = $"-c \"/Users/user/Desktop/test.sh\"";
myProc.Start();

// 同时读取stdout和stderr,避免死锁
var readOutputTask = myProc.StandardOutput.ReadToEndAsync();
var readErrorTask = myProc.StandardError.ReadToEndAsync();

await Task.WhenAll(readOutputTask, readErrorTask);
this.result = await readOutputTask;
myProc.WaitForExit();

验证结果

以上方案均可解决M1 Mac上的耗时问题,使.NET调用脚本的速度与终端执行一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 03:15:46