-
파이썬으로 쉘 명령어 날리기 (부제: AWS CLI 에러 읽어오기)Tips 2022. 6. 16. 01:34728x90반응형
Python으로 쉘 명령어를 날리는 법 중 세 가지를 정리해본다.
1. os.system
import os os.system('쉘 명령어')
os.system은 쉘 명령어의 수행 결과값을 콘솔에 출력한다. 즉, 수행 결과값을 파이썬 내에서 사용할 수 없다.
import os os.system('echo Hello') result = os.system('echo Hello') print(result)
위의 파이썬 파일을 실행하면 출력값은 Hello/Hello/0이다. 즉, 변수에 담는 코드 줄도 결과를 콘솔에 출력하고 result에는 0이 담긴다.
2. os.popen
출력 결과값을 변수에 담아서 사용하고 싶다면 os.popen을 사용할 수 있다.
import os os.popen('쉘 명령어')
os.popen은 결과값을 콘솔에 출력하지 않고 수행만 한다 (수행은 한다는 점에 주의). 결과값을 변수에 담고싶다면 .read() 함수를 호출하면 된다.
import os os.popen('echo Hello') obj = os.popen('echo Hello') print(result) result = os.popen('echo Hello').read() print(result)
위의 파이썬 파일 출력값은 <os._wrap_close object at 0x1030d6fd0>/Hello다. 두 번의 print의 수행 결과값이다.
문제는 여기서 봉착했다. 나는 이 기능을 AWS CLI 명령어를 전달하는데 사용했는데, os.popen은 명령어의 최종 결과값만 받아온다. 즉, 하위 프로세스에서 에러가 난 경우, 해당 에러메세지는 콘솔에 출력하고 결과로 받아오지 못했다. 그래서 사용한 모듈이 subprocess이다.
3. subprocess.Popen
(맨 앞에 P 대문자임에 주의)
import subprocess subprocess.Popen('쉘 명령어')
class subprocess.Popen(args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None,
preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=None,
startupinfo=None, creationflags=0, restore_signals=True, start_new_session=False,
pass_fds=(), *, encoding=None, errors=None, text=None)(공식문서)
Popen은 option 설정으로 콘솔에 결과값을 출력할 수도, 변수에 담을 수도 있다. 몇 가지 옵션을 살펴보면 다음과 같다.
- stdout: Captured stdout from the child process -> PIPE로 할당하면 subprocess를 실행시키는 표준 입출력으로 사용할 수 있다.
- stderr: Captured stderr from the child process -> stdout으로 설정하면 출력으로 같이 볼 수 있다.
- text: 출력값을 텍스트로 받을 건지 바이너리로 받을 건지 설정하는 인자이다 (아래 코드 예제에서 출력값을 비교해보자).
- shell: shell을 통해 명령어 전달. 해당 인자를 True로 사용하지 않으면 명령어에 띄워쓰기가 들어가는 경우 리스트로 전달해야한다 (아니면 파일명으로 인식한다). 하지만 유효성 검사가 되지 않기 때문에 False로 지정하는 것이 권장된다. shell=True를 안 쓸 경우 명령어.split(' ')으로 념겨줘도 된다.
import subprocess one_line = subprocess.Popen('ls', text=True, stdout=subprocess.PIPE).stdout.read() shell_false = subprocess.Popen(['echo','Hello'], text=True, stdout=subprocess.PIPE).stdout.read() use_split = subprocess.Popen('echo Hello'.split(), text=True, stdout=subprocess.PIPE).stdout.read() shell_true = subprocess.Popen('echo Hello', shell=True, text=True, stdout=subprocess.PIPE).stdout.read() text_false = subprocess.Popen('echo Hello', shell=True, stdout=subprocess.PIPE).stdout.read() print(one_line) #띄어쓰기가 없는 명령어는 shell=True 옵션이 없어도 잘 출력된다 print(shell_false) #띄어쓰기가 있는 경우 리스트로 전달하거나 print(use_split) #split()을 사용하거나 print(shell_true) #shell=True 옵션을 사용한다. print(text_false) #text 옵션을 false로 지정하면 바이너리로 출력된다.
위 파일의 출력값은 (파일 리스트)/Hello/Hello/Hello/b'Hello\n' 이다.
그래서 다음 옵션을 통해 AWS CLI 명령어 에러 출력값을 텍스트로 변수에 담을 수 있었다.
from subprocess import Popen, PIPE, STDOUT command = 'aws lambda update-function-code --function-name batch-test --zip-file fileb://lambda_function.zip' result = Popen(command, stdout=PIPE, stderr=STDOUT, shell=True, text=True).stdout.read()
정말 다행히도 모두 파이썬 표준 라이브러리이다. 표준 라이브러리 사랑해요
그리고 마지막으로 저걸 다 찾아내고 나서야 그냥 boto3를 쓰면 된다는 것이 생각났다 ^_^v. 참고로 AWS에서도 파이썬에서 저런 방식으로 AWS CLI 명령어를 전달한는 것보다 boto3를 사용하는 것을 권장한다고 한다.
728x90반응형'Tips' 카테고리의 다른 글
Github 커밋 하나로 합치기 (전체, 선택) (0) 2022.06.20 Git & Github 브랜치 삭제 (0) 2022.06.20 AWS AccessDeniedException: user is not authorized to perform: iam:PassRole on resource 에러 해결 방법 (0) 2022.06.15 맥 실리콘 m1칩에서 brew와 brew로 aws cli 설치하기 (0) 2022.05.24 OLTP vs OLAP (0) 2022.03.29