Python paramiko 모듈의 장기 실행 SSH 명령 (및 종료 방법)
문제
나는 실행하고 싶다 tail -f logfile
Python의 Paramiko 모듈을 사용하여 원격 시스템에서 명령하십시오. 나는 지금까지 다음과 같은 방식으로 그것을 시도해 왔습니다.
interface = paramiko.SSHClient()
#snip the connection setup portion
stdin, stdout, stderr = interface.exec_command("tail -f logfile")
#snip into threaded loop
print stdout.readline()
필요에 따라 명령이 오래 실행되기를 원하지만 두 가지 문제가 있습니다.
- 이것을 깨끗하게 멈추는 방법은 무엇입니까? 나는 채널을 만들고
shutdown()
내가 그것을 통과 할 때 채널에 명령을 내리십시오. 그러나 그것은 지저분 해 보입니다. 보낸 것과 같은 일을 할 수 있습니까?Ctrl-C
채널의 Stdin에? readline()
블록, 그리고 출력을 얻지 못하는 블로킹 방법이 있으면 스레드를 피할 수 있습니까?
해결책
1) 원하는 경우 고객을 닫을 수 있습니다. 다른 쪽 끝에있는 서버는 꼬리 프로세스를 죽입니다.
2) 블로킹하지 않는 방식 으로이 작업을 수행 해야하는 경우 채널 객체를 직접 사용해야합니다. 그런 다음 Channel.recv_ready () 및 Channel.recv_stderr_ready ()로 stdout과 stderr를 모두 시청하거나 select.select를 사용하십시오.
다른 팁
클라이언트에서 exec_command를 호출하는 대신 전송을 유지하고 자신의 채널을 생성하십시오. 그만큼 채널 명령을 실행하는 데 사용할 수 있으며 선택 문서에서 사용하여 데이터를 읽을 수있는시기를 찾을 수 있습니다.
#!/usr/bin/env python
import paramiko
import select
client = paramiko.SSHClient()
client.load_system_host_keys()
client.connect('host.example.com')
transport = client.get_transport()
channel = transport.open_session()
channel.exec_command("tail -f /var/log/everything/current")
while True:
rl, wl, xl = select.select([channel],[],[],0.0)
if len(rl) > 0:
# Must be stdout
print channel.recv(1024)
채널 객체는 원격 명령의 stdout 및 stdin과 연결하여 읽고 쓸 수 있습니다. 당신은 전화를 통해 Stderr에 갈 수 있습니다 channel.makefile_stderr(...)
.
타임 아웃을 설정했습니다 0.0
비 블로킹 솔루션이 요청 되었기 때문에 초. 필요에 따라 0이 아닌 타임 아웃으로 차단할 수 있습니다.
Andrew Aylett의 솔루션에 대한 작은 업데이트. 다음 코드는 실제로 루프를 중단하고 외부 프로세스가 완료되면 다음과 같습니다.
import paramiko
import select
client = paramiko.SSHClient()
client.load_system_host_keys()
client.connect('host.example.com')
channel = client.get_transport().open_session()
channel.exec_command("tail -f /var/log/everything/current")
while True:
if channel.exit_status_ready():
break
rl, wl, xl = select.select([channel], [], [], 0.0)
if len(rl) > 0:
print channel.recv(1024)
프로세스를 닫으려면 단순히 실행됩니다.
interface.close()
비 차단 측면에서는 차단을 읽지 못할 수 없습니다. 당신이 할 수있는 최선의 방법은 한 번에 하나의 "블록"을 구문 분석하는 것입니다. "stdout.read (1)"은 버퍼에 캐릭터가없는 경우에만 차단됩니다.
정보를 얻으려면 Channel.get_pty ()를 사용하여이를 수행하는 솔루션이 있습니다. 더 자세한 내용은 다음을 살펴 봅니다. https://stackoverflow.com/a/11190727/1480181