OSRM (Open Source Routing Machine) ist eine Open-Source Routing-Engine für Straßennetze auf Basis von OpenStreetMap-Daten (OSM). Das Projekt ist in C++ implementiert und auf sehr schnelle Routenberechnung ausgelegt. Im Unterschied zu Geocodern wie Nominatim übersetzt OSRM keine Adressen in Koordinaten, sondern berechnet Wege zwischen bereits bekannten Koordinaten auf dem zugrunde liegenden Straßennetz.
OSRM kann sowohl als HTTP-Dienst betrieben als auch als Bibliothek genutzt werden. Die offizielle Dokumentation beschreibt dafür eine HTTP-API, eine C++ Bibliothek namens libosrm sowie einen Node.js Wrapper.
Demo https://router.project-osrm.org/route/v1/driving/16.3725,48.2082;16.3738,48.2100?overview=false
import requests def get_route(start_lon: float, start_lat: float, end_lon: float, end_lat: float) -> dict: url = ( f"http://localhost:5000/route/v1/driving/" f"{start_lon},{start_lat};{end_lon},{end_lat}" ) params = { "overview": "false", "steps": "true" } response = requests.get(url, params=params, timeout=10) response.raise_for_status() return response.json() result = get_route(16.37208, 48.20849, 16.37382, 48.20672) route = result["routes"][0] print("Distanz in Metern:", route["distance"]) print("Dauer in Sekunden:", route["duration"])
OSRM verarbeitet OpenStreetMap-Daten in einem Vorbereitungsprozess und erzeugt daraus speziell optimierte Routing-Datenstrukturen. Laut Projektseite unterstützt OSRM den Import von OSM-Daten (siehe PBF), ist für sehr große Netze ausgelegt und bietet vorkonfigurierte Profile für Auto, Fahrrad und Fußweg. Das Routing-Verhalten kann über Profile angepasst werden.
Für die Datenvorbereitung werden Werkzeuge wie osrm-extract, osrm-contract, osrm-partition und osrm-customize verwendet. Welche Schritte nötig sind, hängt vom gewählten Routing-Algorithmus ab. Die Dokumentation und projektnahen Quellen unterscheiden dabei insbesondere zwischen CH (Contraction Hierarchies) und MLD (Multi-Level Dijkstra).
Die HTTP-API von OSRM verwendet in Version 5.x das Protokoll v1. Die zentralen Dienste sind:
Der Dienst route berechnet die schnellste Route zwischen Koordinaten auf Basis des gewählten Profils, zum Beispiel driving, bike oder foot. Er liefert unter anderem Distanz, Dauer und auf Wunsch Geometrien und Turn-by-Turn-Informationen.
Beispiel:
/route/v1/driving/16.37208,48.20849;16.37382,48.20672?overview=false
Der Dienst nearest ordnet eine Koordinate dem nächstgelegenen Straßensegment zu. Das ist nützlich, um GPS-Punkte auf das Routing-Netz zu „snappen“.
Der Dienst table berechnet eine Matrix aus Fahrzeiten oder Distanzen zwischen mehreren Koordinaten. Laut API-Dokumentation liefert table bei Distanzen nicht die Luftlinie, sondern die Distanzen der jeweils schnellsten Routen im Straßennetz.
Der Dienst match dient dem Map-Matching. Dabei werden GPS-Spuren auf wahrscheinliche Straßenverläufe abgebildet. Das ist besonders für Tracking- oder Flottenanwendungen relevant.
Der Dienst trip berechnet eine sinnvolle Reihenfolge für mehrere Wegpunkte. Das Problem ist verwandt mit dem Traveling-Salesman-Problem und eignet sich für einfache Tourenplanung.
Der Dienst tile stellt Kachelinformationen für Debugging und Visualisierung bereit.
Das Routing-Verhalten von OSRM wird durch Lua-Profile bestimmt. Das Profil wird bereits bei der Datenaufbereitung festgelegt und definiert, welche Straßen befahrbar sind und wie Geschwindigkeiten, Einschränkungen oder Präferenzen behandelt werden. Die offiziellen Beispiele nennen insbesondere car, bike und foot.
Dadurch lässt sich OSRM an verschiedene Einsatzszenarien anpassen, etwa für klassische Autonavigation, Fahrrad-Routing oder Fußwege. Eigene Profile sind möglich, wenn projektspezifische Regeln benötigt werden. Diese Schlussfolgerung ergibt sich aus der dokumentierten Profil-Logik und der Lua-basierten Konfiguration.
Non persistent
#!/usr/bin/env bash set -euo pipefail PBF_PATH="${1:-}" PROFILE="${2:-car}" PORT="${PORT:-5000}" CONTAINER_NAME="${CONTAINER_NAME:-osrm-demo}" WORKDIR="${WORKDIR:-/tmp/osrm-demo-data}" need_root() { if [[ "${EUID}" -ne 0 ]]; then echo "Bitte mit sudo starten:" echo " sudo bash setup-osrm.sh /pfad/zur/datei.osm.pbf car" exit 1 fi } check_args() { if [[ -z "$PBF_PATH" ]]; then echo "Fehler: Bitte Pfad zur .osm.pbf angeben." exit 1 fi if [[ ! -f "$PBF_PATH" ]]; then echo "Fehler: Datei nicht gefunden: $PBF_PATH" exit 1 fi case "$PROFILE" in car) LUA_PROFILE="/opt/car.lua" ;; bike) LUA_PROFILE="/opt/bicycle.lua" ;; foot) LUA_PROFILE="/opt/foot.lua" ;; *) echo "Fehler: Unbekanntes Profil '$PROFILE'. Erlaubt: car | bike | foot" exit 1 ;; esac export LUA_PROFILE } install_docker_if_missing() { if command -v docker >/dev/null 2>&1; then echo "Docker ist bereits vorhanden: $(docker --version || true)" return fi echo "==> Docker wird installiert" apt-get update apt-get install -y ca-certificates curl install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc chmod a+r /etc/apt/keyrings/docker.asc . /etc/os-release echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu ${UBUNTU_CODENAME:-$VERSION_CODENAME} stable" \ > /etc/apt/sources.list.d/docker.list apt-get update apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin if command -v service >/dev/null 2>&1; then service docker start || true fi if [[ -n "${SUDO_USER:-}" ]]; then usermod -aG docker "$SUDO_USER" || true fi } start_docker_if_needed() { if docker info >/dev/null 2>&1; then echo "Docker läuft bereits." return fi echo "==> Docker-Daemon wird gestartet" if command -v service >/dev/null 2>&1; then service docker start || true fi for _ in $(seq 1 20); do if docker info >/dev/null 2>&1; then echo "Docker läuft." return fi sleep 1 done echo "Fehler: Docker ist installiert, aber der Daemon läuft nicht." exit 1 } prepare_paths() { PBF_ABS="$(readlink -f "$PBF_PATH")" PBF_BASENAME="$(basename "$PBF_ABS")" PBF_NAME="${PBF_BASENAME%.osm.pbf}" mkdir -p "$WORKDIR" export PBF_ABS PBF_BASENAME PBF_NAME } cleanup_old_files() { echo "==> Alte OSRM-Dateien entfernen in $WORKDIR" find "$WORKDIR" -maxdepth 1 -type f \( \ -name "${PBF_NAME}.osrm*" -o \ -name "${PBF_NAME}.timestamp" -o \ -name "${PBF_BASENAME}" \ \) -print -delete || true if docker ps -a --format '{{.Names}}' | grep -qx "$CONTAINER_NAME"; then echo "==> Alten Container entfernen: $CONTAINER_NAME" docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true fi } prepare_input_file() { echo "==> Kopiere Eingabedatei nach $WORKDIR" cp -f "$PBF_ABS" "$WORKDIR/$PBF_BASENAME" } run_osrm_pipeline() { echo "==> Eingabedatei: $PBF_ABS" echo "==> Arbeitsverzeichnis: $WORKDIR" echo "==> Profil: $PROFILE" echo "==> Port: $PORT" echo "==> OSRM-Image laden" docker pull osrm/osrm-backend echo "==> osrm-extract" docker run --rm -t \ -v "$WORKDIR:/data" \ osrm/osrm-backend \ osrm-extract -p "$LUA_PROFILE" "/data/$PBF_BASENAME" echo "==> osrm-partition" docker run --rm -t \ -v "$WORKDIR:/data" \ osrm/osrm-backend \ osrm-partition "/data/${PBF_NAME}.osrm" echo "==> osrm-customize" docker run --rm -t \ -v "$WORKDIR:/data" \ osrm/osrm-backend \ osrm-customize "/data/${PBF_NAME}.osrm" echo "==> osrm-routed starten" docker run -d \ --name "$CONTAINER_NAME" \ -p "$PORT:5000" \ -v "$WORKDIR:/data" \ osrm/osrm-backend \ osrm-routed --algorithm mld "/data/${PBF_NAME}.osrm" >/dev/null } print_done() { echo echo "Fertig." echo "Test:" echo " http://localhost:${PORT}/route/v1/driving/16.3725,48.2082;16.3370,48.1980?overview=false" echo echo "Logs:" echo " sudo docker logs -f $CONTAINER_NAME" echo echo "Stoppen:" echo " sudo docker rm -f $CONTAINER_NAME" } need_root check_args install_docker_if_missing start_docker_if_needed prepare_paths cleanup_old_files prepare_input_file run_osrm_pipeline print_done
sudo bash setup-osrm.sh wien.osm.pbf car
curl "https://download.geofabrik.de/europe/austria-latest.osm.pbf" -o austria-latest.osm.pbf
#!/usr/bin/env bash set -euo pipefail COMMAND="${1:-}" PBF_PATH="${2:-}" PROFILE="${3:-car}" PORT="${PORT:-5000}" CONTAINER_NAME="${CONTAINER_NAME:-osrm-demo}" WORKDIR="${WORKDIR:-/var/lib/osrm}" IMAGE="${IMAGE:-osrm/osrm-backend}" need_root() { if [[ "${EUID}" -ne 0 ]]; then echo "Bitte mit sudo starten." echo "Beispiele:" echo " sudo bash osrm-manager.sh build /pfad/austria-latest.osm.pbf car" echo " sudo bash osrm-manager.sh start /pfad/austria-latest.osm.pbf car" exit 1 fi } usage() { cat <<EOF Verwendung: sudo bash osrm-manager.sh build /pfad/datei.osm.pbf [car|bike|foot] sudo bash osrm-manager.sh start /pfad/datei.osm.pbf [car|bike|foot] sudo bash osrm-manager.sh stop sudo bash osrm-manager.sh restart /pfad/datei.osm.pbf [car|bike|foot] sudo bash osrm-manager.sh status sudo bash osrm-manager.sh logs sudo bash osrm-manager.sh url [car|bike|foot] Umgebungsvariablen: PORT=5000 CONTAINER_NAME=osrm-demo WORKDIR=/var/lib/osrm IMAGE=osrm/osrm-backend Hinweis: Für jedes Profil werden eigene Daten verwendet: /var/lib/osrm/car /var/lib/osrm/bike /var/lib/osrm/foot EOF } check_profile() { case "$PROFILE" in car) LUA_PROFILE="/opt/car.lua" SERVICE_MODE="driving" ;; bike) LUA_PROFILE="/opt/bicycle.lua" SERVICE_MODE="cycling" ;; foot) LUA_PROFILE="/opt/foot.lua" SERVICE_MODE="walking" ;; *) echo "Fehler: Unbekanntes Profil '$PROFILE'. Erlaubt: car | bike | foot" exit 1 ;; esac export LUA_PROFILE SERVICE_MODE } install_docker_if_missing() { if command -v docker >/dev/null 2>&1; then echo "Docker vorhanden: $(docker --version || true)" return fi echo "==> Docker wird installiert" apt-get update apt-get install -y ca-certificates curl install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc chmod a+r /etc/apt/keyrings/docker.asc . /etc/os-release echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu ${UBUNTU_CODENAME:-$VERSION_CODENAME} stable" \ > /etc/apt/sources.list.d/docker.list apt-get update apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin systemctl enable docker || true systemctl start docker || true if [[ -n "${SUDO_USER:-}" ]]; then usermod -aG docker "$SUDO_USER" || true fi } start_docker_if_needed() { if docker info >/dev/null 2>&1; then echo "Docker läuft." return fi echo "==> Docker-Daemon wird gestartet" systemctl enable docker || true systemctl start docker || true for _ in $(seq 1 20); do if docker info >/dev/null 2>&1; then echo "Docker läuft." return fi sleep 1 done echo "Fehler: Docker ist installiert, aber der Daemon läuft nicht." exit 1 } check_pbf_arg() { if [[ -z "$PBF_PATH" ]]; then echo "Fehler: Bitte Pfad zur .osm.pbf angeben." exit 1 fi if [[ ! -f "$PBF_PATH" ]]; then echo "Fehler: Datei nicht gefunden: $PBF_PATH" exit 1 fi } prepare_paths() { check_pbf_arg PBF_ABS="$(readlink -f "$PBF_PATH")" PBF_BASENAME="$(basename "$PBF_ABS")" PBF_NAME="${PBF_BASENAME%.osm.pbf}" PROFILE_DIR="${WORKDIR}/${PROFILE}" DATASET_FILE="${PROFILE_DIR}/${PBF_BASENAME}" OSRM_BASE="${PROFILE_DIR}/${PBF_NAME}.osrm" PROFILE_CONTAINER_NAME="${CONTAINER_NAME}-${PROFILE}" mkdir -p "$PROFILE_DIR" export PBF_ABS PBF_BASENAME PBF_NAME PROFILE_DIR DATASET_FILE OSRM_BASE PROFILE_CONTAINER_NAME } require_prepared_dataset() { local missing=0 local required=( "${OSRM_BASE}" "${OSRM_BASE}.ramIndex" "${OSRM_BASE}.fileIndex" "${OSRM_BASE}.edges" "${OSRM_BASE}.geometry" "${OSRM_BASE}.turn_weight_penalties" "${OSRM_BASE}.turn_duration_penalties" "${OSRM_BASE}.datasource_names" "${OSRM_BASE}.names" "${OSRM_BASE}.properties" "${OSRM_BASE}.icd" ) for f in "${required[@]}"; do if [[ ! -f "$f" ]]; then echo "Fehlt: $f" missing=1 fi done if [[ "$missing" -ne 0 ]]; then echo echo "Fehler: OSRM-Datensatz unvollständig." echo "Führe zuerst aus:" echo " sudo bash osrm-manager.sh build \"$PBF_ABS\" \"$PROFILE\"" exit 1 fi } remove_container_if_exists() { if docker ps -a --format '{{.Names}}' | grep -qx "$PROFILE_CONTAINER_NAME"; then echo "==> Entferne alten Container: $PROFILE_CONTAINER_NAME" docker rm -f "$PROFILE_CONTAINER_NAME" >/dev/null 2>&1 || true fi } copy_input_if_needed() { if [[ -f "$DATASET_FILE" ]]; then local src_size dst_size src_size="$(stat -c '%s' "$PBF_ABS")" dst_size="$(stat -c '%s' "$DATASET_FILE" 2>/dev/null || echo 0)" if [[ "$src_size" == "$dst_size" ]]; then echo "==> PBF bereits vorhanden: $DATASET_FILE" return fi fi echo "==> Kopiere Eingabedatei nach $PROFILE_DIR" cp -f "$PBF_ABS" "$DATASET_FILE" } cleanup_previous_dataset_files() { echo "==> Entferne alte OSRM-Dateien für $PBF_NAME in $PROFILE_DIR" find "$PROFILE_DIR" -maxdepth 1 -type f \ \( -name "${PBF_NAME}.osrm*" -o -name "${PBF_NAME}.timestamp" \) \ -print -delete || true } build_dataset() { echo "==> Image laden" docker pull "$IMAGE" copy_input_if_needed cleanup_previous_dataset_files echo "==> osrm-extract ($PROFILE)" docker run --rm -t \ -v "$PROFILE_DIR:/data" \ "$IMAGE" \ osrm-extract -p "$LUA_PROFILE" "/data/$PBF_BASENAME" echo "==> osrm-partition" docker run --rm -t \ -v "$PROFILE_DIR:/data" \ "$IMAGE" \ osrm-partition "/data/${PBF_NAME}.osrm" echo "==> osrm-customize" docker run --rm -t \ -v "$PROFILE_DIR:/data" \ "$IMAGE" \ osrm-customize "/data/${PBF_NAME}.osrm" echo "==> Build abgeschlossen" } start_container() { require_prepared_dataset remove_container_if_exists echo "==> Starte Container $PROFILE_CONTAINER_NAME auf Port $PORT" docker run -d \ --restart unless-stopped \ --name "$PROFILE_CONTAINER_NAME" \ -p "$PORT:5000" \ -v "$PROFILE_DIR:/data" \ "$IMAGE" \ osrm-routed --algorithm mld "/data/${PBF_NAME}.osrm" >/dev/null echo echo "Läuft." echo "Test-URL:" echo " http://localhost:${PORT}/route/v1/${SERVICE_MODE}/16.3725,48.2082;16.3738,48.2100?overview=false" } stop_container() { local found=0 for p in car bike foot; do local name="${CONTAINER_NAME}-${p}" if docker ps -a --format '{{.Names}}' | grep -qx "$name"; then echo "==> Stoppe und entferne $name" docker rm -f "$name" >/dev/null 2>&1 || true found=1 fi done if [[ "$found" -eq 0 ]]; then echo "Kein passender Container gefunden." fi } show_status() { echo "==> Docker" systemctl is-active docker || true echo echo "==> Container" docker ps -a --filter "name=^${CONTAINER_NAME}-" --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}' echo echo "==> Datensätze" for p in car bike foot; do local dir="${WORKDIR}/${p}" if [[ -d "$dir" ]]; then echo "--- $dir" ls -1 "$dir" | sed 's/^/ /' || true fi done } show_logs() { local found=0 for p in car bike foot; do local name="${CONTAINER_NAME}-${p}" if docker ps -a --format '{{.Names}}' | grep -qx "$name"; then found=1 echo "==> Logs: $name" docker logs --tail 100 "$name" echo fi done if [[ "$found" -eq 0 ]]; then echo "Kein passender Container gefunden." fi } print_url() { check_profile echo "http://localhost:${PORT}/route/v1/${SERVICE_MODE}/16.3725,48.2082;16.3738,48.2100?overview=false" } main() { need_root case "$COMMAND" in build) check_profile install_docker_if_missing start_docker_if_needed prepare_paths build_dataset ;; start) check_profile install_docker_if_missing start_docker_if_needed prepare_paths start_container ;; restart) check_profile install_docker_if_missing start_docker_if_needed prepare_paths remove_container_if_exists start_container ;; stop) install_docker_if_missing start_docker_if_needed stop_container ;; status) install_docker_if_missing start_docker_if_needed show_status ;; logs) install_docker_if_missing start_docker_if_needed show_logs ;; url) print_url ;; *) usage exit 1 ;; esac } main "$@"
sudo bash setup-osrm.sh build /home/austria-latest.osm.pbf foot sudo bash setup-osrm.sh start /home/austria-latest.osm.pbf foot sudo bash setup-osrm.sh status sudo bash osrm-manager.sh stop sudo bash osrm-manager.sh logs
Nur foot, auf WAF getestet)
#!/usr/bin/env bash set -Eeuo pipefail OSRM_DIR="/opt/osrm-austria" DATA_DIR="${OSRM_DIR}/data" SERVICE_FILE="/etc/systemd/system/osrm-austria.service" PBF_URL="https://download.geofabrik.de/europe/austria-latest.osm.pbf" PBF_FILE="${DATA_DIR}/austria-latest.osm.pbf" CONTAINER_IMAGE="ghcr.io/project-osrm/osrm-backend:latest" CONTAINER_NAME="osrm-austria" PORT="5000" DATASET="austria-latest" ROUTED_PATH="/data/${DATASET}" log() { echo "[+] $*" } fail() { echo "[!] FEHLER: $*" >&2 exit 1 } require_root() { [[ "${EUID}" -eq 0 ]] || fail "Bitte als root ausführen." } on_error() { local exit_code=$? echo echo "[!] Das Skript ist fehlgeschlagen. Exit-Code: ${exit_code}" echo "[!] Diagnose:" echo " free -h" echo " df -h" echo " ls -lh ${DATA_DIR}" echo " journalctl -u osrm-austria.service -n 100 --no-pager" exit "${exit_code}" } trap on_error ERR install_packages() { log "Installiere Basis-Pakete ..." apt-get update apt-get install -y \ ca-certificates \ curl \ gnupg \ lsb-release \ wget \ systemd } install_docker() { if command -v docker >/dev/null 2>&1; then log "Docker ist bereits installiert." systemctl enable docker >/dev/null 2>&1 || true systemctl start docker return fi log "Installiere Docker ..." install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc chmod a+r /etc/apt/keyrings/docker.asc cat > /etc/apt/sources.list.d/docker.list <<EOF deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable EOF apt-get update apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin systemctl enable docker systemctl start docker } prepare_dirs() { log "Erzeuge Verzeichnisse ..." mkdir -p "${DATA_DIR}" } download_data() { if [[ -s "${PBF_FILE}" ]]; then log "PBF-Datei existiert bereits: ${PBF_FILE}" return fi log "Lade Österreich-OSM-Daten herunter ..." wget -O "${PBF_FILE}" "${PBF_URL}" [[ -s "${PBF_FILE}" ]] || fail "Download fehlgeschlagen: ${PBF_FILE} fehlt oder ist leer." } pull_image() { log "Lade OSRM-Container-Image ..." docker pull "${CONTAINER_IMAGE}" } cleanup_old_artifacts() { log "Entferne alte OSRM-Artefakte ..." rm -f \ "${DATA_DIR}/${DATASET}.osrm"* \ "${DATA_DIR}/${DATASET}.osrm."* \ "${DATA_DIR}/${DATASET}.osrm" [[ -s "${PBF_FILE}" ]] || fail "PBF-Datei fehlt nach Cleanup: ${PBF_FILE}" } run_extract() { log "Starte osrm-extract (walking, 1 Thread) ..." OMP_NUM_THREADS=1 docker run --rm -t \ -e OMP_NUM_THREADS=1 \ -v "${DATA_DIR}:/data" \ "${CONTAINER_IMAGE}" \ osrm-extract \ -p /opt/foot.lua \ "${ROUTED_PATH}.osm.pbf" [[ -f "${DATA_DIR}/${DATASET}.osrm.ebg" ]] || fail "osrm-extract unvollständig: ${DATASET}.osrm.ebg fehlt." [[ -f "${DATA_DIR}/${DATASET}.osrm.properties" ]] || fail "osrm-extract unvollständig: ${DATASET}.osrm.properties fehlt." [[ -f "${DATA_DIR}/${DATASET}.osrm.timestamp" ]] || fail "osrm-extract unvollständig: ${DATASET}.osrm.timestamp fehlt." } run_partition() { log "Starte osrm-partition ..." docker run --rm -t \ -v "${DATA_DIR}:/data" \ "${CONTAINER_IMAGE}" \ osrm-partition \ "${ROUTED_PATH}" [[ -f "${DATA_DIR}/${DATASET}.osrm.partition" ]] || fail "osrm-partition unvollständig: ${DATASET}.osrm.partition fehlt." } run_customize() { log "Starte osrm-customize ..." docker run --rm -t \ -v "${DATA_DIR}:/data" \ "${CONTAINER_IMAGE}" \ osrm-customize \ "${ROUTED_PATH}" [[ -f "${DATA_DIR}/${DATASET}.osrm.cells" ]] || fail "osrm-customize unvollständig: ${DATASET}.osrm.cells fehlt." [[ -f "${DATA_DIR}/${DATASET}.osrm.mldgr" ]] || fail "osrm-customize unvollständig: ${DATASET}.osrm.mldgr fehlt." } create_service() { log "Erzeuge systemd-Service ..." cat > "${SERVICE_FILE}" <<EOF [Unit] Description=OSRM Austria Walking Server After=docker.service network-online.target Requires=docker.service Wants=network-online.target [Service] Type=simple Restart=always RestartSec=5 TimeoutStartSec=0 ExecStartPre=-/usr/bin/docker rm -f ${CONTAINER_NAME} ExecStart=/usr/bin/docker run --rm --name ${CONTAINER_NAME} -p ${PORT}:5000 -v ${DATA_DIR}:/data ${CONTAINER_IMAGE} osrm-routed --algorithm mld ${ROUTED_PATH} ExecStop=/usr/bin/docker stop ${CONTAINER_NAME} [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable osrm-austria.service } start_service() { log "Starte OSRM-Service ..." systemctl restart osrm-austria.service sleep 3 systemctl --no-pager --full status osrm-austria.service } show_result() { echo log "Fertig." echo echo "Test:" echo "curl 'http://127.0.0.1:${PORT}/route/v1/walking/16.3725,48.2082;16.3738,48.2100?overview=false'" echo echo "Status:" echo "systemctl status osrm-austria.service --no-pager -l" echo echo "Logs:" echo "journalctl -u osrm-austria.service -f" } main() { require_root install_packages install_docker prepare_dirs download_data pull_image cleanup_old_artifacts run_extract run_partition run_customize create_service start_service show_result } main "$@"
#!/usr/bin/env bash set -Eeuo pipefail OSRM_BASE="/opt/osrm-austria" SERVICE_DIR="/etc/systemd/system" PBF_URL="https://download.geofabrik.de/europe/austria-latest.osm.pbf" CONTAINER_IMAGE="ghcr.io/project-osrm/osrm-backend:latest" declare -A PROFILE_LUA=( [driving]="/opt/car.lua" [bicycle]="/opt/bicycle.lua" [foot]="/opt/foot.lua" ) declare -A PROFILE_PORT=( [driving]="5000" [bicycle]="5001" [foot]="5002" ) log() { echo "[+] $*"; } fail() { echo "[!] FEHLER: $*" >&2; exit 1; } require_root() { [[ "${EUID}" -eq 0 ]] || fail "Bitte als root ausführen." } install_packages() { apt-get update apt-get install -y ca-certificates curl gnupg lsb-release wget systemd } install_docker() { if command -v docker >/dev/null 2>&1; then systemctl enable docker >/dev/null 2>&1 || true systemctl start docker return fi install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc chmod a+r /etc/apt/keyrings/docker.asc cat > /etc/apt/sources.list.d/docker.list <<EOF deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable EOF apt-get update apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin systemctl enable docker systemctl start docker } prepare_profile_dir() { local profile="$1" mkdir -p "${OSRM_BASE}/${profile}" } download_pbf() { local profile="$1" local pbf_file="${OSRM_BASE}/${profile}/austria-latest.osm.pbf" if [[ ! -s "${pbf_file}" ]]; then wget -O "${pbf_file}" "${PBF_URL}" fi [[ -s "${pbf_file}" ]] || fail "PBF fehlt für ${profile}" } build_profile() { local profile="$1" local lua="${PROFILE_LUA[$profile]}" local dir="${OSRM_BASE}/${profile}" log "Baue Profil ${profile} ..." rm -f "${dir}/austria-latest.osrm"* docker run --rm -t \ -e OMP_NUM_THREADS=1 \ -v "${dir}:/data" \ "${CONTAINER_IMAGE}" \ osrm-extract -p "${lua}" /data/austria-latest.osm.pbf docker run --rm -t \ -v "${dir}:/data" \ "${CONTAINER_IMAGE}" \ osrm-partition /data/austria-latest.osrm docker run --rm -t \ -v "${dir}:/data" \ "${CONTAINER_IMAGE}" \ osrm-customize /data/austria-latest.osrm [[ -f "${dir}/austria-latest.osrm.cells" ]] || fail "Build fehlgeschlagen für ${profile}" } create_service() { local profile="$1" local port="${PROFILE_PORT[$profile]}" local dir="${OSRM_BASE}/${profile}" local service="${SERVICE_DIR}/osrm-austria-${profile}.service" local container="osrm-austria-${profile}" cat > "${service}" <<EOF [Unit] Description=OSRM Austria ${profile} Server After=docker.service network-online.target Requires=docker.service Wants=network-online.target [Service] Type=simple Restart=always RestartSec=5 TimeoutStartSec=0 ExecStartPre=-/usr/bin/docker rm -f ${container} ExecStart=/usr/bin/docker run --rm --name ${container} -p ${port}:5000 -v ${dir}:/data ${CONTAINER_IMAGE} osrm-routed --algorithm mld /data/austria-latest.osrm ExecStop=/usr/bin/docker stop ${container} [Install] WantedBy=multi-user.target EOF } start_service() { local profile="$1" systemctl daemon-reload systemctl enable "osrm-austria-${profile}.service" systemctl restart "osrm-austria-${profile}.service" } main() { require_root install_packages install_docker docker pull "${CONTAINER_IMAGE}" for profile in driving bicycle foot; do prepare_profile_dir "${profile}" download_pbf "${profile}" build_profile "${profile}" create_service "${profile}" start_service "${profile}" done echo echo "Fertig." echo "driving: http://127.0.0.1:5000" echo "bicycle: http://127.0.0.1:5001" echo "foot: http://127.0.0.1:5002" } main "$@"