我错误地.bash_profile
在bashrc
文件中包含了源代码,反之亦然。现在,当我尝试 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,例如csh
或fish
)
下载-编辑-上传你有问题.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。