วิธีการสแกนใน Python


158

pythonic เป็นวิธีที่ดีที่สุดในการสแกนไฟล์ใน Python คืออะไร? เส้นทางเดียวที่ฉันรู้คือ

os.system('scp "%s" "%s:%s"' % (localfile, remotehost, remotefile) )

ซึ่งเป็นแฮ็กและไม่ทำงานนอกระบบเหมือน Linux และต้องการความช่วยเหลือจากโมดูล Pexpect เพื่อหลีกเลี่ยงการแจ้งรหัสผ่านเว้นแต่คุณตั้ง SSH ไร้รหัสผ่านไว้ที่รีโมตโฮสต์แล้ว

ฉันรู้เรื่อง Twisted conchแต่ฉันต้องการหลีกเลี่ยงการใช้ scp เองผ่านโมดูล ssh ระดับต่ำ

ฉันรู้paramikoแล้วว่าเป็นโมดูล Python ที่รองรับ SSH และ SFTP แต่มันไม่รองรับ SCP

ความเป็นมา: ฉันกำลังเชื่อมต่อกับเราเตอร์ที่ไม่รองรับ SFTP แต่รองรับ SSH / SCP ดังนั้น SFTP จึงไม่ใช่ตัวเลือก

แก้ไข : นี่เป็นสิ่งที่ซ้ำกันของวิธีการคัดลอกไฟล์ไปยังเซิร์ฟเวอร์ระยะไกลใน Python โดยใช้ SCP หรือ SSH? . อย่างไรก็ตามคำถามนั้นไม่ได้ให้คำตอบเฉพาะ SCP ที่เกี่ยวข้องกับคีย์จากภายใน Python ฉันหวังว่าจะมีวิธีเรียกใช้โค้ดที่คล้ายกัน

import scp

client = scp.Client(host=host, user=user, keyfile=keyfile)
# or
client = scp.Client(host=host, user=user)
client.use_system_keys()
# or
client = scp.Client(host=host, user=user, password=password)

# and then
client.transfer('/etc/local/filename', '/etc/remote/filename')

คำตอบ:


106

ลองโมดูลหลาม SCP สำหรับ Paramiko มันใช้งานง่ายมาก ดูตัวอย่างต่อไปนี้:

import paramiko
from scp import SCPClient

def createSSHClient(server, port, user, password):
    client = paramiko.SSHClient()
    client.load_system_host_keys()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    client.connect(server, port, user, password)
    return client

ssh = createSSHClient(server, port, user, password)
scp = SCPClient(ssh.get_transport())

จากนั้นเรียกscp.get()หรือscp.put()ดำเนินการ SCP

( รหัส SCPClient )


3
ยกเว้นว่าโมดูลนั้นไม่ได้ใช้ paramiko จริง ๆ - มันเป็นรหัสจำนวนมากซึ่งในที่สุดแล้วสำหรับการscpเรียกscpบรรทัดคำสั่งที่ใช้งานได้จริงบน * nix เท่านั้น
Nick Bastin

8
เห็นด้วยสิ่งที่คุณเห็นในซอร์สโค้ดคือการโทรระยะไกลไปยังscp -tหรือscp -f('ถึง' และ 'จาก' โหมดซึ่งมีอยู่เพื่อจุดประสงค์ด้านเซิร์ฟเวอร์นี้) นี่คือหลักการทำงานของ scp - มันอาศัยสำเนาของ scp อื่นที่มีอยู่บนเซิร์ฟเวอร์ บทความนี้จะอธิบายได้เป็นอย่างดี: blogs.oracle.com/janp/entry/how_the_scp_protocol_works
laher

8
วิธีแก้ปัญหานี้ใช้ได้กับฉันด้วยคำเตือนสองข้อ: 1. นี่คือคำสั่งการนำเข้าที่ฉันใช้: import paramiko from scp import SCPClient2. นี่คือตัวอย่างของคำสั่ง scp.get ():scp.get(r'/nfs_home/appers/xxxx/test2.txt', r'C:\Users\xxxx\Desktop\MR_Test')
Chris Nielsen

สิ่งนี้ไม่เพียงใช้งานได้ดี แต่ยังใช้ประโยชน์จากปุ่ม SSH หากมีอยู่
Marcel Wilson

โปรดทราบว่าคุณสามารถติดตั้ง lib นี้จาก PyPI ได้เช่นกัน: pip install scpที่เวอร์ชัน 0.10.2 ตามการเขียนนี้
Andrew B.

15

คุณอาจสนใจลองPexpect ( ซอร์สโค้ด ) นี่จะช่วยให้คุณสามารถจัดการกับพรอมต์โต้ตอบสำหรับรหัสผ่านของคุณ

นี่คือตัวอย่างการใช้งาน (สำหรับ ftp) จากเว็บไซต์หลัก:

# This connects to the openbsd ftp site and
# downloads the recursive directory listing.
import pexpect
child = pexpect.spawn ('ftp ftp.openbsd.org')
child.expect ('Name .*: ')
child.sendline ('anonymous')
child.expect ('Password:')
child.sendline ('noah@example.com')
child.expect ('ftp> ')
child.sendline ('cd pub')
child.expect('ftp> ')
child.sendline ('get ls-lR.gz')
child.expect('ftp> ')
child.sendline ('bye')

