<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Timer – Serverküche</title><link>https://serverkueche.de/tags/timer/</link><description>Timer – Neueste Beiträge von Serverküche</description><generator>Hugo</generator><language>de-DE</language><managingEditor>feedback@serverkueche.de (Serverküche)</managingEditor><webMaster>feedback@serverkueche.de (Serverküche)</webMaster><copyright>2026 Serverküche</copyright><lastBuildDate>Thu, 03 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://serverkueche.de/tags/timer/index.xml" rel="self" type="application/rss+xml"/><item><title>systemd verstehen: Units, Journal &amp; Timer (statt Cron)</title><link>https://serverkueche.de/tutorials/systemd-grundlagen/</link><pubDate>Thu, 03 Sep 2026 00:00:00 +0000</pubDate><author>feedback@serverkueche.de (Serverküche)</author><guid>https://serverkueche.de/tutorials/systemd-grundlagen/</guid><description>Dienste starten, Logs lesen, Aufgaben planen: Dieser Grundlagen-Guide erklärt systemd an echten Befehlen – inklusive eigenem Dienst und Timer statt Cron.</description><content:encoded><![CDATA[<p>Jeder Dienst auf deinem Server – SSH, Docker, die Firewall – wird von systemd gestartet, überwacht und protokolliert. Wer systemd versteht, kann Ausfälle diagnostizieren, eigene Hintergrundjobs anlegen und geplante Aufgaben sauber automatisieren. Dieser Guide macht dich damit vertraut.</p>
<h2 id="was-bauen-wir">Was bauen wir?</h2>
<p>Kein Dienst, sondern das Werkzeug, mit dem <em>alle</em> Dienste laufen: <strong>systemd</strong> (hier v257 auf Debian 13). Am Ende kannst du Dienste starten, stoppen und beim Booten aktivieren, ihre Logs mit <code>journalctl</code> lesen, einen <strong>eigenen Dienst</strong> als Unit-Datei anlegen und einen <strong>Timer</strong> bauen, der Cron ersetzt – mit dem entscheidenden Vorteil, dass er verpasste Läufe nachholen kann.</p>
<h2 id="voraussetzungen">Voraussetzungen</h2>
<ul>
<li>Ein Linux-Server mit systemd (jedes moderne Debian/Ubuntu – dein <a href="/tutorials/erste-schritte-netcup-vps/">netcup-VPS</a>)</li>
<li>Root- oder <code>sudo</code>-Zugang (siehe <a href="/tutorials/linux-benutzer-und-rechte/">Benutzer &amp; Rechte</a>)</li>
<li>Vertrautheit mit den <a href="/tutorials/wichtigste-terminal-befehle/">wichtigsten Terminal-Befehlen</a></li>
</ul>
<div class="not-prose my-6 overflow-hidden rounded-xl border border-paprika-200 bg-paprika-50 dark:border-paprika-800 dark:bg-paprika-900/20"
     data-track-content data-content-name="Affiliate-Box · /tutorials/systemd-grundlagen/" data-content-piece="VPS 1000 G12">
  <div class="flex items-center justify-between border-b border-paprika-200 bg-paprika-100 px-4 py-1.5 text-xs font-semibold uppercase tracking-wide text-paprika-700 dark:border-paprika-800 dark:bg-paprika-900/40 dark:text-paprika-300">
    <span>🍳 Empfehlung</span>
    <span title="Mit * markierte Links sind Affiliate-Links.">Anzeige</span>
  </div>
  <div class="flex flex-col gap-4 p-4 sm:flex-row sm:items-center sm:justify-between">
    <div>
      <p class="text-lg font-bold text-slate-900 dark:text-white">VPS 1000 G12</p>
      <p class="mt-1 text-sm text-slate-600 dark:text-slate-300">4 vCore · 8 GB RAM · 256 GB NVMe</p>
      <p class="mt-1 text-sm font-semibold text-paprika-700 dark:text-paprika-400">ab 10,36 €/Monat</p>
      <p class="mt-2 text-sm text-slate-600 dark:text-slate-400">Die Befehle sind auf jedem systemd-Linux gleich – jeder Server genügt.</p>
    </div>
    <a href="https://www.netcup.com/de/server/vps/vps-1000-g12-12m?ref=44083" rel="sponsored noopener" target="_blank"
   data-track-event="Affiliate|netcup: Affiliate-Box|VPS 1000 G12 · {page}"
   class="inline-flex shrink-0 items-center justify-center rounded-lg bg-paprika-600 px-5 py-2.5 font-semibold text-white transition-colors hover:bg-paprika-700">
  Zu netcup →
