3 minute read

Jenkins workspace

image

์  ํ‚จ์Šค(Jenkins) ์—์„œ๋Š” ๊ฐ๊ฐ์˜ job build process ๋งˆ๋‹ค ๊ณ ์œ ํ•œ workspace ์„ ์ƒ์„ฑํ•˜์—ฌ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

workspace ์—๋Š” build ์‹œ ํ•„์š”ํ•œ ํŒŒ์ผ๋“ค์ด ์ €์žฅ๋˜๋ฉฐ,

์—ฌ๋Ÿฌ ๋ฒˆ์˜ ์‹คํ–‰์—๋„ ๋…๋ฆฝ์ ์ธ ํ™˜๊ฒฝ์—์„œ build ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋„๋ก ์ œ๊ณตํ•ด์ค๋‹ˆ๋‹ค.

workspace ์— ์ ์žฌ๋˜๋Š” ํŒŒ์ผ์˜ ํฌ๊ธฐ๊ฐ€ ํฐ ๊ฒฝ์šฐ,

jenkins server ์˜ disk ๊ฐ€ ๊ฐ€๋“ ์ฐฐ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด,

ํŒŒ์ดํ”„๋ผ์ธ์— cleanWs() ๋ช…๋ น์–ด๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๊ฐ build process ๋งˆ๋‹ค workspace ๋ฅผ ์ง€์›Œ์ฃผ๋Š” ์ž‘์—…์„ ์„ ํ–‰/ํ›„ํ–‰ํ•˜๋„๋ก ์„ค์ •ํ•  ์ˆ˜ ์žˆ์ฃ .

workspace ๋ฅผ ์œ ์ง€ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด cleanWs() ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฉด ๋  ๊ฒƒ๋งŒ ๊ฐ™์ง€๋งŒ,

์‹ค์ œ๋กœ๋Š” ์ผ์ • ์ฃผ๊ธฐ๊ฐ€ ์ง€๋‚˜๋ฉด ์˜ค๋ž˜๋œ workspace ๋Š” ์Šค์Šค๋กœ ์ œ๊ฑฐ๋ฉ๋‹ˆ๋‹ค.

์šด์˜ ํ™˜๊ฒฝ์—์„œ ๋™์ž‘ํ•˜๊ณ  ์žˆ๋˜ jenkins job ์ค‘ ์ผ๋ถ€๋Š” ํŒŒ์ดํ”„๋ผ์ธ์— cleanWs() ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿผ์—๋„ console log ๋ฅผ ๋ณด๋ฉด clean workspace ๋ฅผ ์‹œ๋„ํ•œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ์ฃ .

์™œ ์ด๋ ‡๊ฒŒ ๋™์ž‘ํ•˜๋Š” ์ง€, ์‚ดํŽด๋ณด์•˜์Šต๋‹ˆ๋‹ค.

WorkspaceCleanupThread

์„œ์น˜ํ•ด๋ณด๋‹ˆ ์  ํ‚จ์Šค ์‹œ์Šคํ…œ ๋‚ด์—์„œ ์ฃผ๊ธฐ์ ์œผ๋กœ workspace ๋ฅผ cleanup ํ•˜์—ฌ, ์  ํ‚จ์Šค ์„œ๋ฒ„์˜ disk ๊ณต๊ฐ„์„ ๊ด€๋ฆฌํ•œ๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

๊ด€๋ จ ์„ธ๋ถ€ ๋กœ์ง์€ WorkspaceCleanupThread.java ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

์ฃผ์˜๊นŠ๊ฒŒ ํ™•์ธํ•ด์•ผ ํ•˜๋Š” ๋ถ€๋ถ„์—๋Š” โญ๏ธ์ด๋ชจ์ง€๋ฅผ ๋‹ฌ์•„๋‘์—ˆ์Šต๋‹ˆ๋‹ค.

/**
 * Clean up old left-over workspaces from agents.
 *
 * @author Kohsuke Kawaguchi
 */
@Extension @Symbol("workspaceCleanup")
public class WorkspaceCleanupThread extends AsyncPeriodicWork {
    // ... ์ƒ๋žต ...
    @Override protected void execute(TaskListener listener) throws InterruptedException, IOException {
        if (disabled) { <------ โญ๏ธ
            LOGGER.fine("Disabled. Skipping execution");
            return;
        }
        // ... ์ƒ๋žต ...
        for (TopLevelItem item : j.allItems(TopLevelItem.class)) {
            if (item instanceof ModifiableTopLevelItemGroup) { // no such thing as TopLevelItemGroup, and ItemGroup offers no access to its type parameter
                continue; // children will typically have their own workspaces as subdirectories; probably no real workspace of its own
            }
            listener.getLogger().println("Checking " + item.getFullDisplayName());
            for (Node node : nodes) {
                FilePath ws = node.getWorkspaceFor(item);
                if (ws == null) {
                    continue; // offline, fine
                }
                boolean check;
                try {
                    check = shouldBeDeleted(item, ws, node); <------ โญ๏ธ
                } catch (IOException | InterruptedException x) {
                    Functions.printStackTrace(x, listener.error("Failed to check " + node.getDisplayName()));
                    continue;
                }
                if (check) { <------ โญ๏ธ
                    listener.getLogger().println("Deleting " + ws + " on " + node.getDisplayName());
                    try {
                        ws.deleteRecursive(); <------ โญ๏ธ
                        WorkspaceList.tempDir(ws).deleteRecursive(); <------ โญ๏ธ
                    } catch (IOException | InterruptedException x) {
                        Functions.printStackTrace(x, listener.error("Failed to delete " + ws + " on " + node.getDisplayName()));
                    }
                }
            }
        }
    }

