Skip to content

Commit

Permalink
Merge pull request #95 from JNU-econovation/fix_transient_process
Browse files Browse the repository at this point in the history
[FIX] output stream을 건들기 전에 프로세스가 종료됐는지 확인하는 로직 추가 (broken pipe 방지)
  • Loading branch information
inferior3x authored Dec 18, 2024
2 parents 166a1ca + 1bd8a94 commit 8b0b163
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import lombok.extern.slf4j.Slf4j;

//실행 후 종료되어 모든 출력을 얻는 프로세스
//출력 스트림을 통한 프로세스와의 상호작용은 없다.

@Slf4j
public class TransientProcess {

protected BufferedReader br;
Expand All @@ -21,29 +22,46 @@ public TransientProcess() {}

// sudo 없이 실행할 커맨드
// command 예시: "ifconfig"
// IOException을 여기서 처리하므로 무조건 실행되어야 하는 명령어는 사용하면 안된다!
public TransientProcess(String command){
try {
this.process = new ProcessBuilder(command.split(" "))
.redirectErrorStream(true)
.start();
} catch (IOException e) {
throw new RuntimeException(command+" - 실행 실패");
throw new RuntimeException("[Transient Process] " + command + " : 실행 실패");
}
this.br = new BufferedReader(new InputStreamReader(process.getInputStream()));
this.ebr = new BufferedReader(new InputStreamReader(process.getErrorStream()));
}

// sudo로 실행할 커맨드
// sudoCommand 예시: "sudo iwconfig"
// sudo 없이 실행한 커맨드일 경우 writer에 flush하기도 전에 끝날 수 있으므로 나눠진 것
// sudo로 실행할 커맨드는 비밀번호 입력이 필요하여 나눠진 것
// sudoCommand 예시: "sudo -S iwconfig"
// IOException을 여기서 처리하므로 무조건 실행되어야 하는 명령어는 사용하면 안된다!
public TransientProcess(String sudoCommand, String sudoPassword) {
this(sudoCommand);
Writer writer = new OutputStreamWriter(this.process.getOutputStream());
try {
/*
writer를 통해 password를 입력하기 전에 프로세스가 종료됐을경우 예외가 뜬다.
프로세스가 빨리 끝나는 두 가지 경우의 수가 있다. (정상적인 상황이라고 가정)
1. sudo로 실행을 안했을때
2. (리눅스) groups에 포함된 사용자로 실행했을때
이를 아래에서 catch한다.
*/
writer.write(sudoPassword + System.lineSeparator());
writer.flush();
} catch (IOException e) {
throw new RuntimeException(sudoCommand + " - sudo 명령어 입력 중 오류 발생");
if (e.getMessage().contains("Broken pipe") && //프로세스가 종료됐거나 연결이 끊겨서 발생한 예외인지
!this.process.isAlive() && //프로세스가 종료됐는지
this.process.exitValue() == 0 //프로세스가 정상적으로 종료됐는지
) {
//정상적으로 실행됐다고 판단하여 warn 로깅
log.warn("[Transient Process] {} : sudo 비밀번호 입력 전에 프로세스 종료됨", sudoCommand);
return;
}
//이외는 예외를 띄운다.
throw new RuntimeException("[Transient Process] " + sudoCommand + " : sudo 명령어 입력 중 오류 발생" + "\ninput stream:" + resultString() + "\nerror stream:" + errorResultString());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

import com.whoz_in.network_log.common.util.RequesterInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
@RequestMapping("/api/v1")
@RequiredArgsConstructor
Expand All @@ -17,7 +19,7 @@ public class IpAddressController {
@GetMapping("/ip")
public ResponseEntity<String> getMac() {
String ip = requesterInfo.getIp();
System.out.println("Requester Info : " + ip);
log.info("Requester Info : " + ip);
return ResponseEntity.ok(ip);
}

Expand Down

0 comments on commit 8b0b163

Please sign in to comment.