[PYTHON] Paramiko와 exec_command - 원격 프로세스를 종료합니까?
PYTHONParamiko와 exec_command - 원격 프로세스를 종료합니까?
필자는 Paramiko를 사용하여 원격 서버의 파일을 처리합니다.
이전에는 ssh -t를 통해이 작업을 수행 했었지만 이는 비정상적인 것으로 판명되었고 -t는 원격 스케줄링 시스템에서 문제를 일으켰습니다.
내 질문은 스크립트가 SIGINT를 잡을 때 꼬리를 없애는 방법이다.
내 스크립트 (Python paramiko 모듈에서 장기 실행 ssh 명령을 기반으로합니다 (끝내는 방법)
#!/usr/bin/env python2
import paramiko
import select
client = paramiko.SSHClient()
client.load_system_host_keys()
client.connect('someserver', username='victorhooi', password='blahblah')
transport = client.get_transport()
channel = transport.open_session()
channel.exec_command("tail -f /home/victorhooi/macbeth.txt")
while True:
try:
rl, wl, xl = select.select([channel],[],[],0.0)
if len(rl) > 0:
# Must be stdout
print channel.recv(1024)
except KeyboardInterrupt:
print("Caught control-C")
client.close()
channel.close()
exit(0)
이 스크립트는 내 Ctrl-C를 성공적으로 잡아서 끝냅니다. 그러나 tail -f 프로세스는 원격 시스템에서 실행됩니다.
client.close ()도 channel.close ()도 종료 된 것처럼 보이지 않습니다.
except 블록에서 어떤 명령을내어 죽일 수 있습니까?
원격 서버에서 Solaris 10을 실행 중입니다.
해결법
-
==============================
1.가장 효율적인 방법은 아니지만이 방법이 효과적입니다. Ctrl + C를 누른 후; KeyboardInterrupt 핸들러에서 다음과 같이 exec_command ( "killall -u % tail"% uname) 할 수 있습니다.
가장 효율적인 방법은 아니지만이 방법이 효과적입니다. Ctrl + C를 누른 후; KeyboardInterrupt 핸들러에서 다음과 같이 exec_command ( "killall -u % tail"% uname) 할 수 있습니다.
#!/usr/bin/env python2 import paramiko import select import time ltime = time.time() # Or use random: # import random # ltime = random.randint(0, 500) uname = "victorhooi" client = paramiko.SSHClient() client.load_system_host_keys() client.connect('someserver', username=uname, password='blahblah') transport = client.get_transport() channel = transport.open_session() channel.exec_command("tail -%df /home/victorhooi/macbeth.txt" % ltime) while True: try: rl, wl, xl = select.select([channel],[],[],0.0) if len(rl) > 0: # Must be stdout print channel.recv(1024) except KeyboardInterrupt: print("Caught control-C") channel.close() try: # open new socket and kill the proc.. client.get_transport().open_session().exec_command("kill -9 `ps -fu %s | grep 'tail -%df /home/victorhooi/macbeth.txt' | grep -v grep | awk '{print $2}'`" % (uname, ltime)) except: pass client.close() exit(0)
이것은 tail이라는 이름의 열린 프로세스를 모두 종료시킵니다. 그게 문제를 일으킬 수 있습니다 당신이 꼬리가 열려있는 경우에는 닫지 않으려는 경우, ps는 grep 수있는 경우, PID를 얻을 죽일 - 9 그것.
먼저 꼬리를 설정하여 파일 끝에서 n 줄을 읽은 다음 따라 와야합니다. tail.time ()과 같이 고유 한 nuber로 설정합니다. tail은 파일의 행 수보다 큰지 여부에 상관이 없으므로 time.time ()의 큰 숫자는 문제가 발생하지 않아 고유해야합니다. 그런 다음 ps의 해당 고유 번호에 대한 grep :
client.get_transport().open_session().exec_command("kill -9 `ps -fu %s | grep 'tail -%df /home/victorhooi/macbeth.txt' | grep -v grep | awk '{print $2}'`" % (uname, ltime))
-
==============================
2.ssh keepalives를 사용해야합니다. 문제는 원격 쉘이 (기본적으로) ssh 세션이 종료되었음을 알 수있는 방법이 없다는 것입니다. Keepalives는 원격 쉘이 당신이 세션을 죽였다는 것을 탐지 할 수있게합니다
ssh keepalives를 사용해야합니다. 문제는 원격 쉘이 (기본적으로) ssh 세션이 종료되었음을 알 수있는 방법이 없다는 것입니다. Keepalives는 원격 쉘이 당신이 세션을 죽였다는 것을 탐지 할 수있게합니다
client = paramiko.SSHClient() client.load_system_host_keys() client.connect('someserver', username='victorhooi', password='blahblah') transport = client.get_transport() transport.set_keepalive(1) # <------------------------------ # ... carry on as usual...
keepalive 값을 원하는만큼 낮게 설정하십시오 (심지어 1 초). 몇 초 후에 ssh 로그인이 종료되었음을 원격 쉘이 알게되고, 이로 인해 생성 된 모든 프로세스가 종료됩니다.
-
==============================
3.이를 수행하는 한 가지 방법이 있습니다. 그것은 쉘에서와 같이 작동합니다.
이를 수행하는 한 가지 방법이 있습니다. 그것은 쉘에서와 같이 작동합니다.
ssh -t commandname
-t 옵션은 pseudo pty를 열어서 ssh가이 프로세스의 지속 시간을 추적 할 수 있도록 도와줍니다. 동일은 통해 포르 모코 통해 수행 할 수 있습니다
channel.get_pty()
execute_command (...) 이전에. channel.invoke_shell ()을 사용하는 것처럼 쉘을 열지는 않습니다.이 프로세스는 의사 인터페이스를 요청하여 모든 프로세스를 연결합니다. ps aux가 원격 컴퓨터에서 실행되면 프로세스가 ptxXY 인터페이스로 sshd에 연결됩니다.
-
==============================
4.방금이 문제를 짚었습니다. 결국 프로세스를 종료 할 pkill을 발행 할 수있는 위치에 없었습니다.
방금이 문제를 짚었습니다. 결국 프로세스를 종료 할 pkill을 발행 할 수있는 위치에 없었습니다.
더 나은 해결책은 실행중인 명령을 변경하는 것입니다.
tail -f /path/to/file & { read ; kill %1; }
이렇게하면 필요한만큼 꼬리 명령을 실행할 수 있습니다. 원격 프로세스에 개행 문자를 보내면 kill % 1이 실행되고 사용자가 백그라운드에서 지정한 tail 명령을 중지합니다. (참고 용 : % 1은 jobspec이며 세션에서 백그라운드로 처리 된 첫 번째 프로세스, 즉 tail 명령을 설명하는 데 사용됩니다)
-
==============================
5.다음은 원격 프로세스 ID를 얻는 방법입니다.
다음은 원격 프로세스 ID를 얻는 방법입니다.
def execute(channel, command): command = 'echo $$; exec ' + command stdin, stdout, stderr = channel.exec_command(command) pid = int(stdout.readline()) return pid, stdin, stdout, stderr
그리고 그것을 사용하는 방법이 있습니다 (원래 질문의 비트를 ...로 대체하십시오) :
pid, _, _, _ = execute(channel, "tail -f /home/victorhooi/macbeth.txt") while True: try: # ... except KeyboardInterrupt: client.exec_command("kill %d" % pid) # ...
-
==============================
6.특히 '꼬리'의 경우 --pid = PID 인수를 사용하여 꼬리가 처리하도록 할 수 있습니다.
특히 '꼬리'의 경우 --pid = PID 인수를 사용하여 꼬리가 처리하도록 할 수 있습니다.
--pid=PID with -f, terminate after process ID, PID dies
-
==============================
7.https://stackoverflow.com/a/38883662/565212에 설명 된대로 get_pty를 사용할 수 있습니다.
https://stackoverflow.com/a/38883662/565212에 설명 된대로 get_pty를 사용할 수 있습니다.
예 : 시나리오 - client / channel.close ()를 호출 할시기 : 1 단계 : 로그 파일에 기록하는 원격 명령을 실행하십시오. Step2 : tail 명령을 실행하고 readline 루프에서 블록을 실행하는 스레드 생성 Step3 : 메인 쓰레드에서 커맨드가 돌아 왔을 때 더 이상의 로그가 없다는 것을 알게되고 테일 쓰레드를 죽인다.
-
==============================
8.ssh -t와 같은 문제가있었습니다. 클로저라는 라이브러리가 있습니다 - ssh를 통해 원격 프로세스를 실행하고 자동으로 닫힙니다. 확인 해봐.
ssh -t와 같은 문제가있었습니다. 클로저라는 라이브러리가 있습니다 - ssh를 통해 원격 프로세스를 실행하고 자동으로 닫힙니다. 확인 해봐.
from https://stackoverflow.com/questions/7734679/paramiko-and-exec-command-killing-remote-process by cc-by-sa and MIT license
'PYTHON' 카테고리의 다른 글
[PYTHON] 파이썬에서 유니 코드 이스케이프 시퀀스가있는 유니 코드 텍스트 [duplicate] (0) | 2018.11.17 |
---|---|
[PYTHON] 한 목록을 다른 파이썬으로 매핑하는 방법은 무엇입니까? [복제] (0) | 2018.11.17 |
[PYTHON] 플라스크 유닛 테스트 : 로그인 한 사용자의 요청 테스트 방법 (0) | 2018.11.17 |
[PYTHON] 여러 연결 요청 (0) | 2018.11.17 |
[PYTHON] 어떻게하면 OS의 기본 프린터 인 Python 3 (크로스 플랫폼)에서 인쇄 할 수 있습니까? (0) | 2018.11.17 |