Home › Jenkins Cron
Jenkins Cron: Pipeline Triggers and Scheduling
How to schedule cron jobs in Jenkins using pipeline triggers. Covers the triggers { cron() } syntax, the Jenkins-specific H hash operator, timezone configuration, parameterized builds and debugging when a Jenkins cron trigger is not working.
Jenkins Pipeline Cron Trigger Syntax
In a Declarative Pipeline, scheduled builds are defined in the triggers block using cron().
Jenkins uses standard 5-field cron syntax plus the H operator - see the
official Jenkins Pipeline Syntax docs.
pipeline {
agent any
triggers {
cron('H 2 * * *') // Daily around 2 AM (H spreads load)
}
stages {
stage('Build') {
steps {
echo 'Running scheduled build'
}
}
}
}
Declarative Pipeline (Jenkinsfile)
pipeline {
agent any
triggers {
cron('0 9 * * 1-5')
}
stages { ... }
}
Freestyle job (Build periodically)
In a Freestyle job, go to Configure › Build Triggers › Build periodically and enter the cron expression directly - no triggers {} wrapper needed:
H 2 * * *
The Jenkins H Operator
H is the most important Jenkins-specific extension to standard cron syntax. It stands for "hash" - Jenkins replaces it with a value derived from the job name, so each job gets a consistent but different time. This prevents dozens of jobs all firing at the same second (e.g. midnight) and overloading the Jenkins controller.
H vs 0 - the key difference
Without H - all jobs fire at exactly midnight:
0 0 * * * # Every job starts at 00:00:00
# Large spike, Jenkins slows down
With H - jobs spread across midnight hour:
H H * * * # Job A: 00:14
# Job B: 00:37
# Job C: 00:52
H is deterministic, not random. The value is a hash of the job name, so it stays the same for that job every time. You can rely on it for scheduling, you just cannot control the exact minute.
| Expression | Meaning | H equivalent of |
|---|---|---|
H * * * * | Every hour at a stable hash-determined minute | 0 * * * * |
H/15 * * * * | Every 15 minutes, starting at a hash offset | */15 * * * * |
H/30 * * * * | Every 30 minutes, hash-offset start | */30 * * * * |
H 2 * * * | Daily sometime in the 2 AM hour | 0 2 * * * |
H H * * * | Daily at a hash-determined hour and minute | 0 0 * * * |
H H * * 1-5 | Weekdays at a hash-determined time | 0 2 * * 1-5 |
H(0-30) * * * * | Random minute in the first half of each hour | - |
H H(3-4) * * * | Daily sometime between 3 AM and 4 AM | 0 3 * * * |
Jenkins Cron Examples
| Expression | Description |
|---|---|
H/5 * * * * | Every 5 minutes (hash-offset) |
H/15 * * * * | Every 15 minutes |
H/30 * * * * | Every 30 minutes |
H * * * * | Every hour |
H H/4 * * * | Every 4 hours |
H H/6 * * * | Every 6 hours |
H 2 * * * | Daily around 2 AM |
H 9 * * 1-5 | Weekdays around 9 AM |
H 0 * * 0 | Every Sunday around midnight |
H H 1 * * | First day of every month |
H 0 * * 1-5 | Every weekday around midnight |
H 12 * * 1-5 | Weekdays at noon |
Multiple Cron Triggers in One Pipeline
Use a multi-line string to define multiple schedules for the same pipeline:
pipeline {
agent any
triggers {
cron('''
H 0 * * 1-5 # Nightly on weekdays
H 12 * * 1-5 # Midday on weekdays
H H * * 0 # Weekly on Sunday
''')
}
stages { ... }
}
Jenkins Cron Timezone
By default, Jenkins uses the timezone of the Jenkins controller JVM. To specify a different timezone, prepend TZ=Zone/City on its own line before the cron expression:
triggers {
cron('TZ=Europe/Madrid\nH 9 * * 1-5')
}
Or in a Freestyle job's "Build periodically" field:
TZ=America/New_York H 9 * * 1-5
Parameterized Cron in Jenkins
To run a Jenkins job on a schedule with different parameters for each run, use the
Parameterized Scheduler plugin.
Parameters are passed after the cron expression using % as a separator:
// In the parameterized-scheduler field: H 2 * * * % ENV=production H 4 * * * % ENV=staging // Multiple parameters: H 2 * * * % ENV=production;REGION=eu-west
For multi-branch pipelines, restrict the schedule to a specific branch to avoid building feature branches on cron:
pipeline {
agent any
triggers {
cron(BRANCH_NAME == 'main' ? 'H 2 * * *' : '')
}
stages { ... }
}
Jenkins Cron Not Working - Checklist
Run the pipeline at least once manually
Jenkins does not activate the triggers block until the pipeline has run at least once.
If you added a cron trigger to a new pipeline, run it manually first - only after the first run will Jenkins register the schedule.
This is the most common cause of a Jenkins cron trigger silently doing nothing.
Check "Build periodically" is enabled
For Freestyle jobs, go to Configure › Build Triggers and confirm "Build periodically" is checked.
For Pipeline jobs, the triggers { cron() } block in the Jenkinsfile activates it automatically after the first run.
Validate the cron expression
Jenkins shows a preview of when the expression will fire next, directly in the "Build periodically" field.
If the preview shows an error or no upcoming time, the expression is wrong.
Standard cron validators work too - Jenkins syntax is compatible except for the H operator.
Check the Jenkins controller timezone
Jenkins uses the controller's JVM timezone, which may not be what you expect.
Check it in Manage Jenkins › System Information - look for user.timezone.
If the timezone is wrong, set TZ=Your/Timezone in the cron expression or configure -Duser.timezone in the JVM options.
Pipeline cron trigger not working after Jenkinsfile change
If you changed the triggers { cron() } expression in your Jenkinsfile, Jenkins does not pick up the change until the next run.
Trigger one manual run after the change to register the new schedule.
H is not a valid expression outside Jenkins
The H operator is Jenkins-specific. It will not work in Linux crontab, GitHub Actions, Kubernetes or any other platform.
If you copy a Jenkins expression to another tool and replace H with a number, use our cron validator to check the result.
Build and validate your Jenkins cron expression
Jenkins uses standard 5-field cron syntax. Generate the base expression here, then add the H operator if needed.