</a>

  </div><div class="px-4 pb-4"><p class="not-prose my-3 flex flex-wrap items-center gap-x-2 gap-y-1 rounded-lg border border-herb-500/40 bg-herb-50 px-3 py-2 text-sm text-slate-700 dark:bg-herb-900/20 dark:text-slate-200">
  <span>💶 <strong>5 € Gutschein</strong> für netcup-Neukunden:</span><code data-track-voucher="36nc17844976032"
        class="rounded bg-white px-2 py-0.5 font-mono text-sm font-semibold text-herb-800 dark:bg-slate-800 dark:text-herb-400">36nc17844976032</code>
  <span class="text-xs text-slate-500 dark:text-slate-400">(nur Neukunden, keine Domains)</span>
</p></div>
</div>

<h2 id="schritt-für-schritt">Schritt für Schritt</h2>
<h3 id="schritt-1-units--das-grundkonzept">Schritt 1: Units – das Grundkonzept</h3>
<p>systemd verwaltet alles als <strong>Units</strong>. Die wichtigste Art ist der <strong>Service</strong> (<code>.service</code>) – ein Hintergrunddienst. Daneben gibt es u. a. <strong>Timer</strong> (<code>.timer</code>, geplante Ausführung), <strong>Sockets</strong> und <strong>Targets</strong> (Gruppen, grob vergleichbar mit Runlevels). Prüfe zuerst, welche Version läuft:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">systemctl --version</span></span></code></pre></div>
</div>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">systemd 257 (257.13-1~deb13u1)</span></span></code></pre></div>
</div>
<p>Alle laufenden Dienste zeigt dir <code>systemctl</code>:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">systemctl list-units --type<span class="o">=</span>service --state<span class="o">=</span>running</span></span></code></pre></div>
</div>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">  containerd.service   loaded active running containerd container runtime
</span></span><span class="line"><span class="cl">  cron.service         loaded active running Regular background program processing daemon
</span></span><span class="line"><span class="cl">  docker.service       loaded active running Docker Application Container Engine
</span></span><span class="line"><span class="cl">  fail2ban.service     loaded active running Fail2Ban Service
</span></span><span class="line"><span class="cl">  ssh.service          loaded active running OpenBSD Secure Shell server</span></span></code></pre></div>
</div>
<p>Jede Zeile ist eine Unit mit Ladezustand (<code>loaded</code>), Aktivzustand (<code>active</code>) und Unterzustand (<code>running</code>).</p>
<h3 id="schritt-2-dienste-steuern">Schritt 2: Dienste steuern</h3>
<p>Der wichtigste Befehl ist <code>systemctl status</code>. Er zeigt dir alles über einen Dienst – am Beispiel Docker:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">systemctl status docker</span></span></code></pre></div>
</div>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">● docker.service - Docker Application Container Engine
</span></span><span class="line"><span class="cl">     Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; preset: enabled)
</span></span><span class="line"><span class="cl">     Active: active (running) since Sun 2026-07-19 21:34:42 CEST; 4 days ago
</span></span><span class="line"><span class="cl">   Main PID: 53379 (dockerd)
</span></span><span class="line"><span class="cl">      Tasks: 93
</span></span><span class="line"><span class="cl">     Memory: 282.8M (peak: 334.6M)</span></span></code></pre></div>
</div>
<p>Zwei Zeilen sind entscheidend: <code>Active:</code> (läuft der Dienst gerade?) und in der <code>Loaded:</code>-Zeile das Wort <code>enabled</code> (startet er beim Booten automatisch?). Das sind zwei <strong>unabhängige</strong> Dinge – ein Dienst kann laufen, aber nicht beim Boot starten, und umgekehrt. Für Skripte fragst du beides knapp ab:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">systemctl is-active docker
</span></span><span class="line"><span class="cl">systemctl is-enabled docker</span></span></code></pre></div>
</div>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">active
</span></span><span class="line"><span class="cl">enabled</span></span></code></pre></div>
</div>
<p>Die vier Befehle für den Alltag: <code>systemctl start DIENST</code> (jetzt starten), <code>stop</code> (jetzt anhalten), <code>restart</code> (neu starten, z. B. nach Konfigänderung) und <code>reload</code> (Konfiguration neu einlesen, ohne den Dienst zu unterbrechen – sofern er das unterstützt). <strong>Wichtig:</strong> <code>start</code>/<code>stop</code> wirken nur bis zum nächsten Reboot. Damit ein Dienst <em>dauerhaft</em> beim Booten startet, brauchst du <code>enable</code>:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">systemctl <span class="nb">enable</span> --now DIENST</span></span></code></pre></div>
</div>
<p><code>enable</code> schaltet den Autostart ein, <code>--now</code> startet den Dienst zusätzlich sofort – so sparst du dir den separaten <code>start</code>.</p>
<h3 id="schritt-3-logs-lesen-mit-journalctl">Schritt 3: Logs lesen mit journalctl</h3>
<p>systemd sammelt die Ausgaben aller Dienste zentral im <strong>Journal</strong>. Statt in verstreuten Log-Dateien zu suchen, fragst du gezielt einen Dienst ab:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">journalctl -u docker -n <span class="m">20</span></span></span></code></pre></div>
</div>
<p><code>-u</code> wählt die Unit, <code>-n 20</code> zeigt die letzten 20 Zeilen. Die nützlichsten Varianten:</p>
<ul>
<li><code>journalctl -u DIENST -f</code> – live mitverfolgen (wie <code>tail -f</code>), ideal beim Debuggen.</li>
<li><code>journalctl -u DIENST --since &quot;1 hour ago&quot;</code> – zeitlich eingrenzen.</li>
<li><code>journalctl -p err -b</code> – nur Fehler seit dem letzten Boot (<code>-b</code> = aktueller Boot).</li>
</ul>
<p>Genau das ist der erste Griff, wenn ein Dienst nicht startet: <code>systemctl status DIENST</code> für den Überblick, dann <code>journalctl -u DIENST</code> für die Details.</p>
<h3 id="schritt-4-einen-eigenen-dienst-anlegen">Schritt 4: Einen eigenen Dienst anlegen</h3>
<p>Jetzt baust du selbst eine Unit. Beispiel: ein Backup-Skript, das systemd ausführen soll. Unit-Dateien für eigene Dienste liegen in <code>/etc/systemd/system/</code>. Lege <code>backup-demo.service</code> an:</p>
<div class="sk-code">
  <span class="sk-code-head">INI</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ini" data-lang="ini"><span class="line"><span class="cl"><span class="k">[Unit]</span>
