본문 바로가기

Python

[python] 파이썬으로 리눅스 쉘 명령어 수행하기

반응형

 

파이썬 스크립트에서 중간에 리눅스 쉘 명령어를 수행하고 싶다면 어떻게 해야할까?

 

보통 아래와 같이 두가지 방법을 사용한다. 

 

 

1. os.system

>>> import os
>>> os.system('pwd')
/root
0
>>> os.system('ls')
docker  elk_test  hs_err_pid28828.log  kibana  python_test  spark-2.4.5-bin-hadoop2.7.tgz
0
>>> os.system('touch a')
0

 

os 모듈을 임포트해서 system 함수를 사용하여 리눅스 명령어를 수행한다. 파이썬을 수행하는 환경에 명령어를 전달하여 수행한다. os.system은 인자값으로 명령어만 전달해주면 수행해주기 때문에 직관적이나, 명령어의 결과값들을 변수에 저장할 수 없다는 한계가 있다. os.system 의 결과는 프로세스의 수행 결과 값을 리턴하는데 보통 성공하면 0을 리턴하고 실패했을 때는 그에 맞는 에러 코드가 반환된다.

 

만약 출력값을 저장하고 싶다면 아래와 같이 popen을 통해 명령어를 수행하고 read를 통해 읽는 방법을 통해 출력값을 변수에 저장할 수 있다.

 

import os
>>> path = os.popen('pwd').read()
>>> path
'/root\n'
>>> i = os.popen('whoami').read()
>>> i
'root\n'

 

2. subprocess

import subprocess
>>> subprocess.call("whoami")
root
0
>>> subprocess.call(["touch", "a"])
0

subprocess 모듈을 통해서도 리눅스 명령어를 수행할 수 있다. 대략적인 사용방법은 위와 같다. 주의할 사항은 인자값으로 들어가는 경우에는 문자열 리스트로 명령어를 전달한다. 위의 예제에서 touch a 명령어를 touch 명령어와 생성될 파일명인 a를 리스트로 따로 전달한 것을 볼 수 있다.

 

만약 출력값을 변수에 전달하고 싶을때는 check_output 명령어를 통해서 할 수 있다.

 

>>> import subprocess
>>> text = subprocess.check_output(["cat","README.md"])
>>> text
b'Hello\n'
>>> i = subprocess.check_output("whoami")
>>> i
b'root\n'

 

명령어가 여러개의 서브명령어 또는 옵션을 가지게 되는 경우에는 위와 같이 리스트 형식으로 넘기기가 힘들어진다. 그럴떄는 아래와 같이 shell=True 옵션을 주면 한번에 명령어를 수행할 수 있다. 

 

text = subprocess.check_output("cat README.md", shell=True)
>>> text
b'Hello\n'

 

하지만 위 방법은 쉘 수행시 별도의 유효성 검사를 수행하지 않기 때문에 쉘 주입(Shell Injection)에 대해 취약할 수 있다고 한다. 그래서 사용시 주의해야 한다.  

반응형