halloICKEbins
Anmeldungsdatum: 12. September 2017
Beiträge: 226
|
Abend, ich habe die nachfolgenden Quelltexte und Ziel ist es die SSH-Verbindungen durch mein Modul init_ssh.py zu etablieren. Ich habe versucht mit globalen Variablen zu arbeiten, aber entweder sind diese leer oder main.py kennt sie nicht ... habe heute den ganzen Tag versucht es zum Laufen zu bringen - leider ohne Erfolg ... deshalb hier nochmal der Ursprung! 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 | # init_ssh.py
import os
import sys
import paramiko
def init_connection():
file_key = '/.../.../my.key'
key_file_rsa = '/../../id_rsa'
f_data = open(file_key, 'r')
line = f_data.readlines()
f_data.close()
username = line[0].strip('\n')
password= line[1].strip('\n')
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
privatekeyfile = os.path.expanduser(key_file_rsa)
mykey = paramiko.RSAKey.from_private_key_file(privatekeyfile)
def connect_ssh_password(server):
ssh.connect(server, username = username, pkey = mykey)
def connect_ssh_rsa(server):
ssh.connect(server, username = username, password = password, allow_agent=False, look_for_keys=False)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | # main.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import paramiko
from init_ssh import init_connection, connect_ssh_password, connect_ssh_rsa
init_connection()
connect_ssh_password('1.1.1.1') bzw. connect_ssh_rsa('1.1.1.1')
# ...
ssh.close()
|
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11181
Wohnort: München
|
Du könntest die SSHClient-Instanz z.B. in einer Funktion auf den gewünschten Stand bringen und die dann in der main.py weiterverwenden:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 | # init_ssh.py
import os
import sys
import paramiko
from functools import partial
FILE_KEY = '/.../.../my.key' # replace with a valid path
KEY_FILE_RSA = '/../../id_rsa' # replace with a valid path
def read_authentication():
with open(FILE_KEY, 'r') as f:
username, password, *_ = f.read().splitlines()
return username, password
def prepare_ssh_client():
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.load_system_host_keys()
try:
client.load_system_host_keys(os.path.expanduser(KEY_FILE_RSA))
except IOError as e:
print("Could not read KEY_FILE_RSA:", e, file=sys.stderr)
username, password = read_authentication()
client.connect_with_username_and_password = partial(
client.connect, username=username, password=password, allow_agent=False, look_for_keys=False)
return client
|
Und dann in der main.py:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | #!/usr/bin/env python3
# -*- coding: utf-8 -*-
from init_ssh import prepare_ssh_client
client = prepare_ssh_client()
# key-based authentication
client.connect('1.1.1.1')
# do something with the ssh connection
client.close()
# or using the predefined username and password:
client.connect_with_username_and_password('1.1.1.1')
# do something with the ssh connection
client.close()
|
|
halloICKEbins
(Themenstarter)
Anmeldungsdatum: 12. September 2017
Beiträge: 226
|
Danke schonmal dafür ...habe noch eine kleine Fehlermeldung: paramiko.ssh_exception.AuthenticationException: Authentication failed. Liegt vermutlich daran, dass ich mit einem Key eines anderen Benutzers komme oder !?
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11181
Wohnort: München
|
halloICKEbins schrieb: Danke schonmal dafür ...habe noch eine kleine Fehlermeldung: paramiko.ssh_exception.AuthenticationException: Authentication failed. Liegt vermutlich daran, dass ich mit einem Key eines anderen Benutzers komme oder !?
Ohne Kontext kann ich das nicht sagen. Der Traceback ist doch vermutlich einige Zeilen länger. Ich habe gerade noch gesehen, dass ich im Gegensatz zu deinem Beispielcode den Benutzernamen bei einer Authentifikation mit RSA-Keys nicht übergebe - das lässt sich mit Zeile 24 ff. beheben:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 | # init_ssh.py
import os
import sys
import paramiko
from functools import partial
FILE_KEY = '/.../.../my.key' # replace with a valid path
KEY_FILE_RSA = '/../../id_rsa' # replace with a valid path
def read_authentication():
with open(FILE_KEY, 'r') as f:
username, password, *_ = f.read().splitlines()
return username, password
def prepare_ssh_client():
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.load_system_host_keys()
try:
client.load_system_host_keys(os.path.expanduser(KEY_FILE_RSA))
except IOError as e:
print("Could not read KEY_FILE_RSA:", e, file=sys.stderr)
username, password = read_authentication()
client._connect = client.connect
client.connect = partial(client._connect, username=username)
client.connect_with_username_and_password = partial(
client._connect, username=username, password=password, allow_agent=False, look_for_keys=False)
return client
|
|
halloICKEbins
(Themenstarter)
Anmeldungsdatum: 12. September 2017
Beiträge: 226
|
Wenn ich Zeile 25 ersetze, funktionierts! | #client.connect = partial(client._connect, username=username)
client.connect = partial(client._connect, username=username, pkey = paramiko.RSAKey.from_private_key_file(os.path.expanduser(KEY_FILE_RSA)))
|
Spricht irgendetwas dagegen?
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11181
Wohnort: München
|
Wenn du nur genau den Key aus der Datei haben willst nicht.
|
halloICKEbins
(Themenstarter)
Anmeldungsdatum: 12. September 2017
Beiträge: 226
|
Super ... mal wieder vielen Dank
|
noisefloor
Ehemaliger
Anmeldungsdatum: 6. Juni 2006
Beiträge: 29067
Wohnort: WW
|
Hallo, @halloICKEbins: ist dir denn klar, warum deine Version im Ausgangsthread nicht funktioniert bzw. funktionieren kann, die von seahawk1986 aber schon? IMHO zeigt deine Ausgangsfrage, dass du (noch) ein Verständnisproblem mit dem Scoping von Python hast und auch, wann und wie das return Statement genutzt wird. Gruß, noisefloor
|
halloICKEbins
(Themenstarter)
Anmeldungsdatum: 12. September 2017
Beiträge: 226
|
Ich tappe bei mehreren Sachen noch im Dunkeln und habe da noch echten Nachholbedarf... Wenns auf Arbeit mal ruhiger ist, will ich mich im Zuge eines Codereviews damit auseinandersetzen.
|
noisefloor
Ehemaliger
Anmeldungsdatum: 6. Juni 2006
Beiträge: 29067
Wohnort: WW
|
Hallo, wie gesagt, dass Stichwort heißt "Scoping", also der Gültigkeitsbereich von Variablen und Instanzen von Objekten. Dein Code würde voraussetzten, das bei Python alles im globalen Scope sichtbar ist. Ist es aber nicht, weil Python so nicht funktioniert (einige andere Programmiersprachen auch nicht, das ist nicht Python-spezifisch). Deine Funktion init_connection macht zwar alles, was du programmiert hast. Wenn die Funktion abgearbeitet ist, ist aber alles "weg", weil die Variablen wie username , password , ssh etc. nur im Scope (Gültigkeitsbereich) der Funktion leben, _nicht_ außerhalb. Bei seahawk1986 werden alle relevanten Werte per return zurückgegeben, so dass die Wert weiter genutzt werden können. Einfaches Beispiel dafür: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 | >>> def my_func():
... a = 5
... print('a ist gleich {}'.format(a))
...
>>> my_func()
a ist gleich 5
>>> a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
>>> a = my_func()
a ist gleich 5
>>> a
>>> #a ist hier gleich None, weil my_func keinen definierten Rückgabewert hat, damit ist der Rückgabewert None
>>> def my_other_func():
... a = 5
... print('a ist gleich {}'.format(a))
... return a
...
>>> a = my_other_func()
a ist gleich 5
>>> a
5
>>>
|
Gruß, noisefloor
|
snafu1
Anmeldungsdatum: 5. September 2007
Beiträge: 2123
Wohnort: Gelsenkirchen
|
Das Basiswissen zu Funktionen, Sichtbarkeit von dort definierten Bezeichnern, usw wird übrigens alles im offiziellen Python-Tutorial erklärt. Das gibt es sogar auf deutsch. ☺
|