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

如何在保留控制台密码提示的同时通过管道调用SSH

自定义git-remote-<transport>助手的跨平台管道与SSH密码提示问题

我正在编写自定义git-remote-<transport>助手,该助手可在必要时使用自研传输协议,也能回退到基于Smart Protocol的标准SSH协议。这意味着需要实现Git的git_connect方法,调用SSH建立连接并执行远程git-upload-pack或git-receive-pack命令,同时将Git进程的stdin/stdout管道传输至子SSH进程,流程如下:

+-----------------------------------------------------------+
| Process: git                      Handles: writer, reader |
+--------------------------------------------- | ----- ^ ---+
                                             (pipe)  (pipe)
+--------------------------------------------- v ----- | ---+
| Process: git-remote-mytransport   Handles: stdin , stdout |
|                                               \      /    |
|                                            (custom logic) |
|                                               /      \    |
|                                            writer, reader |
+--------------------------------------------- | ----- ^ ---+
                                             (pipe)  (pipe)
+--------------------------------------------- v ----- | ---+
| Process: ssh                      Handles: stdin , stdout |
|                                               \      /    |
|                                              TCP socket   |
+------------------------------------------------- ^ -------+
                                                   |
                                                   v
                                            Remote SSH Host

仅处理stdin/stdout句柄的实现很简单,但SSH的密码提示功能会因盲目重定向管道句柄而失效。

当前实现参考了相关代码,Windows测试命令如下:

go build -o .\bin\git-remote-mytransport .\git-remote-mytransport.go
SET PATH=%CD%\bin;%PATH%
git clone mytransport://dummy

当前实现能正常弹出密码提示,但Git与SSH的stdin/stdout管道传输异常;若直接传递os.Stdin和os.Stdout启动SSH,管道正常但密码提示失效。

Windows的控制台架构较为复杂,经过一天研究仍未实现Git到SSH的可用管道且不破坏密码提示。需要在Windows/Linux/macOS多平台解决该问题,当前用Golang开发,也可接受基于原生API的C/C++方案以便移植。

2023年7月3日更新:参考Microsoft ConPTY文章及示例代码后尝试如下方案,但仍无法工作:

HANDLE hLocalReader, hLocalWriter, hRemoteReader, hRemoteWriter;
CreatePipe(&hLocalReader, &hRemoteWriter, NULL, 0);
CreatePipe(&hRemoteReader, &hLocalWriter, NULL, 0);

HPCON hPC;
CreatePseudoConsole(consoleSize, hRemoteReader, hRemoteWriter, 0, &hPC);

HANDLE hConIn = CreateFile("CONIN$", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
HANDLE hConOut = CreateFile("CONOUT$", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

DWORD consoleMode;
GetConsoleMode(hConOut, &consoleMode);
SetConsoleMode(hConOut, consoleMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);

// on another thread, stream hConIn data to hLocalWriter
// on another thread, stream hLocalReader data to hConOut

HANDLE handles[3];

HANDLE handles[0] = GetStdHandle(STD_INPUT_HANDLE);
HANDLE handles[1] = GetStdHandle(STD_OUTPUT_HANDLE);
HANDLE handles[2] = GetStdHandle(STD_ERROR_HANDLE);

pStartupInfo->hStdInput = handles[0];
pStartupInfo->hStdOutput = handles[1];
pStartupInfo->hStdError = handles[2];

UpdateProcThreadAttribute(pStartupInfo->lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, handles, sizeof(handles), NULL, NULL);

UpdateProcThreadAttribute(pStartupInfo->lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE, hPC, sizeof(HPCON), NULL, NULL);

CreateProcess(
szCommand,                      // Command name
szArgs,                         // Command arguments
NULL,                           // Process handle not inheritable
NULL,                           // Thread handle not inheritable
TRUE,                           // Inherit handles
EXTENDED_STARTUPINFO_PRESENT,   // Creation flags
NULL,                           // Use parent's environment block
NULL,                           // Use parent's starting directory 
&startupInfo.StartupInfo,       // Pointer to STARTUPINFO
&piClient);                     // Pointer to PROCESS_INFORMATION

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 00:05:27