Skip to content

Commit a269358

Browse files
author
Olivier Roques
committed
Update README.md
1 parent 6c5316d commit a269358

File tree

2 files changed

+144
-4
lines changed

2 files changed

+144
-4
lines changed

README.md

Lines changed: 139 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,145 @@ pip3 install --user sshcontroller-oroques
1313
Note that the package has been exclusively tested on Python 3+.
1414

1515
## Usage
16-
Incoming
16+
17+
The code snippets can also be found at [demo.py](./examples/demo.py).
18+
19+
#### 1. Create a new SSH controller from a SSH key
20+
```python
21+
import sshcontroller
22+
23+
HOST_IP = "93.184.216.34" # an IPv4 or IPv6 address
24+
KEY_PWD = "password"
25+
26+
ssh_controller = sshcontroller.SSHController(
27+
host=HOST_IP,
28+
user="olivier",
29+
key_path="~/.ssh/id_rsa", # if omitted, look in agent and in ~/.ssh
30+
key_password=KEY_PWD, # optional
31+
key_type="rsa", # rsa (default), dsa, ecdsa or ed25519
32+
port=22, # 22 is the default
33+
)
34+
```
35+
36+
#### 2. Connect to remote host
37+
```python
38+
ssh_controller.connect()
39+
```
40+
41+
#### 3. Run a command
42+
```python
43+
return_code, output = ssh_controller.run(
44+
command="echo 'Hello world!' > /tmp/hello.txt",
45+
display=True, # display output, false by default
46+
combine_stderr=False, # combine stderr and stdout, false by default
47+
capture_output=True, # return output, false by default
48+
timeout=10, # command timeout in seconds, 600s by default
49+
)
50+
logging.info(f"return code: {return_code}, output: {output}")
51+
```
52+
53+
#### 4. Transfer data with SFTP
54+
All functions from paramiko's `SFTPClient` are available through the
55+
`SSHController` object. Check
56+
[paramiko's documentation](http://docs.paramiko.org/en/stable/api/sftp.html#paramiko.sftp_client.SFTPClient)
57+
for a complete list.
58+
59+
In addition, the package adds new methods:
60+
* `exists(path)`: check that a file or a directory exists on the remote host
61+
* `list_dirs(path)`: return the list of directories present in `path`
62+
* `list_dirs(path)`: return the list of files present in `path`
63+
64+
```python
65+
print(f"hello.txt exists: {ssh_controller.exists('/tmp/hello.txt')}")
66+
print(f"bonjour.txt exists: {ssh_controller.exists('/tmp/bonjour.txt')}")
67+
68+
ssh_controller.get("/tmp/hello.txt", "/tmp/bonjour.txt")
69+
70+
with open("/tmp/bonjour.txt", 'r') as bonjour:
71+
for line in bonjour:
72+
print(line, end='')
73+
```
74+
75+
#### 5. Disconnect
76+
```python
77+
ssh_controller.disconnect()
78+
```
79+
80+
#### 6. Use SSH password instead
81+
```python
82+
import sshcontroller
83+
84+
HOST_IP = "93.184.216.34" # an IPv4 or IPv6 address
85+
SSH_PWD = ""
86+
87+
ssh_controller = sshcontroller.SSHController(
88+
host=HOST_IP,
89+
user="root",
90+
ssh_password=SSH_PWD
91+
)
92+
ssh_controller.connect()
93+
```
94+
95+
#### 7. Run a command until an event is set
96+
If the argument `stop_event` is set when calling `run()`, the controller waits
97+
for the given event to be triggered before stopping. This is especially useful
98+
when using threads.
99+
100+
The example below starts two threads with an event attached to each one:
101+
one is pinging localhost, the other sleeps for 10s. When the sleeping threads
102+
has finished, we trigger the events to also stop the pinging thread.
103+
104+
```python
105+
import logging
106+
import queue
107+
import sshcontroller
108+
import threading
109+
import time
110+
111+
output = queue.Queue() # a queue to store the ping command output
112+
stop_event_sleep = threading.Event()
113+
stop_event_ping = threading.Event()
114+
115+
kwargs_sleep = {
116+
"command": "echo 'thread sleep: sleeping for 10s' && sleep 10s",
117+
"display": True,
118+
"stop_event": stop_event_sleep,
119+
}
120+
kwargs_ping = {
121+
"command": "echo 'thread ping: starting ping' && ping localhost",
122+
"display": True,
123+
"capture_output": True,
124+
"stop_event": stop_event_ping,
125+
}
126+
127+
# call run() and store the command output in the queue
128+
def wrapper(kwargs):
129+
return output.put(ssh_controller.run(**kwargs))
130+
131+
thread_sleep = threading.Thread(
132+
target=ssh_controller.run, name="thread_sleep", kwargs=kwargs_sleep)
133+
thread_ping = threading.Thread(
134+
target=wrapper, name="thread_ping", args=(kwargs_ping, ))
135+
136+
thread_ping.start()
137+
thread_sleep.start()
138+
139+
try:
140+
thread_sleep.join()
141+
except KeyboardInterrupt:
142+
logging.info("KeyboardInterrupt")
143+
finally:
144+
logging.info("Stopping threads")
145+
stop_event_sleep.set()
146+
stop_event_ping.set()
147+
time.sleep(2)
148+
149+
return_code, ping_output = output.get()
150+
logging.info(f"thread ping return code: {return_code}")
151+
logging.info(f"thread ping output length: {len(ping_output)}")
152+
153+
ssh_controller.disconnect()
154+
```
17155

18156
## License
19157
[GNU Lesser General Public License v2.1](LICENSE)

examples/demo.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,12 @@ def demo_pwd():
5151
user="root",
5252
ssh_password=SSH_PWD
5353
)
54-
output = queue.Queue()
54+
ssh_controller.connect()
55+
56+
output = queue.Queue() # a queue to store the ping command output
5557
stop_event_sleep = threading.Event()
5658
stop_event_ping = threading.Event()
59+
5760
kwargs_sleep = {
5861
"command": "echo 'thread sleep: sleeping for 10s' && sleep 10s",
5962
"display": True,
@@ -66,11 +69,10 @@ def demo_pwd():
6669
"stop_event": stop_event_ping,
6770
}
6871

72+
# call run() and store the command output in the queue
6973
def wrapper(kwargs):
7074
return output.put(ssh_controller.run(**kwargs))
7175

72-
ssh_controller.connect()
73-
7476
thread_sleep = threading.Thread(
7577
target=ssh_controller.run, name="thread_sleep", kwargs=kwargs_sleep)
7678
thread_ping = threading.Thread(

0 commit comments

Comments
 (0)