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

Python脚本中树莓派scp+SSH密钥免密传输失效问题求助

问题描述

本地树莓派终端中使用scp配合SSH密钥对,可免密码将文件传输至远程树莓派pi@192.168.0.15。但在Python脚本中通过os.system()执行相同scp命令时,终端会中断脚本并提示输入远程账户的密码。已尝试多种SSH密钥对配置教程,问题仍未解决,求解决思路。

附上的Python代码如下:

# Simple example of reading the MCP3008 analog input channels and printing
# them all out.
# Author: Tony DiCola
# License: Public Domain
import time

# Import SPI library (for hardware SPI) and MCP3008 library.
import Adafruit_GPIO.SPI as SPI
import Adafruit_MCP3008
import os

# Software SPI configuration:
# CLK = 18
# MISO = 23
# MOSI = 24
# CS = 25
# mcp = Adafruit_MCP3008.MCP3008(clk=CLK, cs=CS, miso=MISO, mosi=MOSI)

# Hardware SPI configuration:
SPI_PORT = 0
SPI_DEVICE = 0
mcp = Adafruit_MCP3008.MCP3008(spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE))

num = 1

print('Reading MCP3008 values, press Ctrl-C to quit...')
# Print nice channel column headers.
print('| {0:>4} | {1:>4} | {2:>4} | {3:>4} | {4:>4} | {5:>4} | {6:>4} | {7:>4} |'.format(*range(8)))
print('-' * 57)
# Main program loop.
while True:
    # Read all the ADC channel values in a list.
    values = [0]*8
    for i in range(8):
        # The read_adc function will get the value of the specified channel (0-7).
        values[i] = mcp.read_adc(i)
    # Print the ADC values.
    print('| {0:>4} | {1:>4} | {2:>4} | {3:>4} | {4:>4} | {5:>4} | {6:>4} | {7:>4} |'.format(*values))
    # Check if distance of object has increased, take a picture if it has.
    if values[0] < 100:
        num = num + 1
        imagename = str(num)
        os.system("raspistill -vf -ex night -o "+imagename)
        os.system("scp /home/pi/Adafruit_Python_MCP3008/examples/"+imagename+" pi@192.168.0.15:/home/pi/Pictures")
    else:
        # Pause for half a second.
        time.sleep(0.5)
解决方案

嘿,我之前也碰到过一模一样的情况——手动在终端用scp能免密传输,但Python脚本里跑就卡在密码输入环节,折腾了好一阵才搞明白。核心问题基本都是脚本运行的环境和你手动操作的终端环境不一致,或者scp在脚本里没正确识别到密钥配置。给你几个具体的排查和解决方向:

1. 确认脚本的运行用户身份

你手动执行scp时用的是pi用户对吧?那得先搞清楚Python脚本是不是也用同一个用户在运行。比如如果你是用sudo python3 your_script.py启动的脚本,那运行用户就是root,而root的SSH密钥配置和pi是完全分开的,自然会要求输入密码。

你可以在脚本里加几行代码验证当前用户:

import getpass
print(f"当前运行脚本的用户: {getpass.getuser()}")

如果输出不是pi,有两个解决方向:

  • 换用pi用户启动脚本(直接运行python3 your_script.py,不要加sudo);
  • 给当前运行的用户(比如root)配置SSH密钥:把该用户的~/.ssh/id_rsa.pub内容复制到远程pi@192.168.0.15的~/.ssh/authorized_keys里,同时确保该用户的.ssh目录权限是700,authorized_keys文件权限是600(执行chmod 700 ~/.ssh和chmod 600 ~/.ssh/authorized_keys)。

2. 显式指定密钥文件路径

有时候脚本运行时的环境变量没正确加载,导致scp找不到默认的私钥文件。这时候直接在scp命令里指定私钥路径就能解决问题,把你的scp命令改成:

os.system(f"scp -i /home/pi/.ssh/id_rsa /home/pi/Adafruit_Python_MCP3008/examples/{imagename} pi@192.168.0.15:/home/pi/Pictures")

这里/home/pi/.ssh/id_rsa是你本地私钥的路径,一定要确保路径正确,而且私钥文件的权限是600(执行chmod 600 /home/pi/.ssh/id_rsa)——SSH对密钥文件的权限要求很严格,权限太宽会直接拒绝使用。

3. 查看scp的详细日志定位问题

给scp命令加上-v参数,打印详细的执行日志,这样能精准定位问题出在哪一步:

os.system(f"scp -v /home/pi/Adafruit_Python_MCP3008/examples/{imagename} pi@192.168.0.15:/home/pi/Pictures")

运行脚本后,终端会输出大量日志,你可以重点关注:

  • 是否尝试加载了你的私钥文件;
  • 远程服务器是否接受了你的密钥;
  • 是否出现了权限相关的错误信息。
    根据日志就能快速找到问题的根源。

4. 替换os.system为subprocess模块(更可靠的选择)

os.system是比较老旧的模块,很难捕获命令的输出和错误信息。换成subprocess.run不仅能更灵活地控制命令执行,还能直接获取scp的错误输出,方便排查问题:

import subprocess

# 替换原来的os.system(scp命令)为下面的代码
scp_cmd = [
    "scp", "-i", "/home/pi/.ssh/id_rsa",
    f"/home/pi/Adafruit_Python_MCP3008/examples/{imagename}",
    "pi@192.168.0.15:/home/pi/Pictures"
]
result = subprocess.run(scp_cmd, capture_output=True, text=True)
print("SCP执行输出:", result.stdout)
print("SCP错误信息:", result.stderr)

这样如果scp执行失败,你能直接看到具体的错误原因,比如密钥找不到、权限不足等。

5. 检查SSH_AUTH_SOCK环境变量

手动在终端运行echo $SSH_AUTH_SOCK,然后在脚本里也打印这个变量:

import os
print(f"SSH_AUTH_SOCK环境变量: {os.environ.get('SSH_AUTH_SOCK')}")

如果脚本里的输出是空的,说明ssh-agent没在脚本的环境中运行,导致scp无法通过代理获取密钥。这种情况下,要么显式在脚本里启动ssh-agent并添加密钥,要么就用上面第2种方法直接指定密钥路径(后者更简单)。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:30:51