</span></span><span class="line"><span class="cl"><span class="na">Description</span><span class="o">=</span><span class="s">Demo-Backup-Job</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">[Service]</span>
</span></span><span class="line"><span class="cl"><span class="na">Type</span><span class="o">=</span><span class="s">oneshot</span>
</span></span><span class="line"><span class="cl"><span class="na">ExecStart</span><span class="o">=</span><span class="s">/usr/bin/bash -c &#39;echo &#34;Backup lief am $(date)&#34; &gt;&gt; /var/log/backup-demo.log&#39;</span></span></span></code></pre></div>
</div>
<p>Der Abschnitt <code>[Unit]</code> beschreibt die Unit, <code>[Service]</code> sagt, <em>was</em> laufen soll. <code>Type=oneshot</code> ist der Typ für einmalige Aufgaben, die starten, ihre Arbeit tun und sich beenden (im Gegensatz zu Dauerdiensten wie <code>docker</code>). Nach dem Anlegen einer neuen Unit muss systemd sie einlesen:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">systemctl daemon-reload
</span></span><span class="line"><span class="cl">systemctl start backup-demo.service</span></span></code></pre></div>
</div>
<p>Prüfe das Ergebnis – <code>oneshot</code>-Dienste stehen nach getaner Arbeit korrekterweise auf <code>inactive (dead)</code>:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">systemctl status backup-demo.service</span></span></code></pre></div>
</div>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">○ backup-demo.service - Demo-Backup-Job
</span></span><span class="line"><span class="cl">     Loaded: loaded (/etc/systemd/system/backup-demo.service; static)
</span></span><span class="line"><span class="cl">     Active: inactive (dead)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">systemd[1]: Starting backup-demo.service - Demo-Backup-Job...
</span></span><span class="line"><span class="cl">systemd[1]: backup-demo.service: Deactivated successfully.
</span></span><span class="line"><span class="cl">systemd[1]: Finished backup-demo.service - Demo-Backup-Job.</span></span></code></pre></div>
</div>
<h3 id="schritt-5-timer-statt-cron">Schritt 5: Timer statt Cron</h3>
<p>Damit der Job regelmäßig läuft, koppelst du ihn an einen <strong>Timer</strong> – die systemd-Alternative zu Cron. Lege <code>backup-demo.timer</code> an (gleicher Name wie der Service, andere Endung):</p>
<div class="sk-code">
  <span class="sk-code-head">INI</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ini" data-lang="ini"><span class="line"><span class="cl"><span class="k">[Unit]</span>
