调试神秘的git+ssh+代理故障的艰难方法&bash:没有这样的文件或目录& [英] The hard way to debug the mysterious git+ssh+proxy failure "bash: No such file or directory"

查看:22
本文介绍了调试神秘的git+ssh+代理故障的艰难方法&bash:没有这样的文件或目录&的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过SOCKS5代理克隆GitHub回购。在~/.ssh/config中,我有:

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

&qot;git克隆失败,错误bash: No such file or directory

$ git clone git@github.com: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 git@github.com
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的。我在谷歌上搜索了很多,在MacOS10.15(Catalina)上发现了很多破损的SSH案例,但没有一个解决办法对我有效。最终,我不得不查看OpenSSH代码并找出问题所在。


源文件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 == '')
 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     }

参见第203、240和248行,ssh正在尝试使用$SHELL(我没有找到与此相关的文档)运行ProxyCommand,并且它使用的execv()不会在$PATH中搜索。然后我检查了我的$SHELL

$ echo $SHELL
bash

所以这就是问题所在。$SHELL不是完整路径名可执行文件,因此execv()无法执行,错误bash: No such file or directory来自第249行中的perror()。这个错误把我弄糊涂了。前缀bash:让我认为错误来自Bash。)

解决方案:手动将SHELL设置为shell的完整路径名,例如/bin/bash(我没有在.screenrc中写shell /bin/bash,因为我还有/usr/local/bin/bash。)


那么是谁设置的SHELL=bash?为什么不设置SHELL=/bin/bash

在我的~/.screenrc我有:

shell bash

根据屏幕manual

  • shell命令

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

在我启动Screen之前,SHELLvar最初/bin/bash在我的交互式shell中,因此是Screen设置了SHELL=bash。我认为屏幕应该找出shell的完整路径名,并将SHELL设置为完整路径名,因为根据posix

此变量应表示用户首选命令语言解释器的路径名


那为什么在我的Linux系统(Debian)上也有SHELL=bash(也在屏幕上)可以正常工作?

我做了strace,得到了这个:

$ SHELL=xxx strace -f ssh git@github.com
[...]
[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
", 31xxx: No such file or directory
) = 31
[pid  5767] close(3)                    = 0
[...]

我们可以看到,它实际上是在xxx中搜索$PATH。为什么?我猜Debian肯定已经修补了openssh并改变了它的行为。(如果我了解Debian构建内部,我会验证这一点。:-)


更新2020-11/19

我从source手动编译了OpenSSH(v8.4),并在Debian上重现了同样的问题。这确认Debian已修补OpenSSH并更改其行为。

$ /usr/local/openssh-8.4/bin/ssh git@github.com
bash: No such file or directory
kex_exchange_identification: Connection closed by remote host
$ strace -f /usr/local/openssh-8.4/bin/ssh git@github.com
[...]
[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
", 32bash: No such file or directory
) = 32
[pid 21020] close(3)
[...]

这篇关于调试神秘的git+ssh+代理故障的艰难方法&bash:没有这样的文件或目录&的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