11

นอกจากนี้คุณยังสามารถตรวจสอบparamiko ไม่มีโมดูล scp (ยัง) แต่รองรับ sftp อย่างสมบูรณ์

[แก้ไข] ขออภัยพลาดสายที่คุณพูดถึง paramiko โมดูลต่อไปนี้เป็นเพียงการติดตั้งโปรโตคอล scp สำหรับ paramiko หากคุณไม่ต้องการใช้ paramiko หรือ conch (การใช้ ssh เพียงอย่างเดียวที่ฉันรู้จักสำหรับ python) คุณสามารถทำงานซ้ำนี้เพื่อให้ทำงานในเซสชัน ssh ปกติโดยใช้ไพพ์

scp.py สำหรับ paramiko


คุณกำลังบอกว่าโซลูชันที่เชื่อมต่อจะถ่ายโอนไฟล์ไปยังเครื่องที่ใช้ sshd อย่างปลอดภัยแม้ว่าจะไม่ได้ใช้ sftpd ก็ตาม นั่นคือสิ่งที่ฉันกำลังมองหา แต่ฉันไม่สามารถบอกได้จากความคิดเห็นของคุณว่านี่เป็นแค่การห่อหุ้ม SFTP ในส่วนหน้าของ scp
Michael Gundlach

2
นี่จะถ่ายโอนไฟล์ด้วยเครื่องที่ใช้ sshd ซึ่งมี scp ใน PATH (scp ไม่ใช่ส่วนหนึ่งของข้อมูลจำเพาะของ ssh แต่มันค่อนข้างแพร่หลาย) สิ่งนี้เรียกใช้ "scp -t" บนเซิร์ฟเวอร์และใช้โปรโตคอล scp เพื่อถ่ายโอนไฟล์ซึ่งไม่มีส่วนเกี่ยวข้องกับ sftp
JimB

1
โปรดทราบว่าฉันใช้การติดตั้ง scp ของ openssh เป็นโมเดลดังนั้นจึงไม่รับประกันว่าจะทำงานกับเวอร์ชันอื่นได้ sshd บางเวอร์ชันอาจใช้โปรโตคอล scp2 ซึ่งโดยพื้นฐานแล้วเหมือนกับ sftp
JimB

คุณช่วยโปรดดูคำถามนี้: stackoverflow.com/questions/20111242/… ฉันสงสัยว่า paramiko ใช้กระบวนการย่อยหรือสิ่งอื่นเช่นซ็อกเก็ต ฉันมีปัญหาหน่วยความจำโดยใช้ subprocess.check_output ('ssh blah@blah.com "cat / data / file *") เนื่องจากปัญหา clone / fork และฉันสงสัยว่า paramiko จะมีปัญหาเดียวกันหรือไม่?
พอล

1
@Paul: paramiko จะไม่มีปัญหาเดียวกันเนื่องจากไม่ได้ใช้กระบวนการย่อย
JimB

9

ไม่พบคำตอบที่ตรงและโมดูล "scp.Client" นี้ไม่มีอยู่ แต่สิ่งนี้เหมาะกับฉัน:

from paramiko import SSHClient
from scp import SCPClient

ssh = SSHClient()
ssh.load_system_host_keys()
ssh.connect('example.com')

with SCPClient(ssh.get_transport()) as scp:
   scp.put('test.txt', 'test2.txt')
   scp.get('test2.txt')

6

ถ้าคุณติดตั้ง putty บน win32 คุณจะได้รับ pscp (putty scp)

ดังนั้นคุณสามารถใช้ระบบปฏิบัติการ os.system บน win32 ได้เช่นกัน

(และคุณสามารถใช้ putty-agent สำหรับการจัดการคีย์)


ขออภัยเป็นเพียงแฮ็ค (แต่คุณสามารถสรุปได้ในคลาสไพ ธ อน)


เหตุผลเดียวที่การทำงานของ 'ระวัง' คือคุณมี SCP อยู่บนเส้นทาง ดังที่ Blauohr ชี้ให้เห็นนั่นไม่ใช่เรื่องยากที่จะแก้ไข +1
ojrac

6

คุณสามารถใช้แพ็คเกจย่อยและการเรียกใช้คำสั่งเพื่อใช้คำสั่ง scp จากเชลล์

from subprocess import call

cmd = "scp user1@host1:files user2@host2:files"
call(cmd.split(" "))

2
สิ่งนี้แตกต่างอย่างมากจากกรณีพื้นฐานที่ผู้ถามกล่าวถึงอย่างไร ใช่กระบวนการย่อยจะดีกว่า os.system แต่ในทั้งสองกรณีก็ไม่ได้ทำงานนอกลินุกซ์เหมือนระบบมีปัญหาเกี่ยวกับการแจ้งรหัสผ่าน ฯลฯ
Foon

5

ณ วันนี้ทางออกที่ดีที่สุดน่าจะเป็น AsyncSSH

https://asyncssh.readthedocs.io/en/latest/#scp-client

async with asyncssh.connect('host.tld') as conn:
    await asyncssh.scp((conn, 'example.txt'), '.', recurse=True)

1
สวัสดี คุณอ้างสิทธิ์เกี่ยวกับ AsyncSSH ว่าดีที่สุด แต่คุณสามารถสร้างคำสั่งหรือ 2 เพื่อสนับสนุนข้อเรียกร้องนี้ได้หรือไม่? อาจแยกความแตกต่างจาก scp () หรือความสำคัญกับกรณีการใช้งานของคุณ (สิ่งนี้กล่าวว่ามันเป็นรหัสที่น้อยกว่ามาก - ในตัวอย่างของคุณอย่างน้อย)
Scott Prive

2
@Crossfit_and_Beer สวัสดี ดังนั้นฉันจึงพูดว่า "น่าจะดีที่สุด" ฉันจะให้การตัดสินกับทุกคน :) ฉันไม่ได้มีเวลามากตอนนี้เพื่อเปรียบเทียบ AsyncSSH กับห้องสมุดอื่น ๆ แต่อย่างรวดเร็ว: มันใช้งานง่ายมันไม่ตรงกันมันได้รับการบำรุงรักษาและผู้ดูแลนั้นดีมากและให้ความช่วยเหลือดีมันค่อนข้างสมบูรณ์และบันทึกไว้อย่างดี
Loïc

