You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Paramiko SFTP上传时触发FileNotFoundError问题排查

问题:SFTP上传时出现FileNotFoundError

运行Flask上传代码时,执行sftp.putfo操作时报错FileNotFoundError: [Errno 2] No such file,怀疑与SSH配置Subsystem sftp internal-sftp有关,需排查解决。

相关代码

@app.route('/success', methods=['POST'])
def success():
    try:
        now = datetime.now()
        dt_string = now.strftime("%d/%m/%Y %H:%M:%S")
        print("You are uploading at", dt_string)

        hostname = socket.gethostname()
        client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        client_socket.connect((ip, 9090))  # Connect to server
        UUID = str(uuid.uuid4())
        header_data = "{ \n" + socket.gethostbyname(hostname) + "\n SCOPE:upload \n" + dt_string + "\n" + UUID + "\n}"
        with open("header.txt", "w") as datasave:
            datasave.write(header_data)

        client_socket.send(header_data.encode())
        data_from_server = client_socket.recv(1024).decode()

        with open("header_response.txt", "w") as datasave:
            datasave.write(data_from_server)
        print(data_from_server)

        with open("header_response.txt", "r") as header_file:
            header = header_file.read()
            usr = header.split("USR: ")[1].split("\n")[0].strip()
            passwd = header.split("PASSWD: ")[1].split("\n")[0].strip()
        os.system("sudo rm header_response.txt")
        os.system("sudo rm header.txt")
        ssh = paramiko.SSHClient()
        ssh.load_system_host_keys()
        ssh.connect(ip, username=usr, password=passwd)
        print('a trecut')
        sftp = ssh.open_sftp()
        with open("data.nimb", 'w') as d:
            d.write(UUID + '\n' + dt_string + "\n")
        with open('data.nimb', 'rb') as miau:
            with paramiko.SSHClient() as ssh:
                sftp.putfo(miau, '/incoming/' + "data.nimb")
        os.remove('data.nimb')
        code = str(random.randint(1000000000, 9999999999))
        con = sqlite3.connect(db_file)
        cursor = con.cursor()
        cursor.execute("INSERT INTO users (username, password, code, uuid) VALUES (?, ?, ?, ?)",
                       (usr, passwd, code, UUID))
        con.commit()


        uploaded_filenames = []  # Initialize a list to store uploaded filenames

        for uploaded_file in request.files.getlist('file'):
            filename = uploaded_file.filename
            uploaded_filenames.append(filename)  # Save the filename to the list
            sftp.putfo(uploaded_file, '/incoming/' + filename)

        sftp.close()
        ssh.close()

        #print(uploaded_filenames)
        # Send the uploaded filenames to the specified IP address
        #send_filenames(uploaded_filename)

        return render_template('success.html', code=code, filenames=uploaded_filenames)

    except Exception as e:
        traceback.print_exc()  # Print traceback information including line number
        app.logger.error('An error occurred: {}'.format(str(e)))
        # Handle the error and return an appropriate response
        return render_template('error.html', message="An error occurred")

报错信息

Traceback (most recent call last):
  File "/home/nimbus-pi/mlrasp/web/app.py", line 81, in success
    sftp.putfo(miau, '/incoming/' + "data.nimb")
  File "/root/.pyenv/versions/3.9.16/lib/python3.9/site-packages/paramiko/sftp_client.py", line 714, in putfo
    with self.file(remotepath, "wb") as fr:
  File "/root/.pyenv/versions/3.9.16/lib/python3.9/site-packages/paramiko/sftp_client.py", line 372, in open
    t, msg = self._request(CMD_OPEN, filename, imode, attrblock)
  File "/root/.pyenv/versions/3.9.16/lib/python3.9/site-packages/paramiko/sftp_client.py", line 822, in _request
    return self._read_response(num)
  File "/root/.pyenv/versions/3.9.16/lib/python3.9/site-packages/paramiko/sftp_client.py", line 874, in _read_response
    self._convert_status(msg)
  File "/root/.pyenv/versions/3.9.16/lib/python3.9/site-packages/paramiko/sftp_client.py", line 903, in _convert_status
    raise IOError(errno.ENOENT, text)
FileNotFoundError: [Errno 2] No such file
[2023-07-15 19:57:54,939] ERROR in app: An error occurred: [Errno 2] No such file

排查与解决方案

1. 修复代码逻辑错误

上传data.nimb时多余嵌套的paramiko.SSHClient()上下文会覆盖原有ssh变量,导致SFTP连接异常,修改该段代码:

原错误代码:

with open('data.nimb', 'rb') as miau:
    with paramiko.SSHClient() as ssh:
        sftp.putfo(miau, '/incoming/' + "data.nimb")

修改为:

with open('data.nimb', 'rb') as miau:
    sftp.putfo(miau, '/incoming/data.nimb')

2. 确认远程目录存在且权限合规

  • 登录远程服务器,检查/incoming目录是否存在:
    ls -ld /incoming
    
    不存在则创建:
    mkdir -p /incoming
    
  • 确保登录用户usr拥有该目录读写权限:
    chown usr:usr /incoming  # 替换为实际用户及用户组
    chmod 755 /incoming
    

3. 检查SSH的internal-sftp配置

若使用Subsystem sftp internal-sftp并配置ChrootDirectory,需注意:

  • ChrootDirectory指定的路径必须由root用户拥有,权限为755(不可设为777)
  • /incoming需位于ChrootDirectory内部,例如ChrootDirectory /home/chroot时,实际物理路径为/home/chroot/incoming,需确保该路径存在且权限正确
  • 确认SSH配置文件(通常为/etc/ssh/sshd_config)的相关配置:
    Subsystem sftp internal-sftp
    Match User usr
        ChrootDirectory /home/chroot
        ForceCommand internal-sftp
        AllowTcpForwarding no
        X11Forwarding no
    
    修改后重启SSH服务:
    sudo systemctl restart sshd
    

4. 代码优化(可选)

使用上下文管理器自动管理SSH和SFTP连接,避免手动关闭导致的资源泄漏:

# 替换原有的ssh和sftp初始化代码
with paramiko.SSHClient() as ssh:
    ssh.load_system_host_keys()
    ssh.connect(ip, username=usr, password=passwd)
    with ssh.open_sftp() as sftp:
        # 所有SFTP操作都在此块内执行
        with open("data.nimb", 'w') as d:
            d.write(UUID + '\n' + dt_string + "\n")
        with open('data.nimb', 'rb') as miau:
            sftp.putfo(miau, '/incoming/data.nimb')
        os.remove('data.nimb')

        # 处理文件上传循环
        uploaded_filenames = []
        for uploaded_file in request.files.getlist('file'):
            filename = uploaded_file.filename
            uploaded_filenames.append(filename)
            sftp.putfo(uploaded_file, f'/incoming/{filename}')

内容的提问来源于stack exchange,提问作者VladAndrei

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 22:15:12