Page 1 of 1

Better way for headless server to exit gracefully

Posted: Fri Apr 17, 2026 2:02 pm
by Thremtopod
I'm using Factorio's headless server running in Docker for automated testing of my mods (repo here). It's a bit hacky, but it works great; and the best workflow I've found is to create a scenario for each test suite (putting all the test functions in the scenario's control.lua). The only issue I haven't been able to solve is getting Factorio to exit gracefully when the test suite is finished. This is my hacky solution:

Code: Select all

timeout -f "$TIMEOUT" bash -c '/opt/factorio/bin/x64/factorio \
    --start-server-load-scenario "$SCENARIO_NAME" \
    --mod-directory "$MODS" \
    --server-settings "$CONFIG/server-settings.json" 2>&1 | \
while IFS= read -r line; do
    printf "%s\\n" "$line"
    case "$line" in
        (*__FUNIT__*====END====*)
            echo "FUNIT end signal detected"
            touch "$EARLY_SUCCESS_FLAG"
            pkill -TERM -f ".*factorio.*--start-server-load-scenario" 2>/dev/null || true
            exit 0
            ;;
    esac
done
exit ${PIPESTATUS[0]}'

EXIT_CODE=$?
if [ -f "$EARLY_SUCCESS_FLAG" ]; then
    rm -f "$EARLY_SUCCESS_FLAG"
    EXIT_CODE=0
fi
I had a few ideas for how this could work:
  • Add a command line parameter to tell Factorio to exit when game state is set to game_finished = true
  • Add a command line parameter to specify some other way for a script to signal the game to exit
  • Change to --until-tick parameter to work with more options (does not currently work with --start-server-load-scenario)
It's also worth noting that while my preferred way of running tests is using --start-server-load-scenario, other ways like --start-server are also effective. So it would be good for flexibility for any solution to work broadly with multiple ways of starting a headless server (given implementation constraints of course).

Re: Better way for headless server to exit gracefully

Posted: Tue Apr 21, 2026 4:16 pm
by Thremtopod
Another idea is an option to run a simulation directly from the command line, which would exit when it's finished (based on length). This would also come with the extra benefit of being able to use game.simulation.create_test_player as part of a test. But now this request is starting to sound like a lot of scope creep...