This post digs into the bootstrap process of an IntelliJ-based IDE server inside a Gitpod workspace. It’s also a development note during the https://github.com/gitpod-io/gitpod/pull/10175 and helps me understand Gitpod workspace & IntelliJ Platform better.

Some background information:

TOC


Let’s start a Gitpod workspace from the JetBrains Gateway plugin and open up a terminal and check what's running inside the remote workspace:

gitpod /workspace/spring-petclinic (master) $ ps -afx -o pid,ppid,command
    PID    PPID COMMAND
      1       0 supervisor init
     36       1 supervisor run
     50      36  \\_ /ide-desktop/status 24000 intellij Open in IntelliJ IDEA
   1109      50  |   \\_ /bin/sh /ide-desktop/backend/bin/remote-dev-server.sh run /workspace/spring-petclinic
   1117    1109  |       \\_ /bin/sh /ide-desktop/backend/plugins/remote-dev-server/bin/launcher.sh idea.sh IU IDEA idea -Xmx750m run /workspace/spring-petclinic
   1236    1117  |           \\_ /bin/sh /ide-desktop/backend/bin/idea.sh cwmHostNoLobby /workspace/spring-petclinic
   1251    1236  |               \\_ /lib64/ld-linux-x86-64.so.2 --library-path /ide-desktop/backend/plugins/remote-dev-server/selfcontained/lib /workspace/.cache (...truncated)
   1353    1251  |                   \\_ /ide-desktop/backend/bin/fsnotifier
   1389    1251  |                   \\_ /bin/bash --rcfile /ide-desktop/backend/plugins/terminal/jediterm-bash.in -i
   2144    1251  |                   \\_ /bin/bash --rcfile /ide-desktop/backend/plugins/terminal/jediterm-bash.in -i
   2404    2144  |                       \\_ gp tasks attach
   ...

Untitled

This post covers the Remote part only, the Local part will be covered later


1. Supervisor

supervisor is the init process and service manager for Gitpod workspace (similar to systemd or tini) and it runs as root with PID1. supervisor spawns and runs the ide process defined in a JSON config file (src file):

{
    "entrypoint": "/ide-desktop/startup.sh",
    "entrypointArgs": [ "{DESKTOPIDEPORT}", "intellij", "Open in IntelliJ IDEA" ],
    "readinessProbe": {
        "type": "http",
        "http": {
            "path": "/status"
        }
      }
}

The notable part is entrypoint and readinessProbe, which gives hints on how the IDE process is started and managed.

startup.sh script (src file):

# kill background jobs when the script exits
trap "jobs -p | xargs -r kill" SIGINT SIGTERM EXIT
unset JAVA_TOOL_OPTIONS
exec /ide-desktop/status "$@"

A child process (/ide-desktop/status) is spawned by exec command, and it replaces the current shell. That's the reason why we didn't see start.sh in the process tree. So let's move forward to /ide-desktop/status.