python ftplib ftp.rename() 在某些服务器中抛出错误

python ftplib ftp.rename() throwing error in some servers

刚开始使用 FTP 和 SFTP 编写一些 python 脚本。 SFTP 似乎在所有情况下都能正常工作,但是当脚本尝试使用 FTP 重命名文件时,它在某些服务器上工作并且在某些服务器上抛出错误。我目前正在研究 python 3.9.6 并分享下面的代码示例。

ftp = FTP(host='ip', user='user', passwd='password')

if ftp.size("/path/to/some/directory/filename.txt") is not None:
  print("{} is a file".format("/path/to/some/directory/filename.txt"))
else:
  print("It's NOT a file!")

try:
  print("Downloading file")
  with open("/path/to/some/directory/filename.txt", "wb") as file:
      ftp.retrbinary("RETR %s" %file_path + file_name, file.write)
      file.close()

  print("Download completed!")

  try:
      ftp.rename(fromname="/path/to/some/directory/filename.txt", toname="/path/to/backup/filename" + "_" + str(datetime.datetime.now()).replace(" ", "_") + ".txt")
                      
      print("File renamed.")
  except:
      traceback.print_exc()

except:
  print("Excetion while Downloading file!")
  traceback.print_exc()

ftp.quit()

我已经在 3 个不同的服务器上测试了这段代码。在前 2 个中,我取得了成功(即文件已正确移动)。对于最后一个,我收到以下错误

Traceback (most recent call last):
  File "/path/to/script/ftp.py", line 37, in <module>
    ftp.rename(fromname="/path/to/some/directory/filename.txt", toname="/path/to/backup/filename" + "_" + str(datetime.datetime.now()).replace(" ", "_") + ".txt")
  File "/usr/local/lib/python3.9/ftplib.py", line 604, in rename
    return self.voidcmd('RNTO ' + toname)
  File "/usr/local/lib/python3.9/ftplib.py", line 286, in voidcmd
    return self.voidresp()
  File "/usr/local/lib/python3.9/ftplib.py", line 259, in voidresp
    resp = self.getresp()
  File "/usr/local/lib/python3.9/ftplib.py", line 252, in getresp
    raise error_temp(resp)
ftplib.error_temp: 450 Internal error renaming the file

这只发生在我尝试脚本的最后一个服务器上。我注意到的另一件事是,当我以 FTP 用户身份登录该服务器并尝试手动重命名文件时,重命名命令起作用。这意味着 FTP 用户拥有文件和备份路径的权限。

添加错误和成功案例的 debuglevel(2) 日志。 注意:这些日志来自具有相同脚本的 2 个不同服务器。为了找出问题所在,我只使用了脚本中的重命名代码。

来自脚本 运行s 成功 的服务器的日志 - vsFTPd 3.0.2

Renaming file
cmd 'RNFR /path/to/some/directory/filename.txt'
put 'RNFR /path/to/some/directory/filename.txt\r\n'
get '350 Ready for RNTO.\n'
resp '350 Ready for RNTO.'
cmd 'RNTO /path/to/backup/filename_2022-06-01_10:31:45.765201.txt'
put 'RNTO /path/to/backup/filename_2022-06-01_10:31:45.765201.txt\r\n'
get '250 Rename successful.\n'
resp '250 Rename successful.'
File renamed.

来自脚本失败的服务器的日志 - FileZilla Server 0.9.60 beta

Renaming file
cmd 'RNFR /path/to/some/directory/sample_tst.txt'
put 'RNFR /path/to/some/directory/sample_tst.txt\r\n'
get '350 File exists, ready for destination name.\n'
resp '350 File exists, ready for destination name.'
cmd 'RNTO /path/to/backup/filename_2022-06-01_10:16:45.088433.txt'
put 'RNTO /path/to/backup/filename_2022-06-01_10:16:45.088433.txt\r\n'
get '450 Internal error renaming the file\n'
resp '450 Internal error renaming the file'
Excetion while renaming file: <class 'ftplib.error_temp'>
Traceback (most recent call last):
  File "/opt/APPS/SCRIPT/ftp.py", line 36, in <module>
    ftp.rename(fromname="/path/to/some/directory/filename.txt", toname="/path/to/backup/filename" + "_" + str(datetime.datetime.now()).replace(" ", "_") + ".txt")
  File "/usr/local/lib/python3.9/ftplib.py", line 604, in rename
    return self.voidcmd('RNTO ' + toname)
  File "/usr/local/lib/python3.9/ftplib.py", line 286, in voidcmd
    return self.voidresp()
  File "/usr/local/lib/python3.9/ftplib.py", line 259, in voidresp
    resp = self.getresp()
  File "/usr/local/lib/python3.9/ftplib.py", line 252, in getresp
    raise error_temp(resp)
ftplib.error_temp: 450 Internal error renaming the file

这是我尝试在故障服务器中手动执行时的调试级别日志。

ftp> debug 2
Debugging on (debug=2).
ftp> 
ftp> 
ftp> rename /path/to/some/directory/filename.txt /path/to/backup/filename_2022-06-01_12:16.txt
---> RNFR /path/to/some/directory/filename.txt
350 File exists, ready for destination name.
---> RNTO /path/to/backup/filename_2022-06-01_12:16.txt
250 file renamed successfully
ftp> 

以上是我以 FTP 用户身份登录时尝试使用重命名命令移动它的屏幕截图。

过去几天我一直在研究这个问题,但一无所获。如果有人能帮助我解决这个问题,我将不胜感激。

两台服务器 运行 Red Hat Enterprise Linux

提前致谢。

问题出在文件名上。不支持完整的冒号。因此,我没有附加完整的时间戳,而是将其格式化如下。

ftp.rename(fromname="/path/to/some/directory/filename.txt", toname="/path/to/backup/filename" + "_" + str(datetime.datetime.now().strftime("%Y-%m-%d %H%M%S")).replace(" ", "_") + ".txt")

现在可以使用了。 谢谢@Martin 指出错误。