Python 3 remote Linux server executes commands and uploads and downloads files

1, Introduction

Paramiko is based on SSH to connect to the remote server and perform relevant operations (SSHClient and SFTPClinet, i.e. remote connection, upload and download service). The module can be used to command or operate files on the remote server. It is worth mentioning that the internal remote management of fabric and ansible is realized by paramiko.

2, Use

1. Download

pip3 install paramiko

2. Module use

SSHClient:

There are two types of remote connection: (1) connection based on user name and password (2) connection based on public key and secret key

Through the use of paramiko remote operation, the essence is also divided into two kinds: (1) only use SSHClient (2) create a transport by yourself

(1) Connection based on user name and password

import paramiko

# establish SSH object
ssh = paramiko.SSHClient()
# Allow connection not in know_hosts Hosts in files
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# Connect to server
ssh.connect(hostname='c1.salt.com', port=22, username='GSuser', password='123')
# Execute command
stdin, stdout, stderr = ssh.exec_command('ls')
# Get command results
result = stdout.read()
# Close connection
ssh.close()

SSHClient encapsulates Transport

import paramiko

transport = paramiko.Transport(('hostname', 22))
transport.connect(username='GSuser', password='123')

ssh = paramiko.SSHClient()
ssh._transport = transport

stdin, stdout, stderr = ssh.exec_command('df')
print(stdout.read())

transport.close()

(2) Connection based on public key and secret key

import paramiko

# Add public key file
private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
# establish SSH object
ssh = paramiko.SSHClient()
# Allow connection not in know_hosts Hosts in files
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# Connect to server
ssh.connect(hostname='192.168.1.105', port=22, username='666', key=private_key)
# Execute command
# When executing multiple commands, you need to use the';'Separate, and finally get_pty Set to True;If it is a single command, just pass in the command
stdin, stdout, stderr = ssh.exec_command('cd dw/2020-06-02/;ls',get_pty=True)
# Multiple commands will return the execution results together, so it is recommended to traverse the printing. You can also print directly: print(stdout.read().decode('utf-8'))
files = stdout.readlines()
for i in files:
    # Print execution feedback results
    print(i.encode().decode('utf-8').split()[0])
# Print error message
print(stderr.read().decode('utf-8'))
# Close connection
ssh.close()

SSHClient encapsulates Transport

import paramiko

private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
transport = paramiko.Transport(('192.168.1.105', 22))
transport.connect(username='666', pkey=private_key)
ssh = paramiko.SSHClient()
ssh._transport = transport
# When executing multiple commands, you need to use the';'Separate, and finally get_pty Set to True;If it is a single command, just pass in the command
stdin, stdout, stderr = ssh.exec_command('cd dw/2020-06-02/;ls',get_pty=True)
# Multiple commands will return the execution results together, so it is recommended to traverse the printing. You can also print directly: print(stdout.read().decode('utf-8'))
files = stdout.readlines()
for i in files:
    # Print execution feedback results
    print(i.encode().decode('utf-8').split()[0])
# Print error message
print(stderr.read().decode('utf-8'))
transport.close()

SFTPClient:

It is used to connect to the remote server and perform upload and download functions.

(1) Upload and download based on user name and password

import paramiko

transport = paramiko.Transport(('192.168.1.105',22))
transport.connect(username='666',password='123')

sftp = paramiko.SFTPClient.from_transport(transport)
# take location.py Upload to server /tmp/test.py
sftp.put('/tmp/location.py', '/tmp/test.py')
# take remove_path Download to local local_path
sftp.get('remove_path', 'local_path')

transport.close()

(2) Upload and download based on public key

import paramiko

private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')

transport = paramiko.Transport(('192.168.1.105', 22))
transport.connect(username='666', pkey=private_key )

sftp = paramiko.SFTPClient.from_transport(transport)
# take location.py Upload to server /tmp/test.py
sftp.put('/tmp/location.py', '/tmp/test.py')
# take remove_path Download to local local_path
sftp.get('remove_path', 'local_path')

transport.close()

Demo: implement remote command execution and file upload

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import paramiko

class SSHConnection(object):

    def __init__(self, host='192.168.12.68', port=22, username='locojoy',pwd='123321QQ!'):
        self.host = host
        self.port = port
        self.username = username
        self.pwd = pwd
        self.__k = None

    def run(self):
        self.connect()  # Connect to remote server
        self.upload('db.py','/tmp/1.py')  # Local db.py File upload to remote server/tmp/Under directory and renamed 1.py
        self.cmd('df')  # implement df command
        self.close()    # Close connection

    def connect(self):
        transport = paramiko.Transport((self.host, self.port))
        transport.connect(username=self.username, password=self.pwd)
        self.__transport = transport

    def close(self):
        self.__transport.close()

    def upload(self,local_path,target_path):
        sftp = paramiko.SFTPClient.from_transport(self.__transport)
        sftp.put(local_path,target_path)

    def cmd(self, command):
        ssh = paramiko.SSHClient()
        ssh._transport = self.__transport
        # Execute command
        stdin, stdout, stderr = ssh.exec_command(command)
        # Get command results
        result = stdout.read()
        print(result)
        return result

obj = SSHConnection()
obj.run()

Application of paramiko in bastion aircraft

(1) Simple example: connect a host remotely, operation command, linux version, and send the command if the input terminal is carriage return. tab completion is not supported.

import paramiko, sys, os, socket, select, getpass
from paramiko.py3compat import u   # stay python3 This is how it is used in Python2 Comment this line in

# This program depends on the terminal and can only be Liunx Run down, windows In other ways

tran = paramiko.Transport(('192.168.12.68', 22,))
tran.start_client()
tran.auth_password('locojoy', '123321QQ!')

# Open a channel
chan = tran.open_session()
# Get a terminal
chan.get_pty()
# Activator
chan.invoke_shell()

# The original method uses terminals to send and receive messages
# utilize sys.stdin,To act recklessly
# The user inputs the content at the terminal and sends it to the remote server
# The remote server executes the command and returns the result
# Display content of user terminal

while True:
    # Monitor user input and server return data
    # sys.stdin Process user input
    # chan Is a previously created channel for receiving server return information
    # adopt select Monitor terminal (I / O),Once changed, send the data to the server
    # By monitoring socket Handle. If there is any change, the server will send me a message
    readable, writeable, error = select.select([chan, sys.stdin, ],[],[],1)
    # adopt select.select monitor chan(Open channel (status of connection to remote server)), sys.stdin(Input), once changed, write readable
    # When chan When changing, add to readable,Remote server sends content
    if chan in readable:
        try:
            x = u(chan.recv(1024))  # Python3 Use this
            # x = chan.recv(1024)  Python2 Use this
            if len(x) == 0:
                print('\r\n*** EOF\r\n')
                break
            sys.stdout.write(x)   # Write buffer
            sys.stdout.flush()    # Refresh to display the contents of the buffer
        except socket.timeout:
            pass
    # When sys.stdin Put in readable Send the acquired content to the remote server when
    if sys.stdin in readable:
        inp = sys.stdin.readline()
        chan.sendall(inp)

chan.close()
tran.close()

(2) Send records every time you press a key, and support tab auto completion

import paramiko, sys, os, socket, select, getpass, termios, tty
from paramiko.py3compat import u

tran = paramiko.Transport(('10.211.55.4', 22,))
tran.start_client()
tran.auth_password('wupeiqi', '123')
# Open a channel
chan = tran.open_session()
# Get a terminal
chan.get_pty()
# Activator
chan.invoke_shell()

# Get the original tty attribute
oldtty = termios.tcgetattr(sys.stdin)
try:
    # by tty Set new properties
    # Default current tty Device properties:
    #   Enter a line to enter, execute
    #   CTRL+C Process exit, special characters encountered, special handling.
    # This is for the original pattern, not knowing all the special symbols
    # Place special characters on the current terminal, set as this, and send all user input to the remote server
    tty.setraw(sys.stdin.fileno())  # Restore the original state of the terminal and send it every time you press a key
    chan.settimeout(0.0)

    while True:
        # Monitor user input and remote server return data( socket)
        # Block until handle is readable
        r, w, e = select.select([chan, sys.stdin], [], [], 1)
        if chan in r:  # Get the content returned by the service
            try:
                x = u(chan.recv(1024))
                if len(x) == 0:
                    print('\r\n*** EOF\r\n')
                    break
                sys.stdout.write(x)
                sys.stdout.flush()
            except socket.timeout:
                pass
        if sys.stdin in r: # dispatch orders
            x = sys.stdin.read(1) # Read a character
            if len(x) == 0:
                break
            chan.send(x) # Send a character

finally:
    # Reset terminal properties,Restore terminal state
    termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)

chan.close()
tran.close()

Tags: Python ssh sftp socket ansible

Posted on Wed, 03 Jun 2020 07:20:10 -0700 by joe1986