এসসিপি বা এসএসএইচ ব্যবহার করে পাইথনের রিমোট সার্ভারে কীভাবে একটি ফাইল অনুলিপি করবেন?


103

আমার আমার স্থানীয় মেশিনে একটি পাঠ্য ফাইল রয়েছে যা ক্রোন চালিত দৈনিক পাইথন স্ক্রিপ্ট দ্বারা উত্পন্ন হয়।

এই ফাইলটি আমার সার্ভারে এসএসএইচে নিরাপদে প্রেরণ করতে আমি কিছুটা কোড যুক্ত করতে চাই।


1
অনুরূপ কিছু পাওয়া যায় নি, তোমার দর্শন লগ করা একটি চেহারা থাকতে পারে stackoverflow.com/questions/11009308/...
JJ84

উত্তর:


55

আপনি কল করতে পারেন scpব্যাশ কমান্ড (এটা কপি উপর ফাইলগুলির , SSH ) সঙ্গে subprocess.run:

import subprocess
subprocess.run(["scp", FILE, "USER@SERVER:PATH"])
#e.g. subprocess.run(["scp", "foo.bar", "joe@srvr.net:/path/to/foo.bar"])

আপনি যদি সেই পাইথন প্রোগ্রামে যে ফাইলটি প্রেরণ করতে চান তা যদি আপনি তৈরি করে থাকেন তবে আপনি ফাইলটি খোলার জন্য subprocess.runযে withব্লকটি ব্যবহার করছেন তার বাইরে কমান্ড কল করতে চাইবে (বা .close()আপনি যদি ফাইলটি ব্যবহার না করছেন তবে প্রথমে ফাইলটিতে কল করুন) withঅবরুদ্ধ করুন), সুতরাং আপনি জানেন যে এটি পাইথন থেকে ডিস্কে ফ্লাশ হয়েছে।

আপনাকে পূর্বেই (উত্স মেশিনে) তৈরি এবং (গন্তব্য মেশিনে) একটি এসএস কী ইনস্টল করতে হবে যাতে স্ক্রিপটি আপনার পাবলিক এসএস কী দিয়ে স্বয়ংক্রিয়ভাবে প্রমাণিত হয় (অন্য কথায়, যাতে আপনার স্ক্রিপ্টটি পাসওয়ার্ড জিজ্ঞাসা করে না) ।


3
@CharlesDuffy: subprocess.check_call(['scp', srcfile, dest])পাইথন 2.5 পরিবর্তে যেহেতু ব্যবহার করা যেতে পারেrc = Popen(..).wait(); if rc != 0: raise ..
JFS

1
প্রয়োজন নেই যখন ssh কী যুক্ত করা ভাল সমাধান নয়। উদাহরণস্বরূপ, আপনার যদি ওয়ান টাইম যোগাযোগের প্রয়োজন হয় তবে সুরক্ষা কারণে আপনি ssh কী সেট আপ করবেন না।
ওরেজভানি

150

পাইথনে এটি করার জন্য (যেমন সাবপ্রসেসের মাধ্যমে scp মোড়ানো নয়। পোপেন বা অনুরূপ) প্যারামিকো লাইব্রেরির সাথে আপনি এই জাতীয় কিছু করতে পারেন:

import os
import paramiko

ssh = paramiko.SSHClient() 
ssh.load_host_keys(os.path.expanduser(os.path.join("~", ".ssh", "known_hosts")))
ssh.connect(server, username=username, password=password)
sftp = ssh.open_sftp()
sftp.put(localpath, remotepath)
sftp.close()
ssh.close()

(আপনি সম্ভবত অজানা হোস্ট, ত্রুটিগুলি, যে কোনও ডিরেক্টরি তৈরি করতে প্রয়োজনীয় প্রয়োজনীয়তাগুলি সমাধান করতে চান))


14
প্যারামিকোতে একটি দুর্দান্ত sftp.put (স্ব, লোকালপথ, রিমোটপ্যাথ, কলব্যাক = কিছুই নয়) রয়েছে যা আপনাকে লিখতে হবে না এবং প্রতিটি ফাইল বন্ধ করতে হবে না।
জিম ক্যারল 13