</span></span><span class="line"><span class="cl"><span class="na">Description</span><span class="o">=</span><span class="s">Startet den Demo-Backup täglich</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">[Timer]</span>
</span></span><span class="line"><span class="cl"><span class="na">OnCalendar</span><span class="o">=</span><span class="s">*-*-* 03:00:00</span>
</span></span><span class="line"><span class="cl"><span class="na">Persistent</span><span class="o">=</span><span class="s">true</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">[Install]</span>
</span></span><span class="line"><span class="cl"><span class="na">WantedBy</span><span class="o">=</span><span class="s">timers.target</span></span></span></code></pre></div>
</div>
<p><code>OnCalendar</code> bestimmt den Zeitplan (hier: täglich um 03:00 Uhr). <code>Persistent=true</code> ist der entscheidende Vorteil gegenüber Cron: War der Server zur geplanten Zeit aus, holt systemd den Lauf beim nächsten Start <strong>nach</strong> – ein verpasstes Backup fällt so nicht einfach aus. Aktiviere den Timer:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">systemctl daemon-reload
</span></span><span class="line"><span class="cl">systemctl <span class="nb">enable</span> --now backup-demo.timer</span></span></code></pre></div>
</div>
<p>Alle aktiven Timer und ihre nächste Ausführung zeigt:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">systemctl list-timers</span></span></code></pre></div>
</div>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">NEXT                        LEFT  UNIT                ACTIVATES
</span></span><span class="line"><span class="cl">Sat 2026-07-25 03:00:00 CEST 7h   backup-demo.timer   backup-demo.service</span></span></code></pre></div>
</div>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-herb-400 bg-herb-50 dark:border-herb-700 dark:bg-herb-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">🧑‍🍳</span>OnCalendar-Ausdrücke testen
  </p>
  <div class="prose-kitchen text-sm">Bevor du einen komplizierten Zeitplan aktivierst, prüfe ihn mit <code>systemd-analyze calendar &quot;Mon *-*-* 09:00:00&quot;</code> – das zeigt dir die nächsten Ausführungszeitpunkte, ohne etwas zu starten. So vermeidest du Timer, die nie oder zur falschen Zeit feuern.</div>