    private boolean shouldBeDeleted(@Nonnull TopLevelItem item, FilePath dir, @Nonnull Node n) throws IOException, InterruptedException {
        // ... ์ƒ๋žต ...
        if(dir.lastModified() + retainForDays * DAY > now) { <------ โญ๏ธ
            LOGGER.log(Level.FINE, "Directory {0} is only {1} old, so not deleting", new Object[] {dir, Util.getTimeSpanString(now-dir.lastModified())});
            return false;
        }
        // ... ์ƒ๋žต ...
        return true;
    }
    
    /**
     * Can be used to disable workspace clean up. <------ โญ๏ธ
     */
    public static boolean disabled = SystemProperties.getBoolean(WorkspaceCleanupThread.class.getName()+".disabled");

    /**
     * How often the clean up should run. This is final as Jenkins will not reflect changes anyway. <------ โญ๏ธ
     */
    public static final int recurrencePeriodHours = SystemProperties.getInteger(WorkspaceCleanupThread.class.getName()+".recurrencePeriodHours", 24);

    /**
     * Number of days workspaces should be retained. <------ โญ๏ธ
     */
    public static int retainForDays = SystemProperties.getInteger(WorkspaceCleanupThread.class.getName()+".retainForDays", 30);
}

์œ„ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ์•Œ ์ˆ˜ ์žˆ๋Š” ์ ์„ ์ •๋ฆฌํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค.

- recurrencePeriodHours ์ฃผ๊ธฐ๋งˆ๋‹ค workspace clean up ์„ ์ˆ˜ํ–‰ (๊ธฐ๋ณธ๊ฐ’: 24 ์‹œ๊ฐ„)
- ์‚ญ์ œํ•ด์•ผ ํ•  workspace ๋ฅผ ํŒ๋‹จํ•˜๋Š” ๊ธฐ์ค€์€, ๋งˆ์ง€๋ง‰ ์ˆ˜์ • ์‹œ๊ฐ„์ด retainForDays ๋ณด๋‹ค ์˜ค๋ž˜๋˜์—ˆ๋Š”์ง€๋ฅผ ์ฒดํฌ (๊ธฐ๋ณธ๊ฐ’: 30 ์ผ)

์  ํ‚จ์Šค job ํŒŒ์ดํ”„๋ผ์ธ์—์„œ cleanWs() ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋”๋ผ๋„, ์  ํ‚จ์Šค ์„œ๋ฒ„์—์„œ workspace ๋ฅผ clean up ํ•˜๋ ค๊ณ  ํ•œ ์ด์œ ๋Š” ์ด์ œ ๋ถ„๋ช…ํ•ด์กŒ์ฃ .

๋งŒ์•ฝ, WorkspaceCleanupThread ์— ์˜ํ•œ workspace clean up ์ด ์ผ์–ด๋‚˜์ง€ ์•Š๋„๋ก ๋ฐฉ์ง€ํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ์š”?

WorkspaceCleanupThread.java ์ฝ”๋“œ๋ฅผ ๋‹ค์‹œ ํ™•์ธํ•ด๋ด…์‹œ๋‹ค.


@Override protected void execute(TaskListener listener) throws InterruptedException, IOException {
  if (disabled) { <------ โญ๏ธ
    LOGGER.fine("Disabled. Skipping execution");
    return;
  }
  // ... ์ƒ๋žต ...
}

    /**
     * Can be used to disable workspace clean up. <------ โญ๏ธ
     */
    public static boolean disabled = SystemProperties.getBoolean(WorkspaceCleanupThread.class.getName()+".disabled");

disabled ๊ฐ’์— ๋”ฐ๋ผ์„œ ๋กœ์ง์ด ์ˆ˜ํ–‰๋˜๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๊ณ , ํ•ด๋‹น ๊ฐ’์€ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌ๋ฐ›์œผ๋ฏ€๋กœ

Jenkins ์‹œ์ž‘ ์‹œ,

-Dhudson.model.WorkspaceCleanupThread.disable=true ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ workspace clean up ์„ ๋น„ํ™œ์„ฑํ™” ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


์ž˜๋ชป๋œ ๋ถ€๋ถ„์ด ์žˆ๋‹ค๋ฉด comment ๋‚จ๊ฒจ์ฃผ์„ธ์š”!


References

Categories:

Updated:

Leave a comment