39

我编写了一个简单的自动化过程,需要通过 SSH 将一些文件从 linux 服务器复制到 windows。这可以使用腻子来完成。

SSH 作为协议的一部分,会验证主机的身份,如果不知道是否正确,会提示您接受主机的身份。当我使用 putty 手动连接 linux 服务器时,它不会提示任何信息来接受主机的身份。但是一旦我把这个自动化过程作为计划工作放到 Hudson 中。确切的信息是:

服务器的主机密钥未缓存在注册表中。您无法保证服务器就是您认为的计算机。服务器的 rsa2 密钥指纹为:ssh-rsa 1024 cc:78:13:a3:68:a6:59:7e:b8:23:2d:13:3e:66:9b:b9 如果信任此主机,请输入“ y" 将密钥添加到 PuTTY 的缓存中并继续连接。如果您只想进行一次连接,而不将密钥添加到缓存中,请输入“n”。如果您不信任此主机,请按 Return 放弃连接。将密钥存储在缓存中?(y/n) 已放弃连接。

通常你会在这里点击“Y”,假设主机密钥是正确的,以便在将来的连接中存储它。此存储进入 HKEY_CURRENT_USER\Software\SimonTatham\Putty\SshHostKeys 下的注册表

但不幸的是,在 Hudson 中运行的自动化进程无法通过点击“Y”将主机密钥存储在 putty 缓存中进行交互。而且我无法通过简单地在 dos 命令下运行自动化过程来重现该问题。

有谁知道如何解决这个问题?

4

10 回答 10

41
echo y | pscp -i /path/to/key/file user@remote:/tmp/file  .
echo y | plink -i /path/to/key/file scripts.sh

它将第一次将主机密钥指纹存储到以下位置,下次将忽略“y”

HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\SshHostKeys
于 2012-11-29T01:54:06.260 回答
21

对于内部服务器,盲目的echo y | ...把戏可能就足够了(而且超级简单)。

但是,对于通过 Internet 访问的外部服务器,接受一次服务器主机密钥比每次都盲目接受要安全得多。


