문제

다음을 파일에 넣으십시오 안녕하세요 (그리고 easy_install paramiko 당신이 그것을 얻지 못했다면) :

hostname,username,password='fill','these','in'
import paramiko
c = paramiko.SSHClient()
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
c.connect(hostname=hostname, username=username, password=password)
i,o,e = c.exec_command('ls /')
print(o.read())
c.close()

첫 번째 줄을 적절하게 채우십시오.

이제 입력하십시오

python hello.py

그리고 당신은 일부 LS 출력을 볼 수 있습니다.

이제 대신 입력합니다

python

통역사 유형 내에서

import hello

그리고 Voila! 매달려! 함수에서 코드를 랩핑하면 말해야합니다. foo 그리고 그렇게 import hello; hello.foo() 대신에.

모듈 초기화 내에서 사용될 때 Paramiko가 종료되는 이유는 무엇입니까? Paramiko는 처음에 모듈 초기화 중에 사용되고 있음을 어떻게 알고 있습니까?

도움이 되었습니까?

해결책

Paramiko는 기본 전송을 위해 별도의 스레드를 사용합니다. 당신은해야합니다 절대 가져 오기의 부작용으로 스레드를 스폰하는 모듈이 있습니다. 이해할 수 있듯이 단일 가져 오기 잠금 잠금 장치가 있으므로 모듈의 자식 스레드가 다른 가져 오기를 시도 할 때 기본 스레드가 여전히 잠금을 고정하기 때문에 무기한 차단할 수 있습니다. (아마도 내가 알지 못하는 다른 gotchas가있을 것입니다)

일반적으로 모듈은 가져올 때 어떤 종류의 부작용도 없거나 예측할 수없는 결과를 얻을 수 있습니다. 그냥 실행을 막으십시오 __name__ == '__main__' 속임수, 당신은 괜찮을 것입니다.

편집]이 교착 상태를 재현하는 간단한 테스트 케이스를 만들 수 없습니다. 인증 코드가 해고되지 않는 이벤트를 기다리고 있기 때문에 여전히 Import의 스레딩 문제라고 가정합니다. 이것은 Paramiko 또는 Python의 버그 일지 모르지만 좋은 소식은 당신이 일을 올바르게하는 경우 절대 보지 말아야한다는 것입니다.)

이것은 항상 부작용을 최소화하려는 이유와 기능 프로그래밍 기술이 더 널리 퍼지는 이유입니다.

다른 팁

처럼 Jimb 지적했다 가져 오기 문제 Python이 암시 적으로 가져 오려고 할 때 str.decode('utf-8') SSH 연결 시도 중 처음으로 사용시 디코더. 보다 분석 자세한 내용은 섹션입니다.

일반적으로, 모듈이 가져 오기에 새 스레드를 자동으로 스폰하는 것을 피해야 할 정도로 강조 할 수는 없습니다. 가능하다면, 거의 항상 원치 않는 부작용으로 이어 지므로 일반적으로 마법 모듈 코드를 피하십시오.

  1. 이미 언급했듯이 문제에 대한 쉬운 및 제정신 수정은 코드를 if __name__ == '__main__': 이 특정 모듈을 실행하는 경우에만 실행 되고이 MModule이 다른 모듈로 가져 오면 실행되지 않습니다.

  2. (권장되지 않음) 또 다른 수정 사항은 전화하기 전에 코드에서 더미 str.decode ( 'utf-8')를 수행하는 것입니다. SSHClient.connect() - 아래 분석을 참조하십시오.

그렇다면이 문제의 근본 원인은 무엇입니까?

분석 (간단한 비밀번호 인증)

힌트 : 파이썬 가져 오기 및 세트에서 스레딩을 디버그하려는 경우 threading._VERBOSE = True

  1. paramiko.SSHClient().connect(.., look_for_keys=False, ..) 연결을 위해 새로운 스레드를 암시 적으로 스폰합니다. 디버그 출력을 켜면 이것을 볼 수 있습니다. paramiko.transport.

[Thread-5 ] [paramiko.transport ] DEBUG : starting thread (client mode): 0x317f1d0L

  1. 이것은 기본적으로의 일부로 수행됩니다 SSHClient.connect(). 언제 client.py:324::start_client() 호출되면 잠금이 생성됩니다 transport.py:399::event=threading.Event() 그리고 실이 시작되었습니다 transport.py:400::self.start(). 주목하십시오 start() 그런 다음 메소드가 클래스를 실행합니다 transport.py:1565::run() 방법.

  2. transport.py:1580::self._log(..) 로그 메시지 "시작 스레드"를 인쇄 한 다음 transport.py:1584::self._check_banner().

  3. check_banner 한 가지를합니다. SSH 배너를 검색합니다 (서버의 첫 번째 응답) transport.py:1707::self.packetizer.readline(timeout) (타임 아웃은 소켓 읽기 타임 아웃 일뿐입니다), 끝에 라인 피드를 점검하고 그렇지 않으면 시간을 초과합니다.

  4. 서버 배너가 접수 된 경우 UTF-8 응답 문자열을 해독하려고합니다. packet.py:287::return u(buf) 그리고 교착 상태가 일어나는 곳입니다. 그만큼 u(s, encoding='utf-8') str.decode ( 'utf-i')를하고 암시 적으로 가져옵니다. encodings.utf8 안에 encodings:99 ~을 통해 encodings.search_function 수입 교착 상태로 끝납니다.

따라서 더러운 수정은 모듈 가져 오기 측면 효과로 인해 해당 특정 가져 오기를 차단하지 않기 위해 UTF-8 디코더를 한 번만 가져 오는 것입니다. (''.decode('utf-8'))

고치다

더러운 수정 - 권장되지 않습니다

import paramiko
hostname,username,password='fill','these','in'
''.decode('utf-8')  # dirty fix
c = paramiko.SSHClient()
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
c.connect(hostname=hostname, username=username, password=password)
i,o,e = c.exec_command('ls /')
print(o.read())
c.close()

좋은 수정

import paramiko
if __name__ == '__main__':
    hostname,username,password='fill','these','in'
    c = paramiko.SSHClient()
    c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    c.connect(hostname=hostname, username=username, password=password)
    i,o,e = c.exec_command('ls /')
    print(o.read())
    c.close()

심판 Paramiko 문제 추적기 : 문제 104

"".decode ( "UTF-8")는 저에게 효과가 없었고 결국 이것을했습니다.

from paramiko import py3compat
# dirty hack to fix threading import lock (issue 104) by preloading module
py3compat.u("dirty hack")

구현 된 Paramiko의 래퍼가 있습니다.https://github.com/bucknerns/sshaolin

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top