복붙노트

[PYTHON] Paramiko와 exec_command - 원격 프로세스를 종료합니까?

PYTHON

Paramiko와 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. ==============================

    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. ==============================

    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. ==============================

    3.이를 수행하는 한 가지 방법이 있습니다. 그것은 쉘에서와 같이 작동합니다.

    이를 수행하는 한 가지 방법이 있습니다. 그것은 쉘에서와 같이 작동합니다.

    ssh -t commandname
    

    -t 옵션은 pseudo pty를 열어서 ssh가이 프로세스의 지속 시간을 추적 할 수 있도록 도와줍니다. 동일은 통해 포르 모코 통해 수행 할 수 있습니다

    channel.get_pty()
    

    execute_command (...) 이전에. channel.invoke_shell ()을 사용하는 것처럼 쉘을 열지는 않습니다.이 프로세스는 의사 인터페이스를 요청하여 모든 프로세스를 연결합니다. ps aux가 원격 컴퓨터에서 실행되면 프로세스가 ptxXY 인터페이스로 sshd에 연결됩니다.

  4. ==============================

    4.방금이 문제를 짚었습니다. 결국 프로세스를 종료 할 pkill을 발행 할 수있는 위치에 없었습니다.

    방금이 문제를 짚었습니다. 결국 프로세스를 종료 할 pkill을 발행 할 수있는 위치에 없었습니다.

    더 나은 해결책은 실행중인 명령을 변경하는 것입니다.

    tail -f /path/to/file & { read ; kill %1; }
    

    이렇게하면 필요한만큼 꼬리 명령을 실행할 수 있습니다. 원격 프로세스에 개행 문자를 보내면 kill % 1이 실행되고 사용자가 백그라운드에서 지정한 tail 명령을 중지합니다. (참고 용 : % 1은 jobspec이며 세션에서 백그라운드로 처리 된 첫 번째 프로세스, 즉 tail 명령을 설명하는 데 사용됩니다)

  5. ==============================

    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. ==============================

    6.특히 '꼬리'의 경우 --pid = PID 인수를 사용하여 꼬리가 처리하도록 할 수 있습니다.

    특히 '꼬리'의 경우 --pid = PID 인수를 사용하여 꼬리가 처리하도록 할 수 있습니다.

      --pid=PID  with -f, terminate after process ID, PID dies
    
  7. ==============================

    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. ==============================

    8.ssh -t와 같은 문제가있었습니다. 클로저라는 라이브러리가 있습니다 - ssh를 통해 원격 프로세스를 실행하고 자동으로 닫힙니다. 확인 해봐.

    ssh -t와 같은 문제가있었습니다. 클로저라는 라이브러리가 있습니다 - ssh를 통해 원격 프로세스를 실행하고 자동으로 닫힙니다. 확인 해봐.

  9. from https://stackoverflow.com/questions/7734679/paramiko-and-exec-command-killing-remote-process by cc-by-sa and MIT license