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

如何通过Python Paramiko以其他用户身份执行SFTP操作

用服务账户登录后切换用户执行SFTP传输的解决方案

看起来你卡在用服务账户登录后,没法切换到目标用户做文件传输的问题上了。其实核心是要在登录服务账户后,通过sudo切换到目标用户再启动SFTP服务,而不是直接用Paramiko默认的SFTP通道——默认通道是跑在服务账户权限下的。

下面给你一步步的解决方法:

1. 先确保服务账户有sudo权限(关键)

首先得让你的serviceAccount能免密码切换到目标用户(比如叫targetUser)并执行sftp-server。编辑sudoers文件(记得用visudo,别直接编辑!):

sudo visudo

添加一行:

serviceAccount ALL=(targetUser) NOPASSWD: /usr/lib/openssh/sftp-server

这样服务账户就能不用输入密码,以targetUser身份启动SFTP服务了。

2. 修改Paramiko代码实现切换用户后的SFTP

你原来的代码只打开了会话但没正确启动SFTP服务,试试这个完整的示例:

import paramiko

# 服务器信息
server_address = '<你的服务器地址>'
server_port = <端口号,默认22>
service_account = 'serviceAccount'
service_password = '<服务账户密码>'
target_user = '<目标用户名>'

# 建立SSH传输连接
transport = paramiko.Transport((server_address, server_port))
transport.connect(username=service_account, password=service_password)

# 打开会话,执行sudo切换用户并启动sftp-server
channel = transport.open_session()
# 设置终端类型,避免sudo报错
channel.get_pty()
# 执行切换用户并启动sftp服务的命令
channel.exec_command(f'sudo -u {target_user} /usr/lib/openssh/sftp-server')

# 检查命令执行状态,确保没有报错
if channel.recv_exit_status() != 0:
    print(f"启动SFTP服务失败: {channel.recv(1024).decode()}")
    transport.close()
    exit(1)

# 创建SFTP客户端,基于这个切换用户后的通道
sftp = paramiko.SFTPClient.from_channel(channel)

# 现在你可以用sftp对象执行文件操作了,权限是targetUser的!
# 示例:上传本地文件到服务器目标用户的家目录
sftp.put('/本地文件路径', f'/home/{target_user}/目标文件名')
# 示例:下载服务器文件到本地
sftp.get(f'/home/{target_user}/服务器文件名', '/本地保存路径')

# 用完记得关闭连接
sftp.close()
transport.close()

3. 可能遇到的坑

  • 如果你的sudo配置需要输入密码,那上面的代码得处理密码输入:可以在channel.exec_command后,用channel.send('<sudo密码>\n')来输入密码,但还是建议配置免密码sudo更安全方便。
  • 确保/usr/lib/openssh/sftp-server的路径是对的,不同Ubuntu版本可能路径不同,用which sftp-server确认一下。
  • 检查服务器的sshd_config里PermitRootLogin或者AllowUsers有没有限制服务账户登录,确保服务账户能正常SSH登录。

这样应该就能实现你想要的:用服务账户登录,然后以目标用户身份做文件传输了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:36:19