创建可以在客户端计算机上运行的 .reg 文件。

  • 从任何机器交互式连接plink ...
  • 验证并接受主机密钥
  • 打开regedit
  • 导航HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\SshHostKeys
  • 右键单击条目(将具有类似的名称rsa2@<port>:<address>
  • 导出到 .reg 文件

在客户端机器上缓存主机密钥

  • 在将连接到该服务器的任何客户端计算机上运行 .reg 文件
  • 确保使用将运行的用户帐户登录plink(即如果它是服务帐户)
于 2013-12-11T16:03:30.110 回答
16

使用使用本地系统帐户的批处理调度程序时,我也遇到了这个问题。使用此帐户,您无法登录以接受主机密钥或手动设置HKEY_CURRENT_USER值。我发现创建以下密钥:

HKEY_USERS\.DEFAULT\Software\SimonTatham\PuTTY\SshHostkeys

并在此处添加主机字符串值适用于本地系统帐户。

于 2014-07-22T15:32:10.570 回答
14

自 2014 年 9 月 9 日起使用相应版本的 plink(使用 plink 0.66 测试),您可以使用 -hostkey 选项,如此处所述:

http://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/accept-host-keys.html

使用原始问题中的密钥:

plink -hostkey cc:78:13:a3:68:a6:59:7e:b8:23:2d:13:3e:66:9b:b9 user@remote 

我在脚本中成功使用了“-hostkey”来解决初始主机密钥提示问题。

“-hostkey”也被记录为与 pscp(版本 0.66)一起使用。

请注意,如果您更改主机或 sshd 服务器重新计算密钥,则必须更改主机密钥。

于 2015-12-02T18:38:02.563 回答
5
echo y | plink -ssh <username@remotemachine> -pw <password> exit
plink -ssh <username@remotemachine> -pw <password> [yourcommand]

说明:使用 echo 管道,用户输入 'y' 到选定的命令,然后退出。然后,下一条语句将再次调用 plink 可执行文件来运行您的命令。

于 2013-08-29T13:20:46.833 回答
4

我在使用Bazaar时遇到了这个问题,并手动将我的 ssh 客户端设置为 putty 而不是内置的 paramiko,我遇到了完全相同的问题,它试图说密钥不在“已知主机”中并询问我是否应该验证它,但由于它是由不同的程序而不是在普通终端中运行的,所以它立即退出了。

如果可以,只需运行 putty 并手动连接到服务器以使其将 ssh 公钥保存在注册表中,这样当自动化程序尝试连接时,它就不会显示 y/n 选项。

或者您可以使用我编写的一个小型 python3 脚本在 putty 和 openssh 使用的两种“已知主机”格式之间进行转换:https ://github.com/mbrandi/openssh-putty-knownhost-converter

`

于 2014-04-01T23:32:53.570 回答
1

正如评论中所说,我的答案与@Clay的第一个答案非常相似,因为它指的是特定案例(GIT)并且它更短一些,所以我会放手。

GIT_SSH="path_to_plink.exe"使用 Putty 作为 SSH 客户端时,验证服务器一次的步骤是强制性的,否则当 Putty 要求交互式 'y' 输入时你会卡住:

  1. 从命令行运行 plink:plink <serverName>

  2. 验证将密钥存储在缓存中的第一个提示

  3. 退出命令Ctrl+c

现在,您运行命令的客户端将不再提示进行指纹验证。

Putty 使用注册表而不是文件<...>\.ssh\known_hosts,因此您可以通过导出/导入注册表项来配置另一个主机Computer\HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\SshHostKeys。由于此键引用当前用户,因此您需要在以运行 GIT 命令的用户身份登录时导入。

于 2021-06-10T09:18:42.193 回答
0

从 Windows PowerShell 以管理员模式运行

pscp -i /path/to/private_key source_file user@ip:/home/location
于 2018-06-16T07:41:39.950 回答
-1

它一直工作得很好

pscp file user@dest: 

但后来我得到了同样的错误。所以我做了:

pscp -l USERNAME -pw PASSWORD FILE 10.1.1.1:

这对我有用。

于 2018-07-02T16:42:37.890 回答
-2

通过代码解决方案:编译 putty/plink 以自动接受和存储 ssh 密钥

系统会提示您将 SSH 主机密钥存储在缓存中,由于执行 plink 的用户帐户在注册表中没有主机,因此它挂起,因为它等待回复(是/否..)。
如果您想通过代码解决此问题,请获取 putty 源代码,进行一些更改,编译并使用新的 plink 二进制文件 - 一个在没有提示的情况下存储 ssh 主机密钥的二进制文件。
怎么做 ?对于 Windows,我执行以下操作:

  • 下载最新的 putty 源代码: https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html
    (寻找“Source code”部分并下载“Windows Source archive”)
    注意:打开putty使用 Visual Studio 的源代码,您必须下载发布版本,如果您签出到特定的提交(或头),则 Visual Studio 解决方案文件将不存在,因为它们是在构建期间创建的。
    取自:由于缺少 Windows/MSVC 子目录,无法在 Windows 上编译 PuTTY、Plink 或 Pscp

  • 源码需要更新,我们要修改的是wincons.c中的verify_ssh_host_key(..)函数,我们要注释掉提示yes/no的代码部分,只存储key,开始注释掉提示代码:

    /*hin = GetStdHandle(STD_INPUT_HANDLE);
    GetConsoleMode(hin, &savemode);
    SetConsoleMode(hin, (savemode | ENABLE_ECHO_INPUT |
             ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT));
    ReadFile(hin, line, sizeof(line) - 1, &i, NULL);
    SetConsoleMode(hin, savemode);
    
    if (line[0] != '\0' && line[0] != '\r' && line[0] != '\n') {
    if (line[0] == 'y' || line[0] == 'Y')
    store_host_key(host, port, keytype, keystr);
    return 1;
    } else {
      fprintf(stderr, abandoned);
      return 0;
    }*/  
    

继续添加以下行(负责存储主机密钥的代码):

store_host_key(host, port, keytype, keystr);
return 1;

编译解决方案并采用 plink/pscp .. 无需提示即可,它接受 ssh 主机密钥并将其存储在注册表中。

于 2017-08-16T09:46:49.817 回答