</div>
<p>Genau dieses Muster – ein <code>oneshot</code>-Service plus Timer – nutzen die <a href="/tutorials/backups-mit-restic/">Restic-Backups</a> der Serverküche. Du hast damit das Werkzeug für jede wiederkehrende Wartungsaufgabe in der Hand.</p>
<h2 id="wenn-es-nicht-funktioniert">Wenn es nicht funktioniert</h2>
<div class="troubleshoot not-prose">
<p><strong><code>systemctl start</code> schlägt fehl, der Dienst ist sofort wieder <code>dead</code>.</strong> Lies die Details mit <code>journalctl -u DIENST -n 30</code>. Bei eigenen Units ist die häufigste Ursache ein falscher Pfad in <code>ExecStart</code> – der Befehl muss mit <strong>absolutem Pfad</strong> stehen (<code>/usr/bin/bash</code>, nicht <code>bash</code>).</p>
<p><strong>„Unit changed on disk, run daemon-reload&quot;.</strong> Du hast eine Unit-Datei bearbeitet, aber systemd liest Änderungen nicht automatisch. Nach <em>jeder</em> Änderung an <code>/etc/systemd/system/</code> gilt: <code>systemctl daemon-reload</code>.</p>
<p><strong>Der Timer taucht in <code>list-timers</code> nicht auf.</strong> Er wurde nicht aktiviert. <code>systemctl enable --now DIENST.timer</code> – und daran denken, dass der Timer den <em>Service</em> auslöst, du also beide Dateien brauchst (<code>.service</code> <strong>und</strong> <code>.timer</code>).</p>
<p><strong><code>enable</code> meldet „static&quot;.</strong> Der Unit fehlt der Abschnitt <code>[Install]</code> mit <code>WantedBy=</code>. Ohne ihn weiß systemd nicht, wann die Unit automatisch starten soll – bei Timern gehört <code>WantedBy=timers.target</code> hinein.</p>
<p><strong>Das Journal ist riesig / frisst Platz.</strong> Standardmäßig wächst es begrenzt, aber du kannst es beschneiden: <code>journalctl --vacuum-time=14d</code> löscht Einträge älter als 14 Tage, <code>journalctl --disk-usage</code> zeigt den Verbrauch.</p>

</div>

<h2 id="wartung--backups">Wartung &amp; Backups</h2>
<ul>
<li><strong>Eigene Units gehören ins Backup.</strong> Alles unter <code>/etc/systemd/system/</code> ist deine eigene Konfiguration und sollte im <a href="/tutorials/backups-mit-restic/">Restic-Backup</a> liegen. Nach einem Server-Neuaufbau stellst du damit deine Dienste und Timer sofort wieder her (danach einmal <code>daemon-reload</code> und die Timer neu <code>enable</code>n).</li>
<li><strong>Timer statt eigener Cron-Jobs.</strong> Wenn du ohnehin systemd nutzt, sind Timer die konsistentere Wahl: Sie laufen im Journal auf, holen verpasste Läufe nach (<code>Persistent=true</code>) und lassen sich mit <code>systemctl status DIENST</code> genauso überwachen wie jeder andere Dienst.</li>
<li><strong>Failed-Units im Blick behalten.</strong> <code>systemctl --failed</code> listet Dienste, die abgestürzt sind – ein schneller Gesundheitscheck fürs System. Für echte Alarmierung meldet dir <a href="/tutorials/uptime-kuma-monitoring/">Uptime Kuma</a> den Ausfall des Servers, während <code>systemctl --failed</code> die Ursache auf dem Host zeigt.
</content></li>
</ul>
]]></content:encoded></item></channel></rss>