使用Paramiko通过SSH访问VM共享文件夹失败问题排查
在Windows 10上用VMware搭建Ubuntu 20虚拟机,已将本地ubuntu_shared文件夹共享给虚拟机。手动通过Windows命令行ssh <user>@<host>登录后,执行cd /mnt/hgfs/ubuntu_shared可以正常访问共享目录,但用Python Paramiko库执行相同操作时报错。
使用的代码:
k = paramiko.RSAKey.from_private_key_file(LOCAL_SSH_PRIVATE_KEY) ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) num_tries = 0 ssh_connected = False while not ssh_connected and num_tries < 10: try: ssh.connect(hostname=VM_HOST, username=VM_USER, allow_agent=False, pkey=k) ssh_connected = True print(f"connected via ssh to {VM_USER}@{VM_HOST}") except Exception as e: print("still trying...") num_tries += 1 time.sleep(1) if not ssh_connected: ssh.close() raise Exception(f"failed to connect : {e}") command = "cd /mnt/hgfs/ubuntu_shared" stdin, stdout, stderr = ssh.exec_command(command) if stderr: print(stderr.read().decode())
报错信息:
sh: line 0: cd: /mnt/hgfs/ubuntu_shared: Not a directory
核心原因:Paramiko的
exec_command默认启动非交互式Shell,不会加载用户的Shell配置文件(如~/.bashrc、~/.profile)。手动SSH登录时是交互式Shell,这些配置文件会被执行,其中可能包含自动挂载VMware共享目录(hgfs)的逻辑,导致非交互式Shell下/mnt/hgfs/ubuntu_shared目录不存在。另外,单独执行cd命令在exec_command中无实际意义——每个exec_command都是独立进程,执行完cd后进程就退出,后续命令不会继承这个目录位置。解决方法:
强制使用交互式Shell执行命令
将命令改为通过交互式bash执行,加载用户配置文件自动完成共享目录挂载:command = "bash -i -c 'cd /mnt/hgfs/ubuntu_shared && <你要执行的后续命令>'" stdin, stdout, stderr = ssh.exec_command(command)替换
<你要执行的后续命令>为实际需要在共享目录下运行的操作(比如ls查看文件)。手动挂载共享目录后再执行操作
若不想依赖Shell配置,可在命令中先手动挂载共享目录:command = "sudo mount -t vmhgfs .host:/ubuntu_shared /mnt/hgfs/ubuntu_shared && cd /mnt/hgfs/ubuntu_shared && <你要执行的后续命令>" stdin, stdout, stderr = ssh.exec_command(command, get_pty=True) # 若需要输入sudo密码,可通过stdin.write("你的密码\n")传入需确保用户有免密sudo权限,或在代码中处理密码输入。
配置系统自动挂载共享目录
编辑Ubuntu的/etc/fstab文件,添加自动挂载条目,让系统启动时就挂载共享目录:.host:/ubuntu_shared /mnt/hgfs/ubuntu_shared vmhgfs defaults 0 0执行
sudo mount -a生效后,无论交互式还是非交互式Shell,/mnt/hgfs/ubuntu_shared都会存在,直接执行命令即可:command = "cd /mnt/hgfs/ubuntu_shared && <你要执行的后续命令>" stdin, stdout, stderr = ssh.exec_command(command)
内容的提问来源于stack exchange,提问作者Flabala

