Skip to content

Commit 6c5316d

Browse files
author
Olivier Roques
committed
Add demo file
1 parent 2fedf0a commit 6c5316d

File tree

2 files changed

+125
-21
lines changed

2 files changed

+125
-21
lines changed

examples/demo.py

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#!/usr/bin/python3
2+
import logging
3+
import queue
4+
import sshcontroller
5+
import threading
6+
import time
7+
8+
logging.basicConfig(format="[%(levelname)s] %(message)s", level=logging.INFO)
9+
10+
HOST_IP = "93.184.216.34" # an IPv4 or IPv6 address
11+
KEY_PWD = ""
12+
SSH_PWD = ""
13+
14+
15+
def demo_key():
16+
ssh_controller = sshcontroller.SSHController(
17+
host=HOST_IP,
18+
user="olivier",
19+
key_path="~/.ssh/id_rsa", # if omitted, look in agent and in ~/.ssh
20+
key_password=KEY_PWD, # optional
21+
key_type="rsa", # rsa (default), dsa, ecdsa or ed25519
22+
port=22, # 22 is the default
23+
)
24+
25+
ssh_controller.connect()
26+
27+
return_code, output = ssh_controller.run(
28+
command="echo 'Hello world!' > /tmp/hello.txt",
29+
display=True, # display output, false by default
30+
combine_stderr=False, # combine stderr and stdout, false by default
31+
capture_output=True, # return output, false by default
32+
timeout=10, # command timeout in seconds, 600s by default
33+
)
34+
logging.info(f"return code: {return_code}, output: {output}")
35+
36+
print(f"hello.txt exists: {ssh_controller.exists('/tmp/hello.txt')}")
37+
print(f"bonjour.txt exists: {ssh_controller.exists('/tmp/bonjour.txt')}")
38+
39+
ssh_controller.get("/tmp/hello.txt", "/tmp/bonjour.txt")
40+
41+
with open("/tmp/bonjour.txt", 'r') as bonjour:
42+
for line in bonjour:
43+
print(line, end='')
44+
45+
ssh_controller.disconnect()
46+
47+
48+
def demo_pwd():
49+
ssh_controller = sshcontroller.SSHController(
50+
host=HOST_IP,
51+
user="root",
52+
ssh_password=SSH_PWD
53+
)
54+
output = queue.Queue()
55+
stop_event_sleep = threading.Event()
56+
stop_event_ping = threading.Event()
57+
kwargs_sleep = {
58+
"command": "echo 'thread sleep: sleeping for 10s' && sleep 10s",
59+
"display": True,
60+
"stop_event": stop_event_sleep,
61+
}
62+
kwargs_ping = {
63+
"command": "echo 'thread ping: starting ping' && ping localhost",
64+
"display": True,
65+
"capture_output": True,
66+
"stop_event": stop_event_ping,
67+
}
68+
69+
def wrapper(kwargs):
70+
return output.put(ssh_controller.run(**kwargs))
71+
72+
ssh_controller.connect()
73+
74+
thread_sleep = threading.Thread(
75+
target=ssh_controller.run, name="thread_sleep", kwargs=kwargs_sleep)
76+
thread_ping = threading.Thread(
77+
target=wrapper, name="thread_ping", args=(kwargs_ping, ))
78+
79+
thread_ping.start()
80+
thread_sleep.start()
81+
82+
try:
83+
thread_sleep.join()
84+
except KeyboardInterrupt:
85+
logging.info("KeyboardInterrupt")
86+
finally:
87+
logging.info("Stopping threads")
88+
stop_event_sleep.set()
89+
stop_event_ping.set()
90+
time.sleep(2)
91+
92+
return_code, ping_output = output.get()
93+
logging.info(f"thread ping return code: {return_code}")
94+
logging.info(f"thread ping output length: {len(ping_output)}")
95+
96+
ssh_controller.disconnect()
97+
98+
99+
demo_key()
100+
demo_pwd()

sshcontroller/sshcontroller.py

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -69,18 +69,22 @@ def __init__(
6969
)
7070
)
7171
elif ssh_password is None:
72+
self.keys = paramiko.Agent().get_keys()
73+
7274
try:
73-
self.keys.append(
74-
_KEY_TYPES[key_type].from_private_key(
75-
open(path.expanduser(f"~/.ssh/id_{key_type}"), 'r'),
76-
key_password
77-
)
75+
key_file = _KEY_TYPES[key_type].from_private_key(
76+
open(path.expanduser(f"~/.ssh/id_{key_type}"), 'r'),
77+
key_password
7878
)
79-
except Exception as e:
80-
agent_keys = paramiko.Agent().get_keys()
81-
if not agent_keys:
82-
raise e
83-
self.keys = agent_keys
79+
except Exception:
80+
pass
81+
else:
82+
self.keys.insert(
83+
len(self.keys) if key_password is None else 0, key_file
84+
)
85+
86+
if not self.keys:
87+
logging.error("No valid key found")
8488

8589
def connect(self):
8690
try:
@@ -123,7 +127,7 @@ def __run_until_event(
123127
capture_output=False,
124128
):
125129
channel = self.transport.open_session()
126-
output = []
130+
output = ""
127131
timeout = 2
128132

129133
channel.settimeout(timeout)
@@ -145,10 +149,10 @@ def __run_until_event(
145149
if not len(raw_data):
146150
break
147151

148-
data = raw_data.decode("utf-8").splitlines()
152+
data = raw_data.decode("utf-8")
149153

150154
if display:
151-
print('\n'.join(data))
155+
print(data, end='')
152156

153157
if capture_output:
154158
output += data
@@ -157,7 +161,7 @@ def __run_until_event(
157161
break
158162

159163
channel.close()
160-
return (channel.exit_status_ready(), output)
164+
return (channel.exit_status_ready(), output.splitlines())
161165

162166
def __run_until_exit(
163167
self,
@@ -168,7 +172,7 @@ def __run_until_exit(
168172
capture_output=False,
169173
):
170174
channel = self.transport.open_session()
171-
output = []
175+
output = ""
172176

173177
channel.settimeout(timeout)
174178
channel.set_combine_stderr(combine_stderr)
@@ -177,31 +181,31 @@ def __run_until_exit(
177181

178182
try:
179183
if not display and not capture_output:
180-
return (channel.recv_exit_status(), output)
184+
return (channel.recv_exit_status(), output.splitlines())
181185
else:
182186
while True:
183187
raw_data = channel.recv(self.nb_bytes)
184188

185189
if not len(raw_data):
186190
break
187191

188-
data = raw_data.decode("utf-8").splitlines()
192+
data = raw_data.decode("utf-8")
189193

190194
if display:
191-
print('\n'.join(data))
195+
print(data, end='')
192196

193197
if capture_output:
194198
output += data
195199
except socket.timeout:
196200
logging.warning(f"Timeout after {timeout}s")
197-
return (1, output)
201+
return (1, output.splitlines())
198202
except KeyboardInterrupt:
199203
logging.info("KeyboardInterrupt")
200-
return (0, output)
204+
return (0, output.splitlines())
201205
finally:
202206
channel.close()
203207

204-
return (channel.recv_exit_status(), output)
208+
return (channel.recv_exit_status(), output.splitlines())
205209

206210
def run(
207211
self,

0 commit comments

Comments
 (0)