如何确认 SFTP 文件传送?

How to confirm SFTP file delivery?

我正在使用 SFTP 和非 root 用户的 public 密钥发送文件,看起来文件已发送,但我无法在目标文件夹中找到它,可能是由于权限问题。

sftp> ls
sftp> put /tmp/testx
Uploading /tmp/testx to /folder1/target_folder
/tmp/testx                                 100%    5     0.0KB/s   00:01
sftp> get testx
Couldn't stat remote file: No such file or directory
File "/folder1/target_folder/testx" not found.
sftp> ls
sftp>

这是 -vvv :

debug3: SSH_FXP_REALPATH . -> /folder1
debug3: Looking up /tmp/file_to_send
debug3: Sent message sender_host 4 T:17 I:2
debug3: Wrote 80 bytes for a total of 2653
debug3: Received stat reply T:105 I:2
debug3: Sent message SSH2_FXP_OPEN I:3 P:/folder1/target_directory/file_to_send
debug3: Wrote 112 bytes for a total of 2765
debug3: Sent message SSH2_FXP_WRITE I:4 O:0 S:6206
debug3: Wrote 6288 bytes for a total of 9053
debug3: SSH2_FXP_STATUS 0

目标目录

 drw-rw-rw-    1  0   0       target_directory

如何在没有服务器访问权限的情况下确保文件已交付?

对于完全任意的服务器实现,这是不可能的。通常需要将传入目录设置为对不受信任的用户只写,以防止滥用公开(或其他广泛) 可访问的文件服务器(例如使用它们来托管不相关的内容;曾几何时,FTP 具有被盗凭据的服务器经常被盗版者使用——阻止上传的内容在未经行政审查的情况下被下载可以防止这种情况发生)。因此:如果服务器管理员选择不让你看到上传的文件,那么,你就看不到上传的文件了。

然而 -- SFTP 协议提供了一个契约:如果你告诉服务器在写入一个句柄后关闭它,并且服务器说所有涉及的操作都成功且没有错误,那么如果文件没有成功接收(无论服务器随后决定如何处理它,这可能包括也可能不包括使其可供下载),这表明服务器端存在错误,而不是您的错误 SFTP 客户.

当我上次实现自定义 SFTP 服务器时——出于客户支持目的,使用 Paramiko 实现——我在成功上传后发送了电子邮件通知;不过,显然,这是特定于实现的行为)。

您所能做的就是在上传文件时检查没有错误。这就是 SFTP 服务器为您提供的所有信息。

使用命令行 OpenSSH sftp 客户端,您可以检查其退出代码(您需要使用 -b 开关)。

echo "put file.txt" | sftp -b - user@host
if [ $? -eq 0 ]
then
    echo "File uploaded"
else
    echo "File NOT uploaded"
fi

另见 How to perform checksums during a SFTP file transfer for data integrity?


很可能是 SFTP 服务器不允许您下载刚刚上传的文件。

这种行为有两个常见原因:

  • Public“上传”目录。这是为了防止您下载其他用户的文件。
  • 有些进程会立即选择上传的文件进行某些处理。

我知道这是一个旧线程... 这是我能够使用 openssh sftp 客户端将密码验证上传到盲文件夹的最佳方法。 (ftp 更准确...)

SSHPASS=${PASSWORD} sshpass -e sftp -vvv -oStrictHostKeyChecking=no -oBatchMode=no -b - ${LOGON}@${FTPSITE} >${LOB}ftp.log 2>&1 <<EOF
pwd
cd upload
put ${XMTFILE}
quit
EOF
# sftp does not use FTP codes - it only gives the final status of the requested operation
Status=$?
# Not perfect, but sending a single file using -vvv should produce 2 lines containing "debug3: SSH2_FXP_STATUS 0"
Tmp=`grep "debug3: SSH2_FXP_STATUS 0" ${LOB}ftp.log | wc -l`
[ ${Tmp} -ne 2 ] && Status=1 # Override sftp exit value based on log info