What does the Crontab to Systemd Timer & Service Unit Generator do?
The Crontab to Systemd Timer & Service Unit Generator translates legacy 5-field cron schedule lines (e.g. 15 3 * * 1-5 /usr/local/bin/backup.sh) into modern Systemd OnCalendar calendar events and production-ready .service and .timer unit files. It generates ready-to-run systemctl terminal activation commands with integrated journalctl structured logging and reboot catch-up support.
Core Concepts
Understanding cron to Systemd timer conversion:
- OnCalendar Syntax Translation: Maps cron minutes, hours, days, months, and weekday ranges to Systemd calendar specifications (e.g.
Mon..Fri *-*-* 03:15:00). - Dual Unit Architecture: Generates companion
.service(defining execution parameters, user, and command) and.timer(defining schedule triggers and reboot persistence) units. - Reboot Catch-Up (
Persistent=true): Automatically runs missed schedules during server downtime upon the next system boot. - Structured Journal Logging: Captures
stdoutandstderrdirectly into systemd journals viajournalctl -u unit-name.service.
How to use the tool?
- Enter Crontab Line: Paste your 5-field schedule and command into the input box or click Load Sample Cron.
- Configure Service Options: Set a base Unit Name, Linux User, and toggle Persistent=true.
- Generate & Activate: Click Generate Systemd Units, then copy or download the unit files and execute the provided
systemctlcommands on your Linux server.
Related Developer Utilities
If you work with Linux servers, scheduling, and system automation, explore these complementary tools:
- AWS Cron Generator: Build 6-field EventBridge and CloudWatch cron expressions.
- Linux Logrotate Config Generator: Generate
/etc/logrotate.d/rotation rules. - Rsync Command Generator: Build safe rsync file synchronization commands.
- SSH Config to Ansible Inventory Converter: Convert SSH configs to Ansible inventories.
REST API Integration
Blueutils provides a free REST API endpoint (POST https://blueutils.com/api/linux/cron-to-systemd-timer) to programmatically convert 5-field cron schedules into Systemd OnCalendar timestamps and produce production-ready .service and .timer unit files.
API Request Parameters
| Name | Type | Description | Example |
|---|---|---|---|
rawText |
String | Crontab line containing 5 schedule fields and command. | "0 2 * * * /usr/local/bin/backup.sh" |
options.unitName |
String | Optional. Systemd unit base name (default: "my-job"). |
"db-backup" |
options.user |
String | Optional. Linux execution user (default: "root"). |
"postgres" |
options.persistent |
Boolean | Optional. Enable reboot catch-up (Persistent=true). |
true |
API Request Payload Examples
cURL
curl -X POST https://blueutils.com/api/linux/cron-to-systemd-timer \
-H "Content-Type: application/json" \
-d '{
"rawText": "15 3 * * 1-5 /usr/local/bin/backup-database.sh --full",
"options": {
"unitName": "db-backup",
"user": "postgres",
"persistent": true
}
}'Python
import requests
url = "https://blueutils.com/api/linux/cron-to-systemd-timer"
payload = {
"rawText": "15 3 * * 1-5 /usr/local/bin/backup-database.sh --full",
"options": {
"unitName": "db-backup",
"user": "postgres",
"persistent": True
}
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.json())Java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Main {
public static void main(String[] args) throws Exception {
String jsonPayload = """
{
"rawText": "15 3 * * 1-5 /usr/local/bin/backup-database.sh --full",
"options": {
"unitName": "db-backup",
"user": "postgres",
"persistent": true
}
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://blueutils.com/api/linux/cron-to-systemd-timer"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(jsonPayload))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}API Response Parameters
| Name | Type | Description | Example |
|---|---|---|---|
isValid |
Boolean | Indicates whether conversion succeeded. | true |
unitName |
String | Normalized Systemd unit base name. | "db-backup" |
onCalendar |
String | Systemd OnCalendar timestamp expression. | "Mon..Fri *-*-* 03:15:00" |
serviceFile |
String | Generated .service unit file content. |
"[Unit]\nDescription=..." |
timerFile |
String | Generated .timer unit file content. |
"[Unit]\nRequires=..." |
installCommands |
String | Ready-to-run systemctl terminal activation commands. | "sudo systemctl daemon-reload..." |
API Response Payload Examples
Success Response (HTTP 200 OK)
{
"isValid": true,
"unitName": "db-backup",
"cronSchedule": "15 3 * * 1-5",
"command": "/usr/local/bin/backup-database.sh --full",
"onCalendar": "Mon..Fri *-*-* 03:15:00",
"serviceFile": "[Unit]\nDescription=Automated job translated from crontab (15 3 * * 1-5)\nWants=network-online.target\nAfter=network-online.target\n\n[Service]\nType=oneshot\nUser=postgres\nWorkingDirectory=/tmp\nExecStart=/usr/local/bin/backup-database.sh --full\nStandardOutput=journal\nStandardError=journal\n",
"timerFile": "[Unit]\nDescription=Timer for db-backup.service (15 3 * * 1-5)\nRequires=db-backup.service\n\n[Timer]\nOnCalendar=Mon..Fri *-*-* 03:15:00\nPersistent=true\nRandomizedDelaySec=1m\nUnit=db-backup.service\n\n[Install]\nWantedBy=timers.target\n",
"installCommands": "# 1. Copy unit files to /etc/systemd/system/\nsudo cp db-backup.service /etc/systemd/system/\nsudo cp db-backup.timer /etc/systemd/system/\n\n# 2. Reload systemd daemon & activate timer\nsudo systemctl daemon-reload\nsudo systemctl enable --now db-backup.timer"
}Validation Failure Response (HTTP 400 Bad Request)
{
"isValid": false,
"error": "Crontab line must contain 5 schedule fields followed by the command (e.g. \"0 2 * * * /path/to/script.sh\")."
}Rate Limit Exceeded Response (HTTP 429 Too Many Requests)
{
"error": "API rate limit exceeded. Please wait or contact support@blueutils.com."
}Why use an API to convert crontabs to systemd timers?
Integrating the Cron to Systemd Timer API into server migration scripts, Ansible playbooks, or AI agent tool calling provides key benefits:
- Rapid Script Validation: Converts legacy crontab files into modern Systemd unit definitions during server provisioning.
- Optimized Token Efficiency for AI Agents: LLMs frequently mix up
OnCalendarweekday and month formatting. Calling the API converts schedules deterministically without token consumption. - Deterministic Accuracy Without Hallucinations: Ensures 100% compliant Systemd unit file structure and activation shell commands.
Native Usage
How to test and verify Systemd calendar expressions locally on Linux:
Linux / Unix (Bash)
# Test and verify OnCalendar timestamp execution dates with systemd-analyze
systemd-analyze calendar "Mon..Fri *-*-* 03:15:00"
# List all active timers on system
systemctl list-timers --allPython
Using Python:
import re
cron_line = "15 3 * * 1-5 /usr/local/bin/backup.sh"
parts = cron_line.split(maxsplit=5)
schedule = " ".join(parts[:5])
command = parts[5]
print(f"Schedule: {schedule} | Command: {command}")Java
Using Java:
public class CronToSystemdExample {
public static void main(String[] args) {
String cron = "15 3 * * 1-5 /usr/local/bin/backup.sh";
String[] parts = cron.split("\\s+", 6);
System.out.println("Cron schedule: " + String.join(" ", java.util.Arrays.copyOf(parts, 5)));
System.out.println("Command: " + parts[5]);
}
}