Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FIX] output stream을 건들기 전에 프로세스가 종료됐는지 확인하는 로직 추가 (broken pipe 방지) #95

Merged
merged 5 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading