Python]paramiko 모듈에서 su 명령어로 계정 전환

python에서 ssh에 연결 후 command를 실행하기 위해 사용하는 paramiko 모듈에서 간단하게 command를 실행하는 코드는 다음과 같다.

import paramiko

ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # host keys 관련 설정
ssh_client.connect('127.0.0.1', username='lahuman', password='pass')

stdin, stdout, stderr = ssh_client.exec_command('ls')
stdin.flush()
time.sleep(1)
print stdout.read()

## 결과
lahuman
  • host kyes 관련 설정은 ssh로 다른 서버로 접근시, key 값을 저장할 지에 대한 처리 이다. paramiko.AutoAddPolicy() 로 설정시 자동으로 yes 처리 된다.

ssh_client.exec_command(cmd)를 이용할 경우 매 명령어 마다 새로운 세션이 부여되어, 다른 계정으로 전환 후 작업을 진행 할 수 없다.

하나의 세션에서 작업을 연속되게 진행하고 싶다면 channel = ssh_client.invoke_shell()를 이용하면 된다.

import paramiko

def main():
    ssh_client = None
    recv_size = 9999
    try:
		ssh_client = paramiko.SSHClient()
		ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # host keys 관련 설정
		ssh_client.connect('127.0.0.1', username='lahuman', password='pass')

        channel = ssh_client.invoke_shell()
        channel.send('su -\n')
        outdata, errdata = waitStrems(channel)
        print outdata

        channel.send('pass\n')
        outdata, errdata = waitStrems(channel)
        print outdata

        channel.send('whoami\n')
        outdata, errdata = waitStrems(channel)
        print outdata

    finally:
        if ssh_client is not None:
            ssh_client.close()


def waitStrems(chan):
    time.sleep(1)
    outdata=errdata = ""

    while chan.recv_ready():
        outdata += chan.recv(1000)
    while chan.recv_stderr_ready():
        errdata += chan.recv_stderr(1000)

    return outdata, errdata

if __name__ == "__main__":
    main()


## 결과
Last login: Thu May 17 01:34:37 2018 from 10.0.2.2
su -
[lahuman@localhost ~]$ su -
Password: 

Last login: Thu May 17 01:35:10 EDT 2018
[root@localhost ~]# 
whoami
root
[root@localhost ~]# 

세션을 유지한 상태로 명령어를 실행하기 위해서는 channel을 가져오고 channel을 계속 유지 해야 한다.

각 명령의 결과가 문제 없이 종료 되었는지는

 while chan.recv_ready():
        outdata += chan.recv(1000)
    while chan.recv_stderr_ready():
        errdata += chan.recv_stderr(1000)

를 통해서 확인 한다.

참고 자료


Posted by lahuman

Python에서 class 선언시 object를 꼭 상속 받자

python은 전역 객체를 선언할 경우 해당 클래스를 메모리에 올리는 초기 작업에서 실행 된다. 예를 들어 다음과 같은 코드에서 # 1, # 2 순서로 실행된다.

import lahuman

class test(object):
	a = lahuman.A() # 1 : 

	def b(self):
		pass

main python

import test # 1

if __name__ == '__main__':
    t = test()
    t.b() # 2

또한 test 클래스가 object를 상속 받지 않을 경우 객체 생성시 object를 상속 받지 않으면 객체생성시 new 메소드가 호출되지 않는다.



Posted by lahuman

파이썬을 이용한 압축 해제와 동시에 파일 이름 변경

특정 사이트에서 대량의 압축된 파일을 받아 하나의 디렉터리에 풀어야 하는 미션이 떨어졌다.

문제는 같은 파일 명이 중복으로 발생할 수 있다.

이에 대한 해결책으로 다음 2개의 방법으로 고민했다.

  1. 파일 압축 해제 후 MV 명령어로 이름 변경
  2. 압축을 해제할 때 PATH를 줄 수 있는가?

1번의 방법은 누구나 쉽게 할 수 있을 것 같았다.

2번의 경우 가능 한지 조차 몰라서 Python에서 압축 관련 모듈인 ZipFile을 살펴보았다.

내용을 확인 결과 압축 파일에서 하나의 파일을 읽을 수 있는 read리는 function이 있다.

이를 이용해 다음과 같이 처리하였다

with ZipFile("filename.zip") as zf:
    
    file_list = map(lambda x: "/" + str(uuid.uuid4()), zf.filelist) # 파일 개수만큼 uuid를 생성
    idx = 0
    for zip_file in zf.namelist():  # 루프를 돌며 하나의 파일을 가져옴
        target_path = zip_save_path + file_list[idx]  # 저장되는 파일 위치
        with open(target_path, "wb") as f:  # 저장되는 파일을 쓰기 모드로 오픈
            f.write(zf.read(zip_file, pwd=self.password))  # 압축된 파일을 읽어서 타깃 파일로 저장

        idx += 1 # 다음 uuid 선택

파일은 내가 원하는 위치에 uuid 값으로 저장된다.

참고자료


Posted by lahuman