6
আমি লক্ষ করব যে এসএফটিপি এসসিপির মতো জিনিস নয়।
দ্রহকার

4
@ দ্রহকার প্রশ্নটি ফাইলটি এসএসএইচে পাঠানোর জন্য বলেছে। এটিই তাই করে।
টনি মায়ার

8
দ্রষ্টব্য: ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())তাত্ক্ষণিকতার পরে এই কাজটি বাক্স থেকে আউট করার জন্য ssh
ডোদা

1
বলছি, সার্ভারের পাসওয়ার্ড ব্যবহার করা কি নিরাপদ? প্রাইভেট কী ব্যবহার করার কোন সম্ভাবনা আছে?
আয়সেননৌসি

32

আপনি সম্ভবত সাবপ্রসেস মডিউলটি ব্যবহার করবেন । এটার মতো কিছু:

import subprocess
p = subprocess.Popen(["scp", myfile, destination])
sts = os.waitpid(p.pid, 0)

destinationসম্ভবত ফর্ম যেখানে user@remotehost:remotepath। আমার প্রকৃত উত্তরের দুর্বলতাটি চিহ্নিত করার জন্য @ চারেলস ডাফিকে ধন্যবাদ জানাই, যেটি স্কিপ ক্রিয়াকলাপ নির্দিষ্ট করার জন্য একক স্ট্রিং যুক্তি ব্যবহার করেছিল shell=True- যে পথগুলিতে হোয়াইটস্পেস পরিচালনা করবে না।

মডিউল ডকুমেন্টেশনের ত্রুটি যাচাইয়ের উদাহরণ রয়েছে যা আপনি এই ক্রিয়াকলাপের সাথে মিলিয়ে সম্পাদন করতে চাইতে পারেন।

নিশ্চিত হয়ে নিন যে আপনি যথাযথ শংসাপত্রগুলি সেট আপ করেছেন যাতে আপনি মেশিনগুলির মধ্যে একটি অবরুদ্ধ, পাসওয়ার্ডহীন স্ক্র্যাপ সম্পাদন করতে পারেন । ইতিমধ্যে এটির জন্য একটি স্ট্যাকওভারফ্লো প্রশ্ন রয়েছে


3
সাবপ্রসেস.পোপেন ব্যবহার করা সঠিক জিনিস Right অ্যারের পরিবর্তে এটিকে একটি স্ট্রিং পাস করা (এবং শেল = ট্রু ব্যবহার করে) ভুল জিনিস, কারণ এর অর্থ স্পেস সহ ফাইলের নামগুলি সঠিকভাবে কাজ করে না।
চার্লস ডাফি 12

2
"sts = os.waitpid (p.pid, 0)" এর পরিবর্তে আমরা "sts = p.wait ()" ব্যবহার করতে পারি।
db42

এই প্রোটোকলের জন্য ডাইরেক্ট পাইথন এপিআই সহ এটির কার্যকর করার কোনও উপায় নেই?
lpapp

1
subprocess.check_call(['scp', myfile, destination])এর পরিবর্তে পাইথন 2.5 (2006) ব্যবহার করা যেতে পারে
jfs

@ জেএফএসবেস্টিয়ান: হ্যাঁ, ডিসেম্বরে আমি এটি পরীক্ষা করে দেখেছি। আমার upvotes প্রমাণ করে যে, অন্তত। :) যদিও অনুসরণ করার জন্য ধন্যবাদ।
lpapp

12

সমস্যাটি দেখার জন্য কয়েকটি উপায় রয়েছে:

  1. কমান্ড-লাইন প্রোগ্রাম মোড়ানো
  2. পাইথন লাইব্রেরি ব্যবহার করুন যা এসএসএইচ ক্ষমতা সরবরাহ করে (যেমন - প্যারামিকো বা বাঁকানো শঙ্খ )

প্রতিটি পদ্ধতির নিজস্ব কীর্তি রয়েছে। আপনি "ssh", "scp" বা "rsync" এর মতো সিস্টেম কমান্ড মোড়ানো থাকলে পাসওয়ার্ড-কম লগইন সক্ষম করতে আপনাকে এসএসএইচ কীগুলি সেটআপ করতে হবে। আপনি প্যারামিকো বা অন্য কোনও লাইব্রেরি ব্যবহার করে কোনও স্ক্রিপ্টে একটি পাসওয়ার্ড এম্বেড করতে পারেন তবে ডকুমেন্টেশনের অভাব হতাশ হতে পারে, বিশেষত আপনি যদি এসএসএইচ সংযোগের বেসিকগুলির সাথে পরিচিত না হন (যেমন - কী এক্সচেঞ্জ, এজেন্টস ইত্যাদি)। এটি সম্ভবত বলা ছাড়াই যায় যে এসএসএইচ কীগুলি প্রায়শই এই ধরণের স্টাফের পাসওয়ার্ডের চেয়ে ভাল ধারণা।

দ্রষ্টব্য: আপনি যদি এসএসএইচের মাধ্যমে ফাইল স্থানান্তর করার পরিকল্পনা করেন তবে বিশেষত বিকল্পটি যদি পুরানো স্ক্রিপ হয় তবে আরএসসিএনকে পরাস্ত করা শক্ত।

আমি সিস্টেম কলগুলি প্রতিস্থাপনের দিকে নজর দিয়ে প্যারামিকো ব্যবহার করেছি তবে ব্যবহারের সহজলভ্যতা এবং তাত্ক্ষণিক পরিচয়ের কারণে আমি নিজেকে মোড়ানো কমান্ডগুলিতে ফিরে পেয়েছি। আপনি অন্য হতে পারে। আমি কিছুক্ষণ আগে শঙ্খকে একবারে ওভার দিয়েছিলাম তবে এটি আমার কাছে আবেদন করে না।

যদি সিস্টেম-কলের পথটি বেছে নেওয়া হয়, পাইথন ওএস.সিস্টেম বা কমান্ড / সাবপ্রসেস মডিউলগুলির মতো বিকল্পগুলির একটি অ্যারে সরবরাহ করে। সংস্করণ ২.৪+ ব্যবহার করে আমি সাবপ্রসেস মডিউলটি নিয়ে যাব।


1
কৌতূহলী: আরএসএনসি বনাম স্কিপিতে গল্পটি কী?
অলোক

7

একই সমস্যা পৌঁছেছে, তবে "হ্যাকিং" বা কমান্ড লাইন অনুকরণের পরিবর্তে:

এই উত্তরটি এখানে পেয়েছি ।

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')

1
দ্রষ্টব্য - এটি স্ক্যাপ প্যাকেজ উপর নির্ভর করে। ডিসেম্বর 2017 পর্যন্ত, সেই প্যাকেজের সর্বশেষ আপডেটটি ছিল 2015 এবং সংস্করণ সংখ্যাটি 0.1.x। নিশ্চিত না যে আমি এই নির্ভরতা যুক্ত করতে চাই।
চক

2
সুতরাং, এটি এখনই 2018 এবং মে মাসে তারা সংস্করণ 0.11.0 প্রকাশ করেছে। তো, দেখে মনে হচ্ছে এসসিপি ক্লায়েন্টের মৃত্যুর পরেও কি সব হয় নি?
অ্যাড্রিয়ানো_পিনাফো

5

হোস্ট কী পরীক্ষার পাশাপাশি পরিচালনা করতে আপনি এর মতো কিছু করতে পারেন

import os
os.system("sshpass -p password scp -o StrictHostKeyChecking=no local_file_path username@hostname:remote_path")

4

fabric ssh ফাইল আপলোড করতে ব্যবহৃত হতে পারে:

#!/usr/bin/env python
from fabric.api import execute, put
from fabric.network import disconnect_all

if __name__=="__main__":
    import sys
    # specify hostname to connect to and the remote/local paths
    srcdir, remote_dirname, hostname = sys.argv[1:]
    try:
        s = execute(put, srcdir, remote_dirname, host=hostname)
        print(repr(s))
    finally:
        disconnect_all()

2

আপনি ভ্যাসাল প্যাকেজটি ব্যবহার করতে পারেন, এটি ঠিক এটির জন্য ডিজাইন করা হয়েছে।

আপনার যা দরকার তা হ'ল ভ্যাসাল ইনস্টল করা এবং করা

from vassal.terminal import Terminal
shell = Terminal(["scp username@host:/home/foo.txt foo_local.txt"])
shell.run()

এছাড়াও, এটি আপনাকে প্রমাণীকরণের শংসাপত্রগুলি সংরক্ষণ করবে এবং এগুলি বারবার টাইপ করার দরকার নেই।


1

আমি ssh এর মাধ্যমে রিমোট ডিরেক্টরিটি মাউন্ট করতে sshfs ব্যবহার করেছি , এবং ফাইলগুলি অনুলিপি করতে shutil :

$ mkdir ~/sshmount
$ sshfs user@remotehost:/path/to/remote/dst ~/sshmount

তারপরে অজগরে:

import shutil
shutil.copy('a.txt', '~/sshmount')

এই পদ্ধতিটির সুবিধা রয়েছে যে আপনি যদি স্থানীয়ভাবে ক্যাশে এবং একক বড় ফাইল প্রেরণ না করে ডেটা তৈরি করে থাকেন তবে আপনি ডেটা স্ট্রিম করতে পারবেন।


1

আপনি যদি এসএসএল শংসাপত্র ব্যবহার করতে না চান তবে এটি ব্যবহার করুন:

import subprocess

try:
    # Set scp and ssh data.
    connUser = 'john'
    connHost = 'my.host.com'
    connPath = '/home/john/'
    connPrivateKey = '/home/user/myKey.pem'

    # Use scp to send file from local to host.
    scp = subprocess.Popen(['scp', '-i', connPrivateKey, 'myFile.txt', '{}@{}:{}'.format(connUser, connHost, connPath)])

except CalledProcessError:
    print('ERROR: Connection to host failed!')

1

বাহ্যিক সংস্থান প্যারামিকো ব্যবহার করে;

    from paramiko import SSHClient
    from scp import SCPClient
    import os

    ssh = SSHClient() 
    ssh.load_host_keys(os.path.expanduser(os.path.join("~", ".ssh", "known_hosts")))
    ssh.connect(server, username='username', password='password')
    with SCPClient(ssh.get_transport()) as scp:
            scp.put('test.txt', 'test2.txt')

0

scpসাবপ্রসেসের মাধ্যমে কমান্ড কল করা স্ক্রিপ্টের ভিতরে অগ্রগতি প্রতিবেদনটি গ্রহণ করার অনুমতি দেয় না। pexpectতথ্যটি নিষ্কাশন করতে ব্যবহার করা যেতে পারে:

import pipes
import re
import pexpect # $ pip install pexpect

def progress(locals):
    # extract percents
    print(int(re.search(br'(\d+)%$', locals['child'].after).group(1)))

command = "scp %s %s" % tuple(map(pipes.quote, [srcfile, destination]))
pexpect.run(command, events={r'\d+%': progress})

স্থানীয় নেটওয়ার্কে পাইথন কপি ফাইলটি দেখুন (লিনাক্স -> লিনাক্স)


0

একটি খুব সাধারণ পদ্ধতির নিম্নলিখিত:

import os
os.system('sshpass -p "password" scp user@host:/path/to/file ./')

কোনও পাইথন লাইব্রেরির প্রয়োজন নেই (কেবল ওএস), এবং এটি কাজ করে, তবে এই পদ্ধতিটি ব্যবহার করে ইনস্টল করার জন্য অন্য ssh ক্লায়েন্টের উপর নির্ভর করে। এটি অন্য সিস্টেমে চালিত হলে অনাকাঙ্ক্ষিত আচরণের ফলাফল হতে পারে।


-3

হ্যাকি জাতীয়, কিন্তু নিম্নলিখিত কাজ করা উচিত :)

import os
filePath = "/foo/bar/baz.py"
serverPath = "/blah/boo/boom.py"
os.system("scp "+filePath+" user@myserver.com:"+serverPath)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.