概述
我正在脚本在Windows 7框中的SFTP文件传输。 当我传输大于兆字节左右的zip文件时,传输(和SSH)在大约700KB之后意外停止。 SSH进程似乎挂起,但它不开始疯狂消耗CPU或内存,Windows不会说它停止响应。 服务器最终放弃和超时,但客户端永远不会返回(尽pipe设置ServerAliveCountMax和ServerAliveInterval)。 服务器日志显示传输开始,然后是超时,并在很长一段时间后断开连接。
细节
重新将脚本重新运行回来,在每次挂起之前都会传输相同数量的字节。 走开并回来,然后再次运行脚本,字节数将变化几十千字节。
命令行sftp.exe客户端使用默认选项正常工作; 那些较大的zip文件传输成功。 我无法testingscp.exe,因为SSH用户帐户没有shell访问权限。 我相信这个问题持续在操作系统擦拭和重新映像从XP到7,所以我怀疑networking问题,但我不明白什么样的问题会导致这种行为。
我正在用Perl和Net :: SFTP :: Foreign模块编写脚本。 以下是从我的testing用例脚本(下面附加的SSH输出日志)中提取的代码的相关位:
my %connectOpts = ( user => $username ,timeout => $timeout ,warn => sub {} ,more => [ "-o PreferredAuthentications=publickey", "-o ServerAliveCountMax=6", "-o ServerAliveInterval=" . int($timeout/6), "-vvvv" ] ); my $sftp = Net::SFTP::Foreign::Compat->new( $host, %connectOpts ); foreach my $local_file ( @local_files ) { $sftp->do_stat( 'upload.tmp' ) && print( "Overwriting upload.tmp\n" ); $sftp->put( $local_file, 'upload.tmp' ); $sftp->do_rename( 'upload.tmp', basename( $local_file )); }
为了同样的目的,我在其他几十台现场PC上使用这些代码和非常相似的configuration。 这是我见过的第一个这个问题。 我正在寻找根本原因或诊断build议,而不是此生态系统之外的解决方法。 有无数的方法来编写脚本,但是我需要Net :: SFTP :: Foreign模块的粒度,反馈和模块化来logging和报告错误。 Perl是唯一可用的脚本语言。
谢谢。 这令人难以置信的令人沮丧。
组态:
客户端输出(-vvvv),直到我手动终止后ssh.exe横盘:
OpenSSH_5.3p1, OpenSSL 0.9.8k 25 Mar 2009 debug1: Reading configuration data /etc/ssh_config debug2: ssh_connect: needpriv 0 debug1: Connecting to sftp.server.com [xx.xx.xx.xx] port 22. debug1: Connection established. debug1: identity file /cygdrive/c/program files/copssh/.ssh/identity type -1 debug3: Not a RSA1 key file /cygdrive/c/program files/copssh/.ssh/id_rsa. debug2: key_type_from_name: unknown key type '-----BEGIN' debug3: key_read: missing keytype debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug2: key_type_from_name: unknown key type '-----END' debug3: key_read: missing keytype debug1: identity file /cygdrive/c/program files/copssh/.ssh/id_rsa type 1 debug1: identity file /cygdrive/c/program files/copssh/.ssh/id_dsa type -1 debug1: Remote protocol version 2.0, remote software version 6.2.1.168 SSH Tectia Server debug1: no match: 6.2.1.168 SSH Tectia Server debug1: Enabling compatibility mode for protocol 2.0 debug1: Local version string SSH-2.0-OpenSSH_5.3 debug2: fd 3 setting O_NONBLOCK debug1: SSH2_MSG_KEXINIT sent debug3: Wrote 792 bytes for a total of 813 debug1: SSH2_MSG_KEXINIT received debug2: kex_parse_kexinit: diffie-hellman-group-exchange-sha256,diffie-hellman-g roup-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1 debug2: kex_parse_kexinit: ssh-rsa,ssh-dss debug2: kex_parse_kexinit: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour12 8,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rij [email protected] debug2: kex_parse_kexinit: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour12 8,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rij [email protected] debug2: kex_parse_kexinit: hmac-md5,hmac-sha1,[email protected],hmac-ripemd160 ,[email protected],hmac-sha1-96,hmac-md5-96 debug2: kex_parse_kexinit: hmac-md5,hmac-sha1,[email protected],hmac-ripemd160 ,[email protected],hmac-sha1-96,hmac-md5-96 debug2: kex_parse_kexinit: none,[email protected],zlib debug2: kex_parse_kexinit: none,[email protected],zlib debug2: kex_parse_kexinit: debug2: kex_parse_kexinit: debug2: kex_parse_kexinit: first_kex_follows 0 debug2: kex_parse_kexinit: reserved 0 debug2: kex_parse_kexinit: diffie-hellman-group1-sha1,diffie-hellman-group14-sha 1,[email protected],diffie-hellman-group-exchange-sha1,diffi e-hellman-group-exchange-sha256 debug2: kex_parse_kexinit: ssh-rsa,[email protected] debug2: kex_parse_kexinit: aes256-cbc,aes192-cbc,aes128-cbc,3des-cbc debug2: kex_parse_kexinit: aes256-cbc,aes192-cbc,aes128-cbc,3des-cbc debug2: kex_parse_kexinit: hmac-sha1 debug2: kex_parse_kexinit: hmac-sha1 debug2: kex_parse_kexinit: none,zlib debug2: kex_parse_kexinit: none,zlib debug2: kex_parse_kexinit: debug2: kex_parse_kexinit: debug2: kex_parse_kexinit: first_kex_follows 0 debug2: kex_parse_kexinit: reserved 0 debug2: mac_setup: found hmac-sha1 debug1: kex: server->client aes128-cbc hmac-sha1 none debug2: mac_setup: found hmac-sha1 debug1: kex: client->server aes128-cbc hmac-sha1 none debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<2048<8192) sent debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP debug3: Wrote 24 bytes for a total of 837 debug2: dh_gen_key: priv key bits set: 160/320 debug2: bits set: 1016/2048 debug1: SSH2_MSG_KEX_DH_GEX_INIT sent debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY debug3: Wrote 272 bytes for a total of 1109 debug3: check_host_in_hostfile: filename /cygdrive/c/program files/copssh/.ssh/known_hosts debug3: check_host_in_hostfile: match line 2 debug3: check_host_in_hostfile: filename /cygdrive/c/program files/copssh/.ssh/known_hosts debug3: check_host_in_hostfile: match line 1 debug1: Host 'sftp.server.com' is known and matches the RSA host key. debug1: Found key in /cygdrive/c/program files/copssh/.ssh/known_hosts:2 debug2: bits set: 995/2048 debug1: ssh_rsa_verify: signature correct debug2: kex_derive_keys debug2: set_newkeys: mode 1 debug1: SSH2_MSG_NEWKEYS sent debug1: expecting SSH2_MSG_NEWKEYS debug3: Wrote 16 bytes for a total of 1125 debug2: set_newkeys: mode 0 debug1: SSH2_MSG_NEWKEYS received debug1: SSH2_MSG_SERVICE_REQUEST sent debug3: Wrote 52 bytes for a total of 1177 debug3: Received SSH2_MSG_IGNORE debug3: Received SSH2_MSG_IGNORE debug2: service_accept: ssh-userauth debug1: SSH2_MSG_SERVICE_ACCEPT received debug2: key: /cygdrive/c/program files/copssh/.ssh/identity (0x0) debug2: key: /cygdrive/c/program files/copssh/.ssh/id_rsa (0xd4b720) debug2: key: /cygdrive/c/program files/copssh/.ssh/id_dsa (0x0) debug3: Wrote 84 bytes for a total of 1261 debug3: Received SSH2_MSG_IGNORE debug1: Authentications that can continue: publickey,keyboard-interactive debug3: start over, passed a different list publickey,keyboard-interactive debug3: preferred publickey debug3: authmethod_lookup publickey debug3: remaining preferred: debug3: authmethod_is_enabled publickey debug1: Next authentication method: publickey debug1: Trying private key: /cygdrive/c/program files/copssh/.ssh/identity debug3: no such identity: /cygdrive/c/program files/copssh/.ssh/identity debug1: Offering public key: /cygdrive/c/program files/copssh/.ssh/id_rsa debug3: send_pubkey_test debug2: we sent a publickey packet, wait for reply debug3: Wrote 372 bytes for a total of 1633 debug3: Received SSH2_MSG_IGNORE debug1: Server accepts key: pkalg ssh-rsa blen 277 debug2: input_userauth_pk_ok: fp (...) debug3: sign_and_send_pubkey debug1: read PEM private key done: type RSA debug3: Wrote 644 bytes for a total of 2277 debug3: Received SSH2_MSG_IGNORE debug1: Authentication succeeded (publickey). debug2: fd 4 setting O_NONBLOCK debug2: fd 5 setting O_NONBLOCK debug1: channel 0: new [client-session] debug3: ssh_session2_open: channel_new: 0 debug2: channel 0: send open debug1: Entering interactive session. debug3: Wrote 68 bytes for a total of 2345 debug3: Received SSH2_MSG_IGNORE debug2: callback start debug2: client_session2_setup: id 0 debug1: Sending subsystem: sftp debug2: channel 0: request subsystem confirm 1 debug2: fd 3 setting TCP_NODELAY debug2: callback done debug2: channel 0: open confirm rwindow 65536 rmax 32768 debug3: Wrote 68 bytes for a total of 2413 debug3: Wrote 52 bytes for a total of 2465 debug3: Received SSH2_MSG_IGNORE debug2: channel_input_status_confirm: type 99 id 0 debug2: subsystem request accepted on channel 0 debug3: Received SSH2_MSG_IGNORE debug3: Wrote 68 bytes for a total of 2533 debug3: Received SSH2_MSG_IGNORE debug3: Wrote 84 bytes for a total of 2617 debug3: Received SSH2_MSG_IGNORE debug3: Wrote 68 bytes for a total of 2685 debug3: Received SSH2_MSG_IGNORE debug3: Wrote 16436 bytes for a total of 19121 debug3: Wrote 4148 bytes for a total of 23269 debug3: Wrote 12372 bytes for a total of 35641 debug3: Wrote 16436 bytes for a total of 52077 debug3: Wrote 4148 bytes for a total of 56225 debug3: Wrote 12196 bytes for a total of 68421 debug3: Received SSH2_MSG_IGNORE debug2: channel 0: rcvd adjust 32899 debug3: Wrote 212 bytes for a total of 68633 debug3: Received SSH2_MSG_IGNORE debug3: Wrote 16436 bytes for a total of 85069 debug3: Wrote 4148 bytes for a total of 89217 debug3: Received SSH2_MSG_IGNORE debug2: channel 0: rcvd adjust 98337 debug3: Received SSH2_MSG_IGNORE debug3: Wrote 12372 bytes for a total of 101589 debug3: Wrote 16436 bytes for a total of 118025 debug3: Wrote 4148 bytes for a total of 122173 debug3: Wrote 12372 bytes for a total of 134545 debug3: Wrote 16436 bytes for a total of 150981 debug3: Received SSH2_MSG_IGNORE debug3: Wrote 4148 bytes for a total of 155129 debug3: Wrote 12372 bytes for a total of 167501 debug3: Received SSH2_MSG_IGNORE debug2: channel 0: rcvd adjust 196674 debug3: Received SSH2_MSG_IGNORE debug3: Wrote 16436 bytes for a total of 183937 debug3: Received SSH2_MSG_IGNORE debug3: Wrote 4148 bytes for a total of 188085 debug3: Wrote 12372 bytes for a total of 200457 debug3: Wrote 16436 bytes for a total of 216893 debug3: Wrote 4148 bytes for a total of 221041 debug3: Wrote 12372 bytes for a total of 233413 debug3: Wrote 16436 bytes for a total of 249849 debug3: Received SSH2_MSG_IGNORE debug3: Wrote 4148 bytes for a total of 253997 debug3: Wrote 12372 bytes for a total of 266369 debug3: Received SSH2_MSG_IGNORE debug3: Wrote 16436 bytes for a total of 282805 debug3: Wrote 4148 bytes for a total of 286953 debug3: Wrote 12372 bytes for a total of 299325 debug3: Received SSH2_MSG_IGNORE debug2: channel 0: rcvd adjust 131204 debug3: Wrote 16436 bytes for a total of 315761 debug3: Received SSH2_MSG_IGNORE debug3: Wrote 4148 bytes for a total of 319909 debug3: Received SSH2_MSG_IGNORE debug3: Wrote 12372 bytes for a total of 332281 debug3: Wrote 16436 bytes for a total of 348717 debug3: Wrote 4148 bytes for a total of 352865 debug3: Wrote 12372 bytes for a total of 365237 debug3: Wrote 16436 bytes for a total of 381673 debug3: Wrote 4148 bytes for a total of 385821 debug3: Received SSH2_MSG_IGNORE debug3: Wrote 12372 bytes for a total of 398193 debug3: Wrote 16436 bytes for a total of 414629 debug3: Received SSH2_MSG_IGNORE debug3: Wrote 4148 bytes for a total of 418777 debug3: Wrote 12372 bytes for a total of 431149 debug3: Wrote 16436 bytes for a total of 447585 debug3: Received SSH2_MSG_IGNORE debug2: channel 0: rcvd adjust 393348 debug3: Received SSH2_MSG_IGNORE debug3: Wrote 4148 bytes for a total of 451733 debug3: Received SSH2_MSG_IGNORE debug3: Wrote 12372 bytes for a total of 464105 debug3: Wrote 16436 bytes for a total of 480541 debug3: Wrote 4148 bytes for a total of 484689 debug3: Wrote 12372 bytes for a total of 497061 debug3: Wrote 16436 bytes for a total of 513497 debug3: Wrote 4148 bytes for a total of 517645 debug3: Received SSH2_MSG_IGNORE debug3: Wrote 12372 bytes for a total of 530017 debug3: Wrote 16436 bytes for a total of 546453 debug3: Received SSH2_MSG_IGNORE debug3: Wrote 4148 bytes for a total of 550601 debug3: Wrote 12372 bytes for a total of 562973 debug3: Wrote 16436 bytes for a total of 579409 debug3: Received SSH2_MSG_IGNORE debug3: Wrote 4148 bytes for a total of 583557 debug3: Wrote 12372 bytes for a total of 595929 debug3: Wrote 16436 bytes for a total of 612365 debug3: Received SSH2_MSG_IGNORE debug3: Wrote 4148 bytes for a total of 616513 debug3: Wrote 12372 bytes for a total of 628885 debug3: Wrote 16436 bytes for a total of 645321 debug3: Received SSH2_MSG_IGNORE debug3: Wrote 4148 bytes for a total of 649469 debug3: Wrote 12372 bytes for a total of 661841 debug3: Wrote 16436 bytes for a total of 678277 debug3: Wrote 4148 bytes for a total of 682425 debug3: Received SSH2_MSG_IGNORE debug3: Wrote 12372 bytes for a total of 694797 debug3: Wrote 16436 bytes for a total of 711233 debug3: Received SSH2_MSG_IGNORE debug2: channel 0: rcvd adjust 738120 debug3: Received SSH2_MSG_IGNORE debug3: Wrote 4148 bytes for a total of 715381 debug3: Received SSH2_MSG_IGNORE
更新1
根据@Daniel Lawson的build议,我尝试使用netsh将VPN接口的MTU限制到1280,以避免在沿服务器path的MTU不匹配的情况下填充客户端的TCP缓冲区。 转移仍然停滞在大致相同的点。 我也尝试断开VPN,并将物理接口的MTU夹紧到1280,结果相同。
这对我来说就像是一个MTU问题。 当遇到pathMTU不匹配时,我看到了与scping文件类似的问题。 主机上的TCP缓冲区可能会被填满,这就是为什么你发送多个数据包的原因,但是一旦它们填满了你的客户端,就会停顿 – 在MTU问题本身实际产生影响之后很久。
为了validation这一点,你可以看看一个工具,如scamper 。 或者你可以尝试手动将你的MTU固定在一个较低的点(比如说1280字节),然后看看是否能解决这个问题。 只有轻微的不匹配的机会是好的,例如,由于path中的PPPoE链路将MTU降低到1492。
也许你可以玩block_size参数? 我经历了一些与通过SSH / SSLfile upload有关的奇怪,并以某种方式调整块/块大小帮助。 我相信默认是32 * 1024 ,所以也许降低到16,8,4,尝试可能会有所作为。 可能值得一试。
Windows上的默认队列大小被设置为4,但是由于模块上的错误,这个默认值没有被拾取。
它已被更正(和BTW,Windows默认队列大小更改为16)。 您现在可以下载Net :: SFTP :: Foreign 1.70_08 。
下一次你发现这样的问题,请报告!
注意(TLDR):正如salva所说,快速修复是更新到Net :: SFTP :: Foreign 1.70_08或更新版本。 有一个错误,防止库在Windows中使用正确的默认queue_size 。 阅读我的原始解决scheme。
我能够通过将Perl Net :: SFTP :: Foreign模块的queue_size参数从默认的32位降低到23来消除停滞的传输。这是一个与networking性能相关的variables,当它减less时我不会感觉到速度差异。 为了生产,我将把它拨回到16安全。
queue_size => $ size
读写请求是stream水线的,以最大限度地提高传输吞吐量。 此选项允许设置可以同时等待服务器响应的最大请求数。
(来自Net :: SFTP :: CPAN的外国文档 )
queue_size选项适用于Net :: SFTP :: Foreign的new get , put , rput和rput方法。
如果你使用的是Net :: SFTP :: Foreign,你可以在你的构造函数的结尾或者单独的方法调用中joinqueue_size参数。
my $sftp = Net::SFTP::Foreign->new( $host, queue_size => 16 ); # -- OR -- $sftp->put( $local_file, $remote_file, queue_size => 16 );
我使用Net :: SFTP :: Foreign :: Compat包装类似于Net :: SFTP的API。 包装允许您设置默认参数与底层Net :: SFTP :: Foreign方法调用一起使用。
use Net::SFTP::Foreign::Compat; # Note that the Compat CPAN documentation is INCORRECT # The DEFAULTS hash is under Compat, not Foreign $Net::SFTP::Foreign::Compat::DEFAULTS{ new } = [ queue_size => 16 ]; # -- OR -- $Net::SFTP::Foreign::Compat::DEFAULTS{ put } = [ queue_size => 16 ]; my $sftp = Net::SFTP::Foreign::Compat->new( $host, %options );
相关思想:最大工作queue_size为23,与传输前发送的字节数相关的32KB的默认block_size与停滞。 23 * 32KB有点超过700KB。 我无法解释为什么我需要限制这个部署queue_size ,但它解决了我的问题。