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

Joh*_* M. 7 bash ssh amazon-ec2

我错误地.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.
Run Code Online (Sandbox Code Playgroud)

其他什么都没有出现。你知道出了什么问题吗?

对于健全性检查,如果我这样做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.
Run Code Online (Sandbox Code Playgroud)

解决方案

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

Qua*_*odo 6

通常,~/.bashrc仅由交互式 shell 和~/.bash_profile登录 shell 提供(登录 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
Run Code Online (Sandbox Code Playgroud)

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

结论

Andy 的、Xhienne 的和我的原始答案,相当于通过 SSH 运行命令,将

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


xhi*_*nne 6

[更新]

这个有趣的案例值得一个更好的答案(我从这个关于 superuser 的答案中借用了)。

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

问题在于远程外壳。如果是 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'
Run Code Online (Sandbox Code Playgroud)

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

ssh -t user@server '/bin/bash --noprofile --norc'
Run Code Online (Sandbox Code Playgroud)

运行另一个shell:

ssh -t user@server /bin/sh
Run Code Online (Sandbox Code Playgroud)

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

下载-编辑-上传你错了.bashrc

$ scp user@server:~/.bashrc /tmp/bashrc
$ vi /tmp/bashrc
$ scp /tmp/bashrc user@server:~/.bashrc
Run Code Online (Sandbox Code Playgroud)


And*_*ton 6

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

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

$ ssh -t user@host "/bin/bash --noprofile --norc"
bash-5.0$
Run Code Online (Sandbox Code Playgroud)

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