Remote executing of program via xterm run using paramiko python ssh library
Question: Flow of the program is:

  1. Connect to OpenSSH server on Linux machine using Paramiko library
  2. Open X11 session
  3. Run xterm executable
  4. Run some other program (e.g. Firefox) by typing executable name in the terminal and running it. 

I would be grateful if someone can explain how to cause some executable to run
in a terminal which was open by using the following code and provide sample
source code ([source](http://stackoverflow.com/a/19164039)):

    
    
    import select
    import sys
    import paramiko
    import Xlib.support.connect as xlib_connect
    import os
    import socket
    import subprocess
    
    
    
    # run xming
    XmingProc = subprocess.Popen("C:/Program Files (x86)/Xming/Xming.exe :0 -clipboard -multiwindow")
    ssh_client = paramiko.SSHClient()
    ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh_client.connect(SSHServerIP, SSHServerPort, username=user, password=pwd)
    transport = ssh_client.get_transport()
    channelOppositeEdges = {}
    
    local_x11_display = xlib_connect.get_display(os.environ['DISPLAY'])
    inputSockets = []
    
    def x11_handler(channel, (src_addr, src_port)):
        local_x11_socket = xlib_connect.get_socket(*local_x11_display[:3])
        inputSockets.append(local_x11_socket)
        inputSockets.append(channel)
        channelOppositeEdges[local_x11_socket.fileno()] = channel
        channelOppositeEdges[channel.fileno()] = local_x11_socket
        transport._queue_incoming_channel(channel)
    
    session = transport.open_session()
    inputSockets.append(session)
    session.request_x11(handler = x11_handler)
    session.exec_command('xterm')
    transport.accept()
    
    while not session.exit_status_ready():
        readable, writable, exceptional = select.select(inputSockets,[],[])
        if len(transport.server_accepts) > 0:
            transport.accept()
        for sock in readable:
            if sock is session:
                while session.recv_ready():
                    sys.stdout.write(session.recv(4096))
                while session.recv_stderr_ready():
                    sys.stderr.write(session.recv_stderr(4096))   
            else: 
                try:
                    data = sock.recv(4096)
                    counterPartSocket  = channelOppositeEdges[sock.fileno()]
                    counterPartSocket.sendall(data)
                except socket.error:
                    inputSockets.remove(sock)
                    inputSockets.remove(counterPartSocket)
                    del channelOppositeEdges[sock.fileno()]
                    del channelOppositeEdges[counterPartSocket.fileno()]
                    sock.close()
                    counterPartSocket.close()
    
    print 'Exit status:', session.recv_exit_status()
    while session.recv_ready():
        sys.stdout.write(session.recv(4096))
    while session.recv_stderr_ready():
        sys.stdout.write(session.recv_stderr(4096))
    session.close()
    XmingProc.terminate()
    XmingProc.wait()
    

I was thinking about running the program in child thread, while the thread
running the xterm is waiting for the child to terminate.


Answer: Well, this is a bit of a hack, but hey.

What you can do on the remote end is the following: Inside the xterm, you run
`netcat`, listen to any data coming in on some port, and pipe whatever you get
into `bash`. It's not quite the same as typing it into xterm direclty, but
it's almost as good as typing it into bash directly, so I hope it'll get you a
bit closer to your goal. If you really want to interact with xterm directly,
you might want to [read
this](http://books.google.co.uk/books?id=t8C4pEDQ8s0C&lpg=PA294&ots=n6IT4dU7Po&dq=expect%20xterm&pg=PA293#v=onepage&q=expect%20xterm&f=false).

For example:

terminal 1:

    
    
    % nc -l 3333 | bash
    

terminal 2 (type `echo hi` here):

    
    
    % nc localhost 3333
    echo hi
    

Now you should see `hi` pop out of the first terminal. Now try it with
`xterm&`. It worked for me.

Here's how you can automate this in Python. You may want to add some code that
enables the server to tell the client when it's ready, rather than using the
silly `time.sleep`s.

    
    
    import select
    import sys
    import paramiko
    import Xlib.support.connect as xlib_connect
    import os
    import socket
    import subprocess
    
    # for connecting to netcat running remotely
    from multiprocessing import Process
    import time
    
    # data
    import getpass
    SSHServerPort=22
    SSHServerIP = "localhost"
    # get username/password interactively, or use some other method..
    user = getpass.getuser()
    pwd = getpass.getpass("enter pw for '" + user + "': ")
    NETCAT_PORT = 3333
    FIREFOX_CMD="/path/to/firefox &"
    #FIREFOX_CMD="xclock&"#or this :)
    
    def run_stuff_in_xterm():
        time.sleep(5)
        s = socket.socket(socket.AF_INET6 if ":" in SSHServerIP else socket.AF_INET, socket.SOCK_STREAM)
        s.connect((SSHServerIP, NETCAT_PORT))
        s.send("echo \"Hello there! Are you watching?\"\n")
        s.send(FIREFOX_CMD + "\n")
        time.sleep(30)
        s.send("echo bye bye\n")
        time.sleep(2)
        s.close()
    
    # run xming
    XmingProc = subprocess.Popen("C:/Program Files (x86)/Xming/Xming.exe :0 -clipboard -multiwindow")
    ssh_client = paramiko.SSHClient()
    ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh_client.connect(SSHServerIP, SSHServerPort, username=user, password=pwd)
    transport = ssh_client.get_transport()
    channelOppositeEdges = {}
    
    local_x11_display = xlib_connect.get_display(os.environ['DISPLAY'])
    inputSockets = []
    
    def x11_handler(channel, (src_addr, src_port)):
        local_x11_socket = xlib_connect.get_socket(*local_x11_display[:3])
        inputSockets.append(local_x11_socket)
        inputSockets.append(channel)
        channelOppositeEdges[local_x11_socket.fileno()] = channel
        channelOppositeEdges[channel.fileno()] = local_x11_socket
        transport._queue_incoming_channel(channel)
    
    session = transport.open_session()
    inputSockets.append(session)
    session.request_x11(handler = x11_handler)
    session.exec_command("xterm -e \"nc -l 0.0.0.0 %d | /bin/bash\"" % NETCAT_PORT)
    p = Process(target=run_stuff_in_xterm)
    transport.accept()
    p.start()
    
    while not session.exit_status_ready():
        readable, writable, exceptional = select.select(inputSockets,[],[])
        if len(transport.server_accepts) > 0:
            transport.accept()
        for sock in readable:
            if sock is session:
                while session.recv_ready():
                    sys.stdout.write(session.recv(4096))
                while session.recv_stderr_ready():
                    sys.stderr.write(session.recv_stderr(4096))   
            else: 
                try:
                    data = sock.recv(4096)
                    counterPartSocket  = channelOppositeEdges[sock.fileno()]
                    counterPartSocket.sendall(data)
                except socket.error:
                    inputSockets.remove(sock)
                    inputSockets.remove(counterPartSocket)
                    del channelOppositeEdges[sock.fileno()]
                    del channelOppositeEdges[counterPartSocket.fileno()]
                    sock.close()
                    counterPartSocket.close()
    
    p.join()
    print 'Exit status:', session.recv_exit_status()
    while session.recv_ready():
        sys.stdout.write(session.recv(4096))
    while session.recv_stderr_ready():
        sys.stdout.write(session.recv_stderr(4096))
    session.close()
    XmingProc.terminate()
    XmingProc.wait()
    

I tested this on a Mac, so I commented out the `XmingProc` bits and used
`/Applications/Firefox.app/Contents/MacOS/firefox` as `FIREFOX_CMD` (and
`xclock`).

The above isn't exactly a secure setup, as anyone connecting to the port at
the right time could run arbitrary code on your remote server, but it sounds
like you're planning to use this for testing purposes anyway. If you want to
improve the security, you could make netcat bind to `127.0.0.1` rather than
`0.0.0.0`, setup an ssh tunnel (run `ssh -L3333:localhost:3333
username@remote-host.com` to tunnel all traffic received locally on port 3333
to remote-host.com:3333), and let Python connect to `("localhost", 3333)`.

Now you can combine this with [selenium](http://docs.seleniumhq.org/) for
browser automation:

Follow the instructions from [this
page](https://pypi.python.org/pypi/selenium), i.e. download the selenium
standalone server jar file, put it into `/path/to/some/place` (on the server),
and `pip install -U selenium` (again, on the server).

Next, put the following code into `selenium-example.py` in
`/path/to/some/place`:

    
    
    #!/usr/bin/env python
    from selenium import webdriver
    from selenium.common.exceptions import NoSuchElementException
    from selenium.webdriver.common.keys import Keys
    import time
    
    browser = webdriver.Firefox() # Get local session of firefox
    browser.get("http://www.yahoo.com") # Load page
    assert "Yahoo" in browser.title
    elem = browser.find_element_by_name("p") # Find the query box
    elem.send_keys("seleniumhq" + Keys.RETURN)
    time.sleep(0.2) # Let the page load, will be added to the API
    try:
        browser.find_element_by_xpath("//a[contains(@href,'http://docs.seleniumhq.org')]")
    except NoSuchElementException:
        assert 0, "can't find seleniumhq"
    browser.close()
    

and change the firefox command:

    
    
    FIREFOX_CMD="cd /path/to/some/place && python selenium-example.py"
    

And watch firefox do a Yahoo search. You might also want to increase the
`time.sleep`.

If you want to run more programs, you can do things like this before or after
running firefox:

    
    
    # start up xclock, wait for some time to pass, kill it.
    s.send("xclock&\n")
    time.sleep(1)
    s.send("XCLOCK_PID=$!\n")  # stash away the process id (into a bash variable)
    time.sleep(30)
    s.send("echo \"killing $XCLOCK_PID\"\n")
    s.send("kill $XCLOCK_PID\n\n")
    time.sleep(5)
    

If you want to do perform general X11 application control, I think you might
need to write similar "driver applications", albeit using different libraries.
You might want search for "x11 send {mouse|keyboard} events" to find more
general approaches. That brings up
[these](http://stackoverflow.com/q/6447704/1298153)
[questions](http://stackoverflow.com/q/4402216/1298153), but I'm sure there's
lots more.

If the remote end isn't responding instantaneously, you might want to sniff
your network traffic in Wireshark, and check whether or not TCP is batching up
the data, rather than sending it line by line (the `\n` seems to help here,
but I guess there's no guarantee). If this is the case, you might be [out of
luck](http://stackoverflow.com/q/10511672/1298153), but [nothing is
impossible](http://stackoverflow.com/q/13517246/1298153). I hope you don't
need to go that far though ;-)

One more note: if you need to communicate with CLI programs' STDIN/STDOUT, you
might want to look at expect scripting (e.g. using
[pexpect](http://www.noah.org/wiki/pexpect), or for simple cases you might be
able to use
subprocess.Popen.communicate](<http://docs.python.org/2/library/subprocess.html#subprocess.Popen.communicate>)).

