ssh-ing 到 ec2 服务器时如何修复无限 bash 循环(bashrc + bash_profile)?

ssh-ing 到 ec2 服务器时如何修复无限 bash 循环(bashrc + bash_profile)?

我错误地.bash_profilebashrc文件中包含了源代码,反之亦然。现在,当我尝试 ssh 进入机器(ec2)时,它将卡在加载 bash 并在一秒钟内关闭连接。我有办法修复它吗?我可以将磁盘挂载到另一个 ec2 实例来修复 bash 文件吗?


更新1:我尝试了以下方法:

%  ssh -i "my-pem.pem" -t ubuntu@<server_address>.amazonaws.com "/bin/bash --noprofile --norc"
Connection to <server_address>.amazonaws.com closed.

没有其他东西出现。您知道出了什么问题吗?

对于健全性检查,如果我这样做ssh -i "my-pem.pem"ubuntu@<server_address>.amazonaws.com,消息将是

...

28 packages can be updated.
0 of these updates are security updates.
To see these additional updates run: apt list --upgradable

New release '20.04.2 LTS' available.
Run 'do-release-upgrade' to upgrade to it.


Last login: Mon Feb 22 23:17:41 2021 from ip
Connection to <server_address>.amazonaws.com closed.

解决方案

只需 ssh 到机器上并立即Ctrlc修复 bash 文件。

答案1

[更新]

这个有趣的案例值得一个更好的答案(我借用了这个关于超级用户的答案)。

我下面的原始答案取决于应该在非交互式 shell 中执行命令的事实ssh user@server command,从而防止错误.bashrc被执行。

问题出在远程 shell 上。如果是 Bash,那么有一个特殊功能可以让它执行这些 rc 文件:

(man bash) Bash 尝试确定它何时使用连接到网络连接的标准输入运行,例如何时由远程 shell 守护程序(通常为rshd)或安全 shell 守护程序 执行sshd。如果 bash 确定它正在以这种方式运行,它会读取并执行来自 的命令~/.bashrc(如果该文件存在并且可读)。如果作为 sh 调用,则不会执行此操作。该 --norc选项可用于禁止此行为,并且该 --rcfile选项可用于强制读取另一个文件,但通常不会rshd使用sshd这些选项调用 shell 或允许指定它们。

这意味着,如果您的远程 shell 是 Bash,那么即使您运行ssh user@server 'rm .bashrc',您的命令.bashrc仍然会首先执行,并且永无休止的循环将阻止rm命令执行。

请注意,这scp不会拯救您,因为它也是通过sshd调用在内部执行的命令sh -c scp ...

唯一的例外是 SFTP。sshd内置 SFTP 服务器。如果sshd配置为使用此内部 SFTP 服务器而不是外部服务器,则该服务器将不会以 启动bash -c ...

因此,如果您的远程默认 shell 是 Bash,那么您唯一的选择是使用下面的“下载-编辑-上传”方法,而不是scp使用sftp.


[原答案]

根据您的安装,这里有几个选项:

编辑你的.bashrc文件:

ssh -t user@server 'vi ~/.bashrc'

bash在没有文件的情况下运行.bashrc

ssh -t user@server '/bin/bash --noprofile --norc'

运行另一个 shell:

ssh -t user@server /bin/sh

sh是一个示例;您可以尝试服务器上可用的任何其他 shell,例如cshfish

下载-编辑-上传你有问题.bashrc

$ scp user@server:~/.bashrc /tmp/bashrc
$ vi /tmp/bashrc
$ scp /tmp/bashrc user@server:~/.bashrc

答案2

当您运行时ssh,默认情况下它会以交互模式运行 shell,并在交互模式下处理您的.bashrc.但是,如果您指定要运行的命令,它将以非交互模式调用 shell(因此它不会处理您的.bashrc)。

您可以使用它来启动交互式 shell,但为该 shell 指定命令行参数以指示它不要处理您的.bashrc

$ ssh -t user@host "/bin/bash --noprofile --norc"
bash-5.0$

如果问题出在您的.bashrc文件中,这可能会帮助您登录。但是,如果问题出在与 bash 相关的profile文件中(例如,.bash_profile),那么您可能仍然会在第一个非交互式 shell 中挂起。

答案3

一般来说,仅由交互式 shell 和登录 shell~/.bashrc获取(~/.bash_profile登录 shell 和非登录 shell 之间的区别?)。如果您仅通过 Ssh 发送命令,则既不会获得交互式 shell,也不会获得登录 shell,因此只需重命名其中一个文件(例如)ssh user@host 'mv .bashrc .bashrc.bak'即可。

但正如 Xhienne 指出的那样,有一个例外:如果由 SSH 守护进程调用,Bash 会获取 Bashrc

然而,Xhienne 和我未能重现这一点。我的测试是附加touch testfile到服务器的 Bashrc,然后尝试一个虚拟命令来查看发生了什么:ssh Quasímodo@server 'echo x'。结果:没有testfile创建。直到后来我才发现我的 Bashrc 的第一行包含

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

即,如果 shell 不是交互式的,请停止读取 Bashrc。这个巧妙的技巧实际上存在于大多数发行版中,正如在 为什么 bashrc 检查当前 shell 是否是交互式的?

结论

Andy、Xhienne 和我最初的答案(相当于通过 SSH 运行命令)将

  • 如果该片段存在于用户的远程 Bashrc 中,则成功。
  • 否则会失败,在这种情况下,您可以在以下位置找到一些选项服务器故障,其中Ctrl-C。

相关内容