Cron can run a Zsh script on a schedule after the script already works from the terminal. The important handoff is the executable script path, not an interactive Zsh session, because cron does not load ~/.zshrc or keep terminal-only variables before each job.
The script's shebang selects Zsh for the script body, while the crontab command line is still parsed by /bin/sh unless the crontab sets SHELL differently. Keeping the crontab command to one absolute script path plus redirection avoids quoting problems, and a literal PATH line in the crontab keeps the job from depending on interactive shell startup files.
Use the per-user crontab for jobs that should run as the current account. System cron files such as /etc/crontab and files under /etc/cron.d have an extra username field, so do not copy that format into crontab -e. The schedule follows the cron daemon's local time, and any percent signs typed directly in the crontab command field must be escaped.
Related: Edit a cron job in Linux
Related: How to create and run a Zsh script
Related: How to set the PATH environment variable in Zsh
Related: How to configure Zsh startup files
Steps to schedule a Zsh script with cron:
- Print the account home path for the crontab entry.
$ printf '%s\n' "$HOME" /home/admin
Replace /home/admin in the examples with the home path printed on the target account.
- Confirm the Zsh command path.
$ command -v zsh /usr/bin/zsh
The shebang below uses /usr/bin/env so the crontab PATH must include the directory that contains zsh.
- Create directories for the script and report output.
$ mkdir -p ~/bin ~/reports
- Create the scheduled Zsh script.
- ~/bin/report.zsh
#!/usr/bin/env zsh emulate -L zsh setopt err_exit no_unset mkdir -p "$HOME/reports" print -r -- "daily report $(/usr/bin/date -u +%FT%TZ)" >> "$HOME/reports/daily-report.txt"
emulate -L zsh starts the script with standard Zsh options for the current process, which makes the script less dependent on user startup files.
- Make the script executable for the file owner.
$ chmod u+x ~/bin/report.zsh
- Check the script syntax.
$ zsh -n ~/bin/report.zsh
No output from zsh -n means Zsh parsed the script without finding a syntax error.
- Run the script once from the terminal.
$ ~/bin/report.zsh
- Confirm the script wrote the report file.
$ cat ~/reports/daily-report.txt daily report 2026-06-05T05:58:12Z
- Open the current user's crontab.
$ crontab -e
crontab -e edits the per-user crontab for the current account. Use sudo crontab -u username -e only when the job must run as a different account.
- Add the cron environment lines and schedule entry.
SHELL=/bin/sh PATH=/usr/local/bin:/usr/bin:/bin MAILTO="" 0 6 * * * /home/admin/bin/report.zsh >> /home/admin/report.log 2>&1
Do not add a username field to a per-user crontab. The username field belongs in /etc/crontab and files under /etc/cron.d.
If the crontab command itself contains a % character, escape it as \%. Cron treats unescaped percent signs in the command field as line breaks passed to the command.
Tool: Crontab Generator
- Save the file and exit the editor so crontab installs the updated schedule.
A normal Linux cron daemon loads the saved user crontab automatically. A service restart is not usually required after crontab -e saves successfully.
- List the installed crontab.
$ crontab -l SHELL=/bin/sh PATH=/usr/local/bin:/usr/bin:/bin MAILTO="" 0 6 * * * /home/admin/bin/report.zsh >> /home/admin/report.log 2>&1
This confirms that the user crontab contains the exact Zsh script path and output redirection that cron will evaluate.
Related: How to list cron jobs in Linux
- Run the scheduled command with a minimal cron-like environment.
$ env -i HOME=/home/admin LOGNAME=admin PATH=/usr/local/bin:/usr/bin:/bin SHELL=/bin/sh /home/admin/bin/report.zsh
This catches missing paths, missing directories, and startup-file assumptions before the cron daemon runs the job.
- After the next scheduled run time passes, check the report output again.
$ cat /home/admin/reports/daily-report.txt daily report 2026-06-05T05:58:12Z daily report 2026-06-05T05:59:01Z daily report 2026-06-05T06:00:01Z
The new timestamp confirms that cron matched the schedule, launched the script as the crontab owner, and appended another report line.
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.