.bashrc
我在通过 SSH 远程登录服务器时试验了我的文件。我无意中留下了一个exit
错误,导致所有后续登录都立即断开连接。我实际上被锁定了。我能够在具有 root 权限的人的干预下恢复访问权限,但如果没有其他人的帮助,这是否可行?
我尝试运行ssh <server> 'bash --norc --noprofile'
和ssh <server> 'mv .bashrc bashrc-backup'
,甚至尝试用强行覆盖它scp empty-file <server>:.bashrc
。但是,所有这些选项似乎都依赖于.bashrc
在运行命令之前先找到损坏的源,因此它们都不起作用。
很可能这种情况是无法避免的。但这是设计使然吗?为什么会如此容易地将自己锁定在系统之外,例如只需运行ssh <server> 'echo exit > .bashrc'
?有没有什么方法可以减轻这种错误?
答案1
正如在另一个答案中讨论的那样,当 SSH 客户端连接到 OpenSSH 服务器时,OpenSSH 服务器通常会使用用户的登录 shell 代表客户端启动 shell 会话:
- 如果客户端请求交互式会话,服务器将启动用户的登录 shell。
- 如果客户端请求运行某个命令,服务器将使用用户的登录 shell 将该命令作为 shell 命令来运行。
scp
、、rsync
和等使用 ssh 进行传输的实用程序git
将请求在远程系统上运行命令,因此它们属于#2。
如果远程用户的 shell 启动文件中存在导致 shell 退出的因素,那么您将无法进入。
然而,SFTP 是一个特殊情况。OpenSSH 服务器可能配置为支持 SFTP,无需启动外部命令。如果如果是这样,那么您将能够使用 sftp 连接到服务器并删除、重命名或更改.bashrc
导致问题的文件。
这取决于服务器如何配置以支持 sftp。它可以通过启动外部程序(名为sftp-server
)。在这种情况下,您会遇到与使用类似程序相同的问题scp
。或者,服务器可以通过称为“内部-sftp”,这不需要调用 shell。它只取决于特定 SSH 服务器的配置方式。
答案2
发生这种情况的原因是sshd
,服务器端组件使用您的 shell 调用进程。如果它生成一个交互式 shell,它会将其生成为登录 shell;否则,它会使用参数-c
生成一个非交互式 shell 来运行您指定的命令。
您指定的所有操作(指定的命令和scp
)都是非交互式操作,因此通常 bash 不会加载.bashrc
,但 bash 在调用时具有特殊大小写,sshd
因此无论如何它都会调用它。如果您使用的是 zsh,那么.zshenv
(为所有 shell 调用)将被加载,但.zshrc
(仅适用于交互式 shell)不会加载,除非您专门加载 shell 会话。
在这种情况下,如果您使用的是 bash,那么您就没那么幸运了。没有办法在不使用 shell 的情况下在服务器端调用 SSH 命令;即使对于 scp 和 sftp 也是如此。大多数情况下,您希望使用 shell,因为它可以PATH
为各种程序设置内容,并且允许编写大量复杂命令的脚本,因此 OpenSSH 始终使用它。
这也有一些安全方面的好处:如果您尝试登录一个系统帐户,该帐户以某种方式具有有效密码但 shell 为/usr/sbin/nologin
或/bin/false
,那么您将无法执行任何操作,这可能是系统管理员想要的。
有办法缓解这种情况。许多人保留一个 Git 存储库来存放他们的点文件,并在一个系统上开发它们,然后将它们部署到其他系统。例如,我总是在笔记本电脑上进行点文件开发。如果你每次打开新的终端窗口时它都会立即退出,那么你大概会更早注意到这个问题,并且你可能有 root 权限来自己修复它。
如果您需要测试可能会将您锁定的配置,例如 shell 配置或sudoers
更改,您可以保持一个 shell(分别是普通或 root)打开,然后进行一些测试,这样如果您破坏了某些东西,您仍然可以撤消它。