为什么我的 SSH 会话中可以正常工作,但在 Capistrano 中却不行?

这可能是最复杂的支持问题之一,唯一真正的答案是 **取决于**。

实际上,这是一个关于 Capistrano 使用哪种类型的 shell 的问题,它是一个关于 loginnon-logininteractivenon-interactive 的可能性矩阵。

默认情况下,Capistrano 始终分配一个 non-loginnon-interactive shell。

Shell 模式

Unix shell 可以以三种模式之一启动:未命名的 *基本* 模式(几乎不会发生)、login shell 或 interactive shell。

根据 shell 启动的模式(以及您使用的 shell),这将影响加载哪些启动(更常见的是 *点* 文件)文件(如果有)。这里 是加载内容的矩阵。

Capistrano 的 pty 选项怎么样?

这个选项一直被误导性地使用,如果您要求 SSH 提供一个 pty,您实际上是在告诉 SSH *“我将把此会话连接到用户终端”*,因此接收端程序期望能够提示输入并提供彩色输出等。简而言之,它们认为它们正在与您进行交互式会话,因为通过分配一个 pty,Bash 已在 non-logininteractive 模式下启动。

阅读更多相关内容

Capistrano 的工作方式与 SSH 会话有何不同

默认情况下,Capistrano 倾向于启动一个 *非登录、非交互式 shell*,以尝试隔离环境并确保一切按预期工作,无论服务器端可能发生任何更改。

相反,当您使用终端登录到机器,进入常规 Bash 会话时,Bash 的 --login 选项被隐式授予,为您提供一个 login shell,并且由于您在终端中,ssh 会要求 ssh 服务器提供一个 pty,以便您可以启动一个交互式会话。因此,您将获得一个 interactive login shell,这与我们对 Capistrano 的需求完全相反!

如何检查?

我实际上不得不查找这个问题,大多数情况下都是常识,但 stackoverflow 来救援,让我们弄清楚!

首先,我们将尝试一个 *真正的* SSH 会话,通过我们的终端登录,看看会发生什么

me@localhost $ ssh me@remote
me@remote $ [[ $- == *i* ]] && echo 'Interactive' || echo 'Not interactive'
Interactive
me@remote $ shopt -q login_shell && echo 'Login shell' || echo 'Not login shell'
Login shell

将此与我们在不先登录的情况下将要运行的命令传递给 SSH 命令行时发生的情况进行对比……

me@localhost $ ssh me@remote "[[ $- == *i* ]] && echo 'Interactive' || echo 'Not interactive'"
Interactive
me@localhost $ ssh me@remote "shopt -q login_shell && echo 'Login shell' || echo 'Not login shell'"
Not login shell

在这里我们可以看到,当我们只运行一个命令时,Bash 仍然以 **交互式** 模式启动,这是因为我们正在使用的终端是交互式的,SSH 继承了这一点并将它传递给远程服务器。

当我们用 Capistrano 尝试相同的事情时,我们将看到另一组结果;我们可以有一个非常简单的 Capfile,我们甚至不需要加载默认的配方来测试这一点

# Capistrano 3
task :query_interactive do
  on 'me@remote' do
    info capture("[[ $- == *i* ]] && echo 'Interactive' || echo 'Not interactive'")
  end
end
task :query_login do
  on 'me@remote' do
    info capture("shopt -q login_shell && echo 'Login shell' || echo 'Not login shell'")
  end
end

给我们以下内容

me@localhost $ cap query_login
INFO Not login shell
me@localhost $ cap query_interactive
INFO Not interactive

哪些 shell 启动文件被加载?

用这张图解释最好,是的,它很复杂

Bash Startup Files

来源:http://www.solipsys.co.uk/new/BashInitialisationFiles.html

Fork me on GitHub