gpt4 book ai didi

python - 使用 paramiko python ssh 库通过 xterm run 远程执行程序

转载 作者:太空狗 更新时间:2023-10-30 01:29:24 25 4
gpt4 key购买 nike

程序流程是:

  1. 使用 Paramiko 库连接到 Linux 机器上的 OpenSSH 服务器
  2. 打开 X11 session
  3. 运行 xterm 可执行文件
  4. 通过在终端中输入可执行文件名称并运行它来运行一些其他程序(例如 Firefox)。

如果有人可以解释如何使某些可执行文件在使用以下代码打开的终端中运行并提供示例源代码 (source),我将不胜感激:

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

我正在考虑在子线程中运行程序,而运行 xterm 的线程正在等待子线程终止。

最佳答案

好吧,这有点 hack,但是嘿。

您可以在远程端执行以下操作:在 xterm 中,您运行 netcat,监听从某个端口传入的任何数据,并将您接收到的任何数据通过管道传输到 bash 。这与直接将其输入 xterm 不太一样,但几乎与直接将其输入 bash 一样好,所以我希望它能让您更接近您的目标。如果你真的想直接与 xterm 交互,你可能需要 read this .

例如:

终端 1:

% nc -l 3333 | bash

终端 2(在此处键入 echo hi):

% nc localhost 3333
echo hi

现在您应该看到 hi 从第一个终端弹出。现在尝试使用 xterm&。它对我有用。

以下是如何在 Python 中自动执行此操作。您可能希望添加一些代码,使服务器能够在准备就绪时通知客户端,而不是使用愚蠢的 time.sleeps。

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

我在 Mac 上测试了这个,所以我注释掉了 XmingProc 位并使用 /Applications/Firefox.app/Contents/MacOS/firefox 作为 FIREFOX_CMD (和 xclock)。

以上并不是完全安全的设置,因为任何在正确时间连接到该端口的人都可以在您的远程服务器上运行任意代码,但听起来您无论如何都打算将其用于测试目的。如果你想提高安全性,你可以让 netcat 绑定(bind)到 127.0.0.1 而不是 0.0.0.0,设置一个 ssh 隧道(运行 ssh -L3333: localhost:3333 username@remote-host.com 将本地在端口 3333 上接收到的所有流量隧道传输到 remote-host.com:3333),并让 Python 连接到 ("localhost", 3333).

现在您可以将其与 selenium 结合使用用于浏览器自动化:

按照 this page 中的说明进行操作,即下载 selenium 独立服务器 jar 文件,将其放入 /path/to/some/place (在服务器上),然后 pip install -U selenium (再次,在服务器上)。

接下来,将以下代码放入/path/to/some/place中的selenium-example.py:

#!/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()

并更改 firefox 命令:

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

然后观看 firefox 进行 Yahoo 搜索。您可能还想增加 time.sleep

如果你想运行更多的程序,你可以在运行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)

如果你想执行一般的 X11 应用程序控制,我认为你可能需要编写类似的“驱动程序应用程序”,尽管使用不同的库。您可能需要搜索“x11 发送 {鼠标|键盘} 事件”以找到更通用的方法。这带来了 these questions ,但我敢肯定还有更多。

如果远程端没有即时响应,您可能需要在 Wireshark 中嗅探您的网络流量,并检查 TCP 是否正在对数据进行批处理,而不是逐行发送(\n 似乎在这里有所帮助,但我想不能保证)。如果是这种情况,您可能是 out of luck , 但是 nothing is impossible .我希望你不需要走那么远;-)

还有一点要注意:如果您需要与 CLI 程序的 STDIN/STDOUT 进行通信,您可能需要查看 expect 脚本(例如使用 pexpect ,或者对于简单的情况,您可以使用 subprocess.Popen.communicate ]( http://docs.python.org/2/library/subprocess.html#subprocess.Popen.communicate )).

关于python - 使用 paramiko python ssh 库通过 xterm run 远程执行程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19207210/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com