본문 바로가기

Java

apache commons exec 을 이용한 java에서 linux script 실행

보통 linux 쓰면 인터넷 연결된 경우 시간을 알아서 동기화한다.

그런데 이 케이스에서는 인터넷 연결이 안 돼서 시간설정을 수동으로밖에 할 수 없는 상황이었다.


일단 시간 설정을 하려면 root 계정으로

date -s "2017-01-18 13:00:00"

이렇게 입력하면 된다.


내가 생각한건, 

1. jsp에서 javascript new Date()로 클라이언트 시간을 가져옴

2. 그 시간으로 리눅스 시간 셋팅


요거였고, 여기서 문제가 된건 2번.. 

java에서 linux 명령어를 입력할 수 가 있나? 하는 것이었다.

찾아보니 아파치에서 만든게 있더라.


스프링 기반 웹프로젝트이고, 메이븐을 사용했으므로 일단 pom.xml에 아래와 같이 추가


<dependency>

   <groupId>org.apache.commons</groupId>

   <artifactId>commons-exec</artifactId>

   <version>1.1</version>

</dependency>


그리고 아래와 같이 소스를 짜보았다.


logger.info("dateStr==="+dateStr);//이게 jsp에서 넘겨준 날짜값

int exitCode = 1;

DefaultExecutor executor = new DefaultExecutor();


try {

  

  String line = "sudo date -s";

  CommandLine cmdLine = CommandLine.parse(line);

  // 따옴표 추가 방지 위해 두번재 인자에 false 추가

  cmdLine.addArgument(dateStr, false);

  logger.info("cmdLine==="+cmdLine);

  exitCode = executor.execute(cmdLine);


   logger.info("exitCode : " + exitCode);   


} catch (Exception e) {

  logger.warn(e.getMessage(), e);

  throw new Exception(e.getMessage(), e);

}


return exitCode;


명령어가 제대로 돌아가면 exitCode가 0이 나온다. 

요걸 return해주고 성공/실패 여부를 판단하도록 했다.


root계정으로 실행해야하기때문에 sudo를 앞에 붙여줬다.

그리고 실행을 해봤는데, 2가지 문제가 발생했다.


1. sudo를 그냥 쓸수가 없다!


sudo: no tty present and no askpass program specified

위와 같은 에러가 났다.

구글링해보니, root계정이 아닌 계정으로 sudo 명령어를 쓰려면 추가적인 작업이 필요한 것 같았다.

root로 로그인 후, visudo 실행 후 유저에게 권한(?)을 주는 라인을 추가했다.

tomcat_user(나같은 경우 서버가 톰캣이었으므로 톰캣 실행하는 계정) ALL=(ALL) NOPASSWD: ALL

이렇게 하면 보안상 절대 하면 안되겠지만... 지금 같은 특이케이스에서는 뭐, 어쩔수 없다고 봤다.


2. date: invalid date ‘"2017-01-10 12:00:00"’


이렇게 하면 이제 될 줄 알았더니 이건 또 무슨... 날짜 형식이 유효하지 않다는 에러가 떴다.

이것도 구글링 해보니, commons-exec의 버그라는 것 같다.

http://stackoverflow.com/questions/4927226/apache-commons-exec-produces-too-many-quotes-for-arguments-containing-spaces

인자에 따옴표를 자기 맘대로 추가하는 버그인 것 같고, 

그래서 ""2017-01-10 12:00:00"" 이런 식으로 쌍타옴표가 두번 들어가서 에러가 난것으로 보인다.

다행히도 해결책이 있어서 cmdLine.addArgument(dateStr, false); 와 같이 두번째 인자로 false를 넘겨주면

따옴표 자동 감싸기가 적용되지 않는다.



그렇게 몇번의 시도 끝에 성공..!


java에서 OS의 command 명령어를 실행할 수 있게 만든 개발자는 누구일까.. 또 감탄하게 된 하루...