5

มีลักษณะที่fabric.transfer

from fabric import Connection

with Connection(host="hostname", 
                user="admin", 
                connect_kwargs={"key_filename": "/home/myuser/.ssh/private.key"}
               ) as c:
    c.get('/foo/bar/file.txt', '/tmp/')

2
คุณเจาะจงมากกว่านี้ไหม?
Nick T

4

ไม่นานนักตั้งแต่มีการถามคำถามนี้และในขณะเดียวกันก็มีห้องสมุดอื่นที่สามารถจัดการสิ่งนี้ได้ถูกครอบตัด: คุณสามารถใช้ฟังก์ชันคัดลอกที่รวมอยู่ในไลบรารีPlumbum :

import plumbum
r = plumbum.machines.SshMachine("example.net")
   # this will use your ssh config as `ssh` from shell
   # depending on your config, you might also need additional
   # params, eg: `user="username", keyfile=".ssh/some_key"`
fro = plumbum.local.path("some_file")
to = r.path("/path/to/destination/")
plumbum.path.utils.copy(fro, to)

ฉันจะป้อนวลีรหัสผ่านสำหรับกุญแจส่วนตัวด้วย Plumbum ได้อย่างไร p
ekta

@ekta: คุณจะได้รับแจ้งในบรรทัดคำสั่ง หากคุณต้องการที่จะให้มันจากรหัสของคุณเองฉันไม่คิดว่า plumbum ของ API รองรับสิ่งนี้ แต่ plumbum SshMachineก็สามารถเข้าถึงได้ssh-agentดังนั้นหากคุณต้องการหลีกเลี่ยงการพิมพ์ทุกครั้งนั่นเป็นวิธีหนึ่งที่ทำได้ คุณสามารถยื่นคำขอคุณสมบัติในหน้า github ของ plumbum
pmos


2
import paramiko

client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

client.connect('<IP Address>', username='<User Name>',password='' ,key_filename='<.PEM File path')

#Setup sftp connection and transmit this script 
print ("copying")

sftp = client.open_sftp() 
sftp.put(<Source>, <Destination>)


sftp.close()

มันจะช่วยถ้าคุณเพิ่มความเห็นในคำตอบของคุณอธิบายว่าทำไมโซลูชันของคุณดีและช่วยให้ผู้อ่านเปรียบเทียบกับโซลูชันอื่น ๆ ที่มี การโพสต์โค้ดไม่ได้ช่วยให้ผู้เรียนรู้วิธีรู้จักวิธีแก้ปัญหาที่ดีกว่าเสมอไป
Brian Tompsett - 汤莱恩

นี่คือ SFTP ไม่ใช่ SCP
Martin Prikryl

1

อืมบางทีตัวเลือกอื่นอาจจะใช้บางอย่างเช่นsshfs (มีsshfsสำหรับ Mac ด้วย) เมื่อติดตั้งเราเตอร์แล้วคุณสามารถคัดลอกไฟล์ได้ทันที ฉันไม่แน่ใจว่าเหมาะกับแอปพลิเคชันของคุณหรือไม่


1

เมื่อไม่นานมานี้ฉันได้รวบรวมสคริปต์คัดลอก SCP ไพ ธ อนซึ่งขึ้นอยู่กับ paramiko มันมีรหัสในการจัดการการเชื่อมต่อกับคีย์ส่วนตัวหรือตัวแทนคีย์ SSH ที่มีการรับรองความถูกต้องทางเลือกในการย้อนกลับไปยังรหัสผ่าน

http://code.activestate.com/recipes/576810-copy-files-over-ssh-using-paramiko/


ขอบคุณสำหรับลิงค์และสละเวลาในการเผยแพร่ตัวอย่างที่ดีของการใช้ paramiko
Peter M. - ย่อมาจาก Monica

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.