2011년 2월 18일 금요일

[Android/Java] Run shell command

안드로이드 (혹은 Java에서) 쉘 커맨드 실행하고 결과 읽어오기? Python의 os.popen과 비교되는 녀석이라 메모.

기본적으로 Java의 Runtime / DataInputStream / DataOutputStream 를 이용하는 거니 안드로이드가 아니라도 돌아가겠지만 일단 안드로이드 에서 구현해 본 거라서 안드로이드 카테고리로 글을 쓴다.

기본은 Runtime을 이용한 실행. Java 스럽게 보기 싫은 준비가 필요하다.
Runtime rt = Runtime.getRuntime();
Process prc = rt.exec("Shell command");
BufferedReader reader = new BufferedReader(
  new InputStreamReader(prc.getInputStream()), 1024);

while ((line = reader.readLine()) != null) {
  ...
}
Runtime의 exec로 실행시킬 때 argument를 넘기는 방법은 리스트로 넘기는 형태였던가. 잘 기억 안나는데 문서를 뒤져보는게 좋을 듯.

어쨌든 while문 내부에서 line을 통해 결과를 얻을 수 있다.

실행의 다른 방법은 OutputStream을 이용하는 방법이 있다.
DataOutputStream os = 
  new DataOutputStream(prc.getOutputStream());
DataInputStream is = 
  new DataInputStream(prc.getInputStream());
사실 Runtime을 통해 Process를 뽑아낸 prc에서 가져오는 거라 Runtime을 이용한 후에나 가능한 것 같지만 일단 이렇게 준비해 둘 수가 있다.

이 후 쉘 커맨드를 실행시킬 때는 단순하다.
os.writeBytes("Shell commands with arguments" + "\n");
인자 까지 몽땅 스트링으로 넘겨주면 된다. 즉, 이건 쉘로 해당 문자열을 전송하는 거라고 볼 수 있다. Runtime의 exec()에 비해 커맨드를 문자열화 할 수 있다는 건 꽤 효용성이 있다. 안드로이드용 터미널앱을 만들 때 꽤나 유용하게 써먹을 수 있을 것 같다.

만약 루팅(rooting)된 폰에서 su를 exec한 결과를 이용해 input stream/output stream을 만들어 놓으면 루트쉘을 이용할 수 있게 되는데... -ㅁ- 아아 위험 위험... 루팅은 이렇게 보안에 취약하다는 걸 알아야한다.

ps. su는 super user의 약자가 아니라 switch user의 약자라는 걸 모르는 사람 제법 될거다 아마...;; (주. substitute user 가 맞다는 제보가... 어흑 ;ㅁ;)

댓글 2개 :

익명 :

switch 아니고 substitute입니다. 중요한 것은 아니지만,

Seorenn :

어라 제가 잘못 알고 있었던 것인가요 -ㅁ-; 쪽팔리는데;;;