def download():
if os.path.exists( dst_dir_path ) == False:
logger.error( "Cannot access destination folder %s. Please check path and permissions. " % ( dst_dir_path ))
return 1
elif os.path.isdir( dst_dir_path ) == False:
logger.error( "%s is not a folder. Please check path. " % ( dst_dir_path ))
return 1
file_list = None
#transport = paramiko.Transport(( hostname, port))
paramiko.util.log_to_file('paramiko.log')
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
#transport
try:
ssh.connect( hostname, username=username, password=password, timeout=5.0)
#transport.connect(username=username, password=password )
except Exception, err:
logger.error( "Failed to connect to the remote server. Reason: %s" % ( str(err) ) )
return 1
try:
#sftp = paramiko.SFTPClient.from_transport(transport)
sftp = ssh.open_sftp()
except Exception, err:
logger.error( "Failed to start SFTP session from connection to %s. Check that SFTP service is running and available. Reason: %s" % ( hostname, str(err) ))
return 1
try:
sftp.chdir(src_dir_path)
#file_list = sftp.listdir(path="%s" % ( src_dir_path ) )
file_list = sftp.listdir()
except Exception, err:
logger.error( "Failed to list files in folder %s. Please check path and permissions. Reason: %s" % ( src_dir_path, str(err) ))
return 1
match_text = re.compile( file_mask )
download_count = 0
for file in file_list:
# Here is an item name... but is it a file or directory?
#logger.info( "Downloading file %s." % ( file ) )
if not re.match( file_mask, file ):
continue
else:
logger.info( "File \"%s\" name matched file mask \"%s\". matches %s.Processing file..." % ( file, file_mask, (match_text.match( file_mask ) ) ) )
src_file_path = "./%s" % ( file )
dst_file_path = "/".join( [ dst_dir_path, file] )
retry_count = 0
while True:
try:
logger.info( "Downloading file %s to %s." % ( file, dst_file_path ) )
#sftp.get( file, dst_file_path, callback=printTotals ) #sftp.get( remote file, local file )
sftp.get( file, dst_file_path) #sftp.get( remote file, local file )
logger.info( "Successfully downloaded file %s to %s." % ( file, dst_file_path ) )
download_count += 1
break
except Exception, err:
if retry_count == retry_threshold:
logger.error( "Failed to download %s to %s. Reason: %s." % ( file, dst_file_path, str(err) ) )
sftp.close()
#transport.close()
return 1
else:
logger.error( "Failed to download %s to %s. Reason: %s." % ( file, dst_file_path, str(err) ) )
retry_count +=1
sftp.close()
transport.close()
logger.info( "%d files downloaded." % ( download_count ) )
return 0
当我运行下面的函数时,它会下载源文件约3分钟,然后关闭会话,即使下载的1-1.6GB文件只有38-41MB(不同)。
从Paramiko日志文件来看,SSh连接在SFTP会话关闭时保持打开状态:
DEB [20120913-10:05:00.894] thr=1 paramiko.transport: Switch to new keys ... DEB [20120913-10:05:06.953] thr=1 paramiko.transport: Rekeying (hit 401 packets, 1053444 bytes received) DEB [20120913-10:05:07.391] thr=1 paramiko.transport: kex algos:['diffie-hellman-group1-sha1', 'diffie-hellman-group-exchange-sha1'] server key:['ssh-dss'] client encrypt:['aes256-ctr', 'aes192-ctr', 'aes128-ctr', 'aes256-cbc', 'aes192-cbc', 'aes128-cbc', 'twofish-cbc', 'blowfish-cbc', '3des-cbc', 'arcfour'] server encrypt:['aes256-ctr', 'aes192-ctr', 'aes128-ctr', 'aes256-cbc', 'aes192-cbc', 'aes128-cbc', 'twofish-cbc', 'blowfish-cbc', '3des-cbc', 'arcfour'] client mac:['hmac-sha1', 'hmac-sha1-96', 'hmac-md5', 'hmac-md5-96', 'umac-64@openssh.com'] server mac:['hmac-sha1', 'hmac-sha1-96', 'hmac-md5', 'hmac-md5-96', 'umac-64@openssh.com'] client compress:['zlib@openssh.com', 'zlib', 'none'] server compress:['zlib@openssh.com', 'zlib', 'none'] client lang:[''] server lang:[''] kex follows?False DEB [20120913-10:05:07.421] thr=1 paramiko.transport: Ciphers agreed: local=aes128-ctr, remote=aes128-ctr DEB [20120913-10:05:07.421] thr=1 paramiko.transport: using kex diffie-hellman-group1-sha1; server key type ssh-dss; cipher: local aes128-ctr, remote aes128-ctr; mac: local hmac-sha1, remote hmac-sha1; compression: local none, remote none DEB [20120913-10:05:07.625] thr=1 paramiko.transport: Switch to new keys ... INF [20120913-10:05:10.374] thr=2 paramiko.transport.sftp: [chan 1] sftp session closed. DEB [20120913-10:05:10.388] thr=2 paramiko.transport: [chan 1] EOF sent (1)
在这一点之后,脚本将退出并出现此异常(来自sftp.get()try/except块)
There are insufficient resources to complete the request
系统本身有千兆字节的可用磁盘空间,所以这不是问题所在。
parakmiko失败的相同传输在FileZilla和Java应用程序上也很好,这些都是我几年前为进行SFTP传输而编写的。所以我认为这是帕拉米科的问题。
这是在WindowsXP和WindowsServer2003上运行的。
我试过修补Paramko 1.17,以便它更频繁地刷新密钥,但是传输仍然抛出了一个例外。 Python2.7.3 帕拉米科1.7带补丁 Windows 2003服务器
有什么想法?
其他信息: 它在WindowsXPSP3和Windows2003服务器上失败,行为和错误消息完全相同。 系统版本信息 Windows XP工作站:“2.7.3(默认值,2012年4月10日,23:31:26)[MSC v.1500 32位(Intel)] Windows 2003服务器:“2.7.3(默认值,2012年4月10日,23:31:26)[MSC v.1500 32位(Intel)] 我修补了packet.py文件以缩短密钥续订之间的时间。它对sftp.get()的行为没有影响。
我有一个非常类似的问题,在我的情况下,这个文件只有大约400MB,但在下载大约35MB之后,它会一直失败。下载的字节数并不总是完全相同,但在大约35-40 MB的某个地方,文件将停止传输,大约一分钟后,我会得到“没有足够的资源来完成请求”错误。
通过WinSCP或PSFTP下载文件运行良好。
我试过螺旋胶带的方法,但很慢。我的400 MB文件的下载速度大约需要4个小时,这对于这个特定的应用程序来说是一个不可接受的时间段。
而且,有一次,当我们第一次建立这个系统时,一切都很好。但服务器管理员对SFTP服务器做了一些更改,这时出现了问题。我不确定更改是什么,但是由于使用WinSCP/other SFTP方法仍然可以正常工作,所以我认为尝试从服务器端攻击它不会有什么效果。
我不会假装明白为什么,但以下是对我有用的:
我下载并安装了当前版本的Paramiko(此时为1.11.1)。最初这一点都没有影响,但我想我会提到它,以防它是解决方案的一部分。
异常的堆栈跟踪为:
在sftp_file.py中翻了翻,我注意到了这一点(当前版本的第43-45行):
一时兴起,我试着将MAX_REQUEST_的大小改为1024,瞧,我可以下载整个文件了!
在我通过将MAX_REQUEST_SIZE更改为1024来工作之后,我尝试了一系列介于1024和32768之间的其他值,以查看它是否影响性能或其他方面。但是,当值明显大于1024(1025还可以,但1048最终失败)时,我迟早会得到错误。
除了Screwtape的答案之外,还值得一提的是,您应该使用
.read([block size in bytes])
来限制块的大小见lazy method for reading big file
我对2.4中没有块大小的
file.read()
有真正的问题,但是2.7有可能确定正确的块大小。SFTP协议没有流式传输文件数据的方法;相反,它有一种从打开的文件中的特定偏移量请求数据块的方法。下载文件的简单方法是请求第一个块,将其写入磁盘,然后请求第二个块,依此类推。这是可靠的,但非常缓慢。
相反,Paramiko使用了一个性能技巧:当您调用
.get()
时,它会立即向文件中的每个块发送一个请求,并记住它们应该写入的偏移量。然后,当每个响应到达时,它确保将其写入磁盘上的正确偏移量。有关更多信息,请参见Paramiko文档中的SFTPFile.prefetch()
和SFTPFile.readv()
方法。我怀疑它在下载1GB文件时存储的簿记信息可能会导致。。。资源不足,生成“资源不足”消息。如果您只是调用
.open()
来获取SFTPFile
实例,则不使用.get()
,而是调用该对象上的.read()
,或者将其交给Python标准库函数shutil.copyfileobj()
来下载内容。这将避免Paramiko预取缓存,并允许您下载文件,即使它不是很快。即:
相关问题 更多 >
编程相关推荐