调试神秘的git+ssh+proxy失败“bash:没有这样的文件或目录”的艰难方法

2024-04-28

我正在尝试通过 SOCKS5 代理克隆 github 存储库。在~/.ssh/config I have:

Host github.com *.github.com
    ProxyCommand /usr/bin/nc -X 5 -x 127.0.0.1:7070 %h %p

git clone因错误而失败bash: No such file or directory:

$ git clone [email protected] /cdn-cgi/l/email-protection:aureliojargas/sedsed.git
Cloning into 'sedsed'...
bash: No such file or directory
kex_exchange_identification: Connection closed by remote host
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

我手动尝试过ssh命令也失败了:

$ ssh -v [email protected] /cdn-cgi/l/email-protection
OpenSSH_8.1p1, LibreSSL 2.7.3
debug1: Reading configuration data /Users/pynexj/.ssh/config
debug1: /Users/pynexj/.ssh/config line 16: Applying options for github.com
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 47: Applying options for *
debug1: Executing proxy command: exec /usr/bin/nc -X 5 -x 127.0.0.1:7070 github.com 22
                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
debug1: identity file /Users/pynexj/.ssh/id_rsa type 0
debug1: identity file /Users/pynexj/.ssh/id_rsa-cert type -1
debug1: identity file /Users/pynexj/.ssh/id_dsa type -1
debug1: identity file /Users/pynexj/.ssh/id_dsa-cert type -1
debug1: identity file /Users/pynexj/.ssh/id_ecdsa type -1
debug1: identity file /Users/pynexj/.ssh/id_ecdsa-cert type -1
bash: No such file or directory
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
debug1: identity file /Users/pynexj/.ssh/id_ed25519 type -1
debug1: identity file /Users/pynexj/.ssh/id_ed25519-cert type -1
debug1: identity file /Users/pynexj/.ssh/id_xmss type -1
debug1: identity file /Users/pynexj/.ssh/id_xmss-cert type -1
debug1: Local version string SSH-2.0-OpenSSH_8.1
kex_exchange_identification: Connection closed by remote host

然后我手动尝试了nc命令并且它确实有效:

$ /usr/bin/nc -X 5 -x 127.0.0.1:7070 github.com 22
SSH-2.0-babeld-8cd15329
^C

SOCKS5 代理也可以正常工作:

$ curl -x socks5://127.0.0.1:7070/ https://github.com/ > foo.html
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  214k    0  214k    0     0  86775      0 --:--:--  0:00:02 --:--:-- 86775

我很好奇谁(以及为什么)产生了错误bash: no such file or directory.


对我来说,这个问题是 macOS 特有的。我在 Google 上搜索了很多,发现 macOS 10.15 (Catalina) 上有许多损坏的 SSH 案例,但没有一个解决方法对我有用。最终我不得不查看 OpenSSH 代码并找出问题所在。


在源文件中sshconnect.c https://github.com/openssh/openssh-portable/blob/master/sshconnect.c:

 194 static int
 195 ssh_proxy_connect(struct ssh *ssh, const char *host, const char *host_arg,
 196     u_short port, const char *proxy_command)
 197 {
 ...
 ...
 201     char *shell;
 202
 203     if ((shell = getenv("SHELL")) == NULL || *shell == '\0')
 204         shell = _PATH_BSHELL;
 ...
 ...
 211     command_string = expand_proxy_command(proxy_command, options.user,
 212         host, host_arg, port);
 213     debug("Executing proxy command: %.500s", command_string);
 214
 215     /* Fork and execute the proxy command. */
 216     if ((pid = fork()) == 0) {
 217         char *argv[10];
 ...
 ...
 240         argv[0] = shell;
 241         argv[1] = "-c";
 242         argv[2] = command_string;
 243         argv[3] = NULL;
 244
 245         /* Execute the proxy command.  Note that we gave up any
 246            extra privileges above. */
 247         ssh_signal(SIGPIPE, SIG_DFL);
 248         execv(argv[0], argv);
 249         perror(argv[0]);
 250         exit(1);
 251     }

See line 203, 240 and 248, ssh is trying to run the ProxyCommand with $SHELL (I found no doc for this) and it's using execv() https://man7.org/linux/man-pages/man3/exec.3.html which would not search in $PATH. Then I checked my $SHELL:

$ echo $SHELL
bash

So that's the problem. $SHELL is not a full pathname executable so execv() failed to execute it and the error bash: No such file or directory is from perror() https://man7.org/linux/man-pages/man3/perror.3.html in line 249. (The error confused me a lot. The prefix bash: made me think the error is from Bash.)

SOLUTION: Manually set SHELL to the shell's full pathname, e.g. /bin/bash. (I did not write shell /bin/bash in .screenrc because I also has /usr/local/bin/bash.)


那谁定SHELL=bash?为什么没有设置SHELL=/bin/bash?

In my ~/.screenrc I have:

shell bash

根据画面manual https://man7.org/linux/man-pages/man1/screen.1.html:

  • shell command

    设置用于创建新 shell 的命令。这会覆盖环境变量的值$SHELL.

The SHELLvar 最初是/bin/bash在我启动 screen 之前在我的交互式 shell 中,所以是 screen 进行设置SHELL=bash。我认为 screen 应该找出 shell 的完整路径名并设置SHELL到完整路径名,因为,根据posix https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html:

该变量应代表一个pathname用户首选的命令语言解释器。


那么为什么它在我的 Linux 系统(Debian)上运行得很好呢?SHELL=bash也是(也在屏幕上)?

I did a strace https://man7.org/linux/man-pages/man1/strace.1.html并得到这个:

$ SHELL=xxx strace -f ssh [email protected] /cdn-cgi/l/email-protection
[...]
[pid  5767] rt_sigaction(SIGPIPE, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
[pid  5767] execve("/root/bin/xxx", ["xxx", "-c", "exec nc -X 5 -x 127.0.0.1:7070 g"...], 0x561e33a599a0 /* 33 vars */) = -1 ENOENT (No such file or directory)
[pid  5767] execve("/usr/local/bin/xxx", ["xxx", "-c", "exec nc -X 5 -x 127.0.0.1:7070 g"...], 0x561e33a599a0 /* 33 vars */) = -1 ENOENT (No such file or directory)
[pid  5767] execve("/usr/local/sbin/xxx", ["xxx", "-c", "exec nc -X 5 -x 127.0.0.1:7070 g"...], 0x561e33a599a0 /* 33 vars */) = -1 ENOENT (No such file or directory)
[pid  5767] execve("/usr/sbin/xxx", ["xxx", "-c", "exec nc -X 5 -x 127.0.0.1:7070 g"...], 0x561e33a599a0 /* 33 vars */) = -1 ENOENT (No such file or directory)
[pid  5767] execve("/usr/bin/xxx", ["xxx", "-c", "exec nc -X 5 -x 127.0.0.1:7070 g"...], 0x561e33a599a0 /* 33 vars */) = -1 ENOENT (No such file or directory)
[pid  5767] execve("/sbin/xxx", ["xxx", "-c", "exec nc -X 5 -x 127.0.0.1:7070 g"...], 0x561e33a599a0 /* 33 vars */) = -1 ENOENT (No such file or directory)
[pid  5767] execve("/bin/xxx", ["xxx", "-c", "exec nc -X 5 -x 127.0.0.1:7070 g"...], 0x561e33a599a0 /* 33 vars */) = -1 ENOENT (No such file or directory)
[pid  5767] dup(2)                      = 3
[pid  5767] fcntl(3, F_GETFL)           = 0x8402 (flags O_RDWR|O_APPEND|O_LARGEFILE)
[pid  5767] fstat(3, {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x21), ...}) = 0
[pid  5767] write(3, "xxx: No such file or directory\n", 31xxx: No such file or directory
) = 31
[pid  5767] close(3)                    = 0
[...]

As we can see, it's actually searching xxx in $PATH. Why? I guess Debian must have patched openssh and changed its behavior. (I would have verified this if I know Debian build internals. :-)


更新2020-11-19:

我手动编译了 OpenSSH (v8.4)source https://github.com/openssh/openssh-portable并在 Debian 上重现了同样的问题。这证实 Debian 已经修补了 OpenSSH 并改变了其行为。

$ /usr/local/openssh-8.4/bin/ssh [email protected] /cdn-cgi/l/email-protection
bash: No such file or directory
kex_exchange_identification: Connection closed by remote host
$ strace -f /usr/local/openssh-8.4/bin/ssh [email protected] /cdn-cgi/l/email-protection
[...]
[pid 21020] rt_sigaction(SIGPIPE, {sa_handler=SIG_DFL, sa_mask=~[RTMIN RT_1], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7f19a05a9840}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
[pid 21020] execve("bash", ["bash", "-c", "exec nc -X 5 -x 127.0.0.1:7070 g"...], 0x5566982872f0 /* 33 vars */) = -1 ENOENT (No such file or directory)
[pid 21020] dup(2)                      = 3
[pid 21020] fcntl(3, F_GETFL)           = 0x8402 (flags O_RDWR|O_APPEND|O_LARGEFILE)
[pid 21020] fstat(3, {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x25), ...}) = 0
[pid 21020] write(3, "bash: No such file or directory\n", 32bash: No such file or directory
) = 32
[pid 21020] close(3)
[...]
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

调试神秘的git+ssh+proxy失败“bash:没有这样的文件或目录”的艰难方法 的相关文章

  • 如何在 MFC 中调整对话框大小时移动控件?

    我已经在 MFC 中创建了对话框视图 从下图中可以清楚地看到 如滑块控件和编辑框等 当我调整对话框大小时 这些控件不会移动 在此输入图像描述 https i stack imgur com 7OxAK jpg 我想移动控件以适应对话框 但不
  • 将指针转换为浮点数?

    我有一个unsigned char 通常 这指向一块数据 但在某些情况下 指针就是数据 即 铸造一个int的价值unsigned char 指针 unsigned char intData unsigned char myInteger 反
  • 隐式方法组转换陷阱

    我想知道为什么给定代码的输出 在 LinqPad 中执行 void Main Compare1 Action Main Dump Compare2 Main Dump bool Compare1 Delegate x return x Ac
  • 如何从 List 中的字符串中删除数字/数字?

    我有一个字符串列表 List
  • 使用 Selenium for C# 登录 Facebook

    我一直在使用 Selenium C 框架并尝试进行 facebook 登录 但没有任何运气 这是我到目前为止得到的 基于这篇文章 使用 Selenium 测试 Facebook Connect 应用程序 https stackoverflo
  • 如何防止字符串被截留

    我的理解 可能是错误的 是 在 C 中 当你创建一个字符串时 它会被实习到 实习生池 中 这保留了对字符串的引用 以便多个相同的字符串可以共享操作内存 但是 我正在处理很多很可能是唯一的字符串 一旦完成每个字符串 我需要将它们从操作内存中完
  • 枚举器上的 [[maybe_unused]]

    查看规格 maybe unused http en cppreference com w cpp language attributes 它指出 出现在类 typedef 变量 非静态数据成员 函数 枚举或枚举器的声明中 如果编译器对未使用
  • Create CFrameWnd 给出了第一次机会异常——为什么?

    我正在尝试使用基于 CFrameWnd 的代码编写一个简单的 MFC 应用程序 该应用程序在可滚动窗口中绘制 下面的代码改编自 Prosise Programming Windows with MFC 第 2 版 第 89ff 页 当我在调
  • 为什么C++变量是指针时不需要正确定义?

    我对 C 语言完全陌生 特别是指针 经验主要是 PHP 并且希望对以下内容进行一些解释 我已经尝试寻找答案 这两行代码如何能够在我的程序中完成完全相同的工作 第二行似乎违背了我迄今为止所学到和理解的关于指针的一切 char disk 3 D
  • std::string 在 Visual Studio 上的具体行为?

    我有一个项目需要读取 写入大文件 我决定使用 ifstream read 将这些文件一次性放入内存中 放入 std string 中 这似乎是在 C 中执行此操作的最快方法 http insanecoding blogspot com 20
  • C# 的空条件委托调用线程安全吗? [复制]

    这个问题在这里已经有答案了 这就是我一直以来编写事件引发者的方式 例如属性更改 public event PropertyChangedEventHandler PropertyChanged private void RaisePrope
  • Qt mouseReleaseEvent() 未触发?

    我有一个显示图片的库 我们称之为 PictureGLWidget 其中 class PictureGLWidget public QGLWidget 所以 PictureGLWidget 扩展了 QGLWidget 在PictureGlWi
  • Active Directory UserPrincipal.Current.GetGroups() 返回本地组而不是 Web 服务器上的组

    以下内容在我的本地开发盒上效果很好 但是 当我将其移动到网络服务器时 它失败了 甚至不会记录错误 public static List
  • C 的“char”使用什么字符集? [复制]

    这个问题在这里已经有答案了 简单的问题 我最近开始用 C 编程 有一个简单的问题 C 编程语言在其 char 类型中使用什么字符集 例如 ASCII 还是取决于软件 操作系统 char 本质上是 1 个字节 主要在所有操作系统上 所以默认情
  • 如何解释“错误C2018:未知字符'0x40'?[关闭]

    Closed 这个问题需要调试细节 help minimal reproducible example 目前不接受答案 在编译一些代码时 我收到以下信息 错误 C2018 未知字符 0x40 我想知道如何解决这样的问题 这是我要开始的地方
  • 实体框架代理创建

    我们可以通过使用来停止在上下文构造函数中创建代理 this Configuration ProxyCreationEnabled false 在 EF 4 1 中创建代理有哪些优点和缺点 代理对于两个功能是必需的 延迟加载 导航属性在第一次
  • 如何将 Metro 应用部署到桌面?

    我正在尝试将我的 C 应用程序部署到我的 Windows 8 Metro 桌面 我可以在 bin 文件夹中看到部署的文件 但是当我尝试打开它们时 出现以下错误 该应用程序只能在 AppContainer 的上下文中运行 我检查了属性上下文菜
  • 在类中使用 std::chrono::high_resolution_clock 播种 std::mt19937 的正确方法是什么?

    首先 大家好 这是我在这里提出的第一个问题 所以我希望我没有搞砸 在写这篇文章之前我用谷歌搜索了很多 我对编码 C 很陌生 我正在自学 考虑到有人告诉我 只为任何随机引擎播种一次是一个很好的做法 我在这里可能是错的 什么是正确 最佳 更有效
  • 如何向 ItemsControl 中的 WPF 按钮添加相同的命令

    如何将命令添加到 wpf 按钮 该按钮是ItemsControl并正在修改ItemsSource itself 这是我的 XAML
  • FakeItEasy 代理方法调用实际实现

    我正在尝试将对假对象的调用代理到实际的实现 这样做的原因是我希望能够使用 Machine Specifications 的 WasToldTo 和 WhenToldTo 它们仅适用于接口类型的伪造 因此 我正在执行以下操作来代理对我的真实对

随机推荐