πŸ“Œ 컨텐츠 배포 μžλ™ν™” - SH 파일 μ‹€ν–‰

πŸ“ κ°œμš”

Shell(SH) νŒŒμΌμ„ μ‹€ν–‰ν•˜μ—¬ 컨텐츠λ₯Ό μžλ™μœΌλ‘œ λ°°ν¬ν•˜λŠ” κΈ°λŠ₯을 κ°œλ°œν–ˆλ‹€.

SH νŒŒμΌμ„ λ™μ μœΌλ‘œ 읽고 μ‹€ν–‰ν•˜μ—¬ μ„œλ²„μ— 컨텐츠λ₯Ό λ°°ν¬ν•˜λŠ” 방식이며, 이λ₯Ό 톡해 배포 ν”„λ‘œμ„ΈμŠ€λ₯Ό κ°„μ†Œν™”ν•  수 μžˆλ‹€.


πŸš€ κ΅¬ν˜„ λ‚΄μš©

1. 배포 API κ΅¬ν˜„ (Spring Boot)

배포 μš”μ²­μ΄ λ“€μ–΄μ˜€λ©΄ SH νŒŒμΌμ„ μ‹€ν–‰ν•˜λŠ” APIλ₯Ό μž‘μ„±ν–ˆλ‹€.

βœ… μ£Όμš” κΈ°λŠ₯

βœ… μ½”λ“œ μ˜ˆμ‹œ

@PostMapping("content/deploy")
public ResponseEntity<GResponse> deployContent(HttpServletResponse response, @RequestBody DeployParam param) {
    response.setHeader("Job-Log", "컨텐츠 배포 μ‹€ν–‰");

    String basePath = System.getProperty("user.dir") + "/deploy_scripts/";
    String shFileName = "deploy_" + param.getName() + "_" + param.getProductName() + ".sh";
    File shFile = new File(basePath, shFileName);

    if (!shFile.exists()) {
        log.error("SH 파일이 μ‘΄μž¬ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€: {}", shFile.getAbsolutePath());
        return ResponseEntity.ok(new GResponse("404", "배포에 ν•„μš”ν•œ SH 파일이 μ—†μŠ΅λ‹ˆλ‹€."));
    }

    try {
        ProcessBuilder processBuilder = new ProcessBuilder("/bin/bash", "-c",
            "server_host=\\"" + param.getServerHost().replaceFirst("https?://", "") + "\\" " +
            "server_port=\\"" + param.getServerPort() + "\\" " +
            "bash " + shFile.getAbsolutePath()
        );
        processBuilder.redirectErrorStream(true);

        Process process = processBuilder.start();
        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));

        StringBuilder output = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            output.append(line).append("\\n");
        }

        int exitCode = process.waitFor();
        if (exitCode == 0) {
            log.info("SH 파일 μ‹€ν–‰ 성곡: {}", shFileName);
            return ResponseEntity.ok(new GResponse("0000", "배포 성곡:\\n" + output));
        } else {
            log.error("SH 파일 μ‹€ν–‰ μ‹€νŒ¨ (exitCode: {}): {}", exitCode, shFileName);
            return ResponseEntity.ok(new GResponse("500", "배포 μ‹€νŒ¨:\\n" + output));
        }
    } catch (IOException | InterruptedException e) {
        log.error("SH 파일 μ‹€ν–‰ 쀑 였λ₯˜ λ°œμƒ: {}", shFileName, e);
        return ResponseEntity.ok(new GResponse("500", "SH 파일 μ‹€ν–‰ 쀑 였λ₯˜ λ°œμƒ."));
    }
}


2. ν΄λΌμ΄μ–ΈνŠΈ 배포 μš”μ²­ 처리 (JavaScript)

배포 μš”μ²­μ„ 보낼 수 μžˆλ„λ‘ JavaScript둜 ν΄λΌμ΄μ–ΈνŠΈ μš”μ²­μ„ μ²˜λ¦¬ν–ˆλ‹€.

$("#deploy_content").click(function () {
    let selectedRow = $table.bootstrapTable('getSelections');
    if (selectedRow.length === 0) {
        return alert('배포할 ν•­λͺ©μ„ μ„ νƒν•˜μ„Έμš”.');
    }

    let params = {
        name: selectedRow[0].name,
        product_name: selectedRow[0].product_name,
        server_host: selectedRow[0].server_host,
        server_port: selectedRow[0].server_port.startsWith(":") ? selectedRow[0].server_port : ":" + selectedRow[0].server_port
    };

    if (confirm("λ°°ν¬ν•˜μ‹œκ² μŠ΅λ‹ˆκΉŒ?")) {
        $.post("/api/content/deploy", params, function (response) {
            alert(response.code === '0000' ? "배포 성곡" : "배포 μ‹€νŒ¨: " + response.message);
        });
    }
});


3. Shell Script (SH 파일)