x11 forwarding with paramiko

前端 未结 5 1183
抹茶落季
抹茶落季 2020-12-30 03:15

I\'m trying to run a command with paramiko that should be able to open an X window. The script I\'m using would something as follows:

import par         


        
5条回答
  •  长发绾君心
    2020-12-30 03:47

    Given that you asked for a minimal version, which I understand as make it as easy to to use as possible. Here is a version based in both codes, but this separate the x11 session commands from the general code, making the main program simple and the session code reusable:

    import paramiko
    import os
    import select
    import sys
    import Xlib.support.connect as xlib_connect
    
    def run(transport, session, command):
        def x11_handler(channel, (src_addr, src_port)):
            x11_fileno = channel.fileno()
            local_x11_channel = xlib_connect.get_socket(*local_x11_display[:3])
            local_x11_fileno = local_x11_channel.fileno()
    
            # Register both x11 and local_x11 channels
            channels[x11_fileno] = channel, local_x11_channel
            channels[local_x11_fileno] = local_x11_channel, channel
    
            poller.register(x11_fileno, select.POLLIN)
            poller.register(local_x11_fileno, select.POLLIN)
    
            transport._queue_incoming_channel(channel)
    
        def flush_out(channel):
            while channel.recv_ready():
                sys.stdout.write(channel.recv(4096))
            while channel.recv_stderr_ready():
                sys.stderr.write(channel.recv_stderr(4096))
    
        local_x11_display = xlib_connect.get_display(os.environ['DISPLAY'])
    
        channels = {}
        poller = select.poll()
        session_fileno = session.fileno()
        poller.register(session_fileno)
    
        session.request_x11(handler=x11_handler)
        session.exec_command(command)
        transport.accept()
    
        # event loop
        while not session.exit_status_ready():
            poll = poller.poll()
            if not poll: # this should not happen, as we don't have a timeout.
                break
            for fd, event in poll:
                if fd == session_fileno:
                    flush_out(session)
                # data either on local/remote x11 channels/sockets
                if fd in channels.keys():
                    sender, receiver = channels[fd]
                    try:
                        receiver.sendall(sender.recv(4096))
                    except:
                        sender.close()
                        receiver.close()
                        channels.remove(fd)
    
        flush_out(session)
        return session.recv_exit_status()
    
    if __name__ == '__main__':
        ssh_client = paramiko.SSHClient()
        ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh_client.connect('192.168.122.55', username='user', password='password')
        transport = ssh_client.get_transport()
        session = transport.open_session()
        run(transport, session, 'xterm')
    

    I know you could do it by yourself. However, but just by copying the function run anybody could use it without hassle.

    The right answer is https://stackoverflow.com/a/12903844/278878. This example is to make it easier for newcomers.

提交回复
热议问题