scp \ 033H消息

有一个奇怪的scp问题:

$ scp user@server.org:~/test.txt ./ Password: \033H \033H \033H \033H \033H \033H \033H \033H \033H \033H \033H \033H \033H \033H \033H \033H \033H \033H \033H \033H 

密码很好,但得到那个奇怪的\ 033H的东西。 并且文件不会传输。 有人有主意吗?

对此的修复通常很简单。 通常你可以检查.bashrc ,找到导致问题的顶部附近的一行或几行,然后移动或删除它们。 困难的部分是让人们相信这个问题实际上是真的。 详细信息如下,但如果您只是想解决此问题,那么您只需要使用这个较短的第一部分。

问题,以及如何解决它

当远程计算机上用户主目录中的.bashrc包含生成输出的命令并且即使在非交互式shell中运行时,也会发生这种情况。 不太常见的是,如果系统范围的/etc/bash.bashrc包含此类命令,也会发生这种情况。 具体的输出取决于产生它的原因。 但是接收意外输出和没有任何传输的组合成功甚至开始非常强烈地指向该原因(特别是当服务器是Debian或Ubuntu系统时)。 scp使用标准输入和输出来发送和接收数据,如果通过它们传输不相关的数据,则它不能传输文件。

如果你在想, “那是不可能的, .bashrc只适用于交互式shell!” 或者对如何发生这种情况的详细解释感兴趣,请参阅下面的第二部分。

此问题不会破坏正常的SSHing。 因此,假设系统配置为允许您成功ssh成为交互式登录shell,您可以这样做,在远程用户的主目录中打开.bashrc ,并删除或注释掉(使用# )有问题的命令或命令,如果你不需要它们。 或者如果你确实需要它们,那么将它们移到另一个命令下面,当shell是非交互式的时候中止。 这样的命令可能已经存在。 在Ubuntu中,用户的.bashrc文件和系统范围的/etc/bash.bashrc通常以它们开头。

Ubuntu中的默认.bashrc文件,在创建用户帐户时从/etc/skel复制,包含此代码以检查正在运行的shell是否是交互式的,并且如果不是,则阻止文件中的任何其他命令运行:

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

另一种常见的方法是,有些人在他们的.bashrc文件中使用,目前在系统范围的/etc/bash.bashrc文件中为所有用户使用,方法是:

 # If not running interactively, don't do anything [ -z "$PS1" ] && return 

如果文件已从默认值中替换或修改,则您可能会在任一文件中看到任一技术。 还有其他可能的方法来检查交互操作,但它们并不常见。 如果用户从头开始编写自己的.bashrc文件,或者从另一个不是Debian,Ubuntu或其他Debian派生的操作系统中删除它,那么很可能他们根本就没有这样的代码。 但是如果你需要它,你仍然可以添加它。

产生输出并显示在.bashrc/etc/bash.bashrc任何命令,除非它出现上面显示的代码之后 ,将导致在scp会话开始时发送意外数据,并将阻止scp能够传输文件。

如果您最近通过向顶部添加命令自己编辑了其中一个文件,那么您应该很容易找出导致问题的特定更改。 即使没有,上面的描述可能会给你足够的信息。

但是,我建议您使用完整的详细信息编辑您的问题,包括这些文件的内容,无论您是否能够根据上述说明解决问题。 请记住, 这些是远程服务器上的文件,而不是客户端计算机上的文件 这应该有助于找到问题的其他人了解问题,并且如果需要,可以提供更具体的建议。

我相信你的问题可能由完全不同的东西造成的非常低,但不管怎样,增加的信息应该可以确定。 除了这个问题的作者,有类似问题并需要帮助解决这些问题的其他人当然应该编辑这个问题,但应该发表自己的问题。


为什么会出现问题

人们经常说.bashrc仅用于交互式shell,但这是一种误解,或者至多是一种严重的过度简化。 bash运行来自~/.bashrc/etc/bash.basrhc命令:

  1. shell是交互式的, 或者
  2. 另一个启动脚本,如/etc/profile~/.profile 来源 , 但也
  3. bash既不以交互方式运行也不作为登录shell运行,但确定它可能作为远程连接中的初始shell运行。

什么 bash作为远程shell的充分证据 – 因此实际上,这种效果是否在SSH中发生 – 主要取决于它是如何编译的,这在操作系统中是不同的 ,其次是在版本上bash和正在使用的sshd版本 。

在当前的Debian和Ubuntu系统上,当bash作为非交互式非登录shell运行时,它会检查SSH_CLIENT环境变量是否设置SSH_CLIENT空。 (它也会检查其他内容,但对于当前Ubuntu系统上的SSH,它们不会显示任何内容。)如果是这样,并且SHLVL环境变量设置为小于2的值 – 表示它是会话的初始 shell- – bash运行/etc/bash.bashrc~/.bashrc的命令。

为了在不修改配置文件的情况下快速validation,读者可以手动将这些变量传递到bash -c ''的环境中并跟踪它读取的内容 ,或者检查run_startup_files中的run_startup_files函数(从该版本的第1022行开始)。

使用bash运行脚本时,可以获得非交互式非登录bash shell,方法是在设置必要的权限并为其提供适当的hashbang行后执行它,或者通过显式运行bash your-script 。 当你使用-c选项使bash运行单行时,这也是你得到的,例如:

 bash -c 'echo hello world' 

正如您所料,当您通过SSH 登录进行交互式会话时获得的shell是一个交互式登录shell。 这就是你运行这样的命令时得到的结果(假设它成功):

 ssh user@server.org 

但是这里是非直观部分的来源:当您通过SSH 登录进行非交互式会话时获得的shell是非交互式非登录 shell。 这就是通过SSH运行单个命令所得到的:

 ssh user@server.org command args... 

也就是说,通过SSH运行单个命令将bash作为相同类型的shell(非交互式非登录shell)运行,就像使用bash -c在本地(或在已建立的远程会话中)运行单个命令一样bash -c

ssh一样, scp会导致shell作为远程用户在远程计算机上运行。 这仍然是他们配置为shell的任何东西,即/etc/passwd用户条目中列出的shell或getent passedgetent passed输出(当它们登录时也被设置为$SHELL环境变量的值) )。 除非他们通过运行chsh改变它,否则这是默认的用户shell,在Ubuntu中是bash

这就是为什么这样的命令在远程服务器上运行非交互式非登录bash shell的原因:

 scp user@server.org:~/test.txt ./ 

如果shell是非交互式的,那么除非它们被代码保护,否则.bashrc/etc/bash.bashrc中的命令由这样的shell运行。 如果他们有意或无意地产生输出,那么scp将无法复制文件 。