The batch command schedules commands to run when system load drops below a threshold, making it ideal for resource-intensive tasks that do not require immediate execution. Unlike cron jobs that run at specific times or the at command that executes at a precise moment, batch waits for favorable system conditions before starting your tasks. This approach prevents resource contention and ensures your scheduled operations do not degrade system responsiveness.
Common use cases include running overnight backups, compressing large log archives, generating system reports, and performing maintenance tasks during periods of low activity. Because batch monitors the system load average, your tasks run when the system has spare capacity rather than competing with active users or services. As a result, batch is particularly useful on shared servers or workstations where resource availability fluctuates throughout the day.
By the end of this guide, you will know how to queue batch jobs, review pending work, and remove or troubleshoot jobs when needed.
Prerequisites
Before using the batch command, ensure the at package is installed and the atd daemon is running. On most Linux distributions, this package provides both the at and batch commands.
Check whether the command is already available:
command -v batch
Example output:
/usr/bin/batch
If the command returns a path, batch is installed. If it returns no output, install the at package using the commands below.
Ubuntu, Debian, and Linux Mint
Install the at package:
sudo apt install at
Fedora (DNF5)
Install the at package:
sudo dnf install at
RHEL, CentOS Stream, Rocky Linux, and AlmaLinux (DNF4)
Install the at package:
sudo dnf install at
Arch Linux
Install the at package:
sudo pacman -S at
openSUSE
Install the at package:
sudo zypper install at
Void Linux
Install the at package:
sudo xbps-install at
On systemd-based distributions, start the daemon and enable it at boot:
sudo systemctl enable --now atd
On Void Linux (runit), enable and start the service:
sudo ln -s /etc/sv/at /var/service/
sudo sv start at
Verify the daemon is running:
pgrep -a atd
Expected output shows an atd process:
1234 atd
On Void Linux, the output may include atd -f, which is normal.
Understanding Batch Command Syntax
The batch command reads commands from standard input and queues them for execution when the system load average drops below a threshold. By default, this threshold is 1.5, which means batch waits until the one-minute load average falls below 1.5 before running queued jobs. On a single-core system, a load of 1.5 indicates the CPU is fully utilized with additional tasks waiting. On multi-core systems, you may want a higher threshold (for example, n-1 on an n-core system) so batch jobs do not wait unnecessarily.
The load threshold of 1.5 is the default value. System administrators can change this value when starting the
atddaemon using the-loption. For example,atd -l 2.0would only run batch jobs when the load drops below 2.0.
Batch is the same as running at -b, so it accepts the same options as at (for example, -q to choose a queue or -m to mail output). In most cases, you will run batch without options and feed it commands via standard input:
batch
When invoked without input redirection, batch opens an interactive prompt where you can type commands. After entering your commands, press Ctrl+D to submit the job. Alternatively, you can press Ctrl+C to cancel without submitting.
Piping Commands to Batch
The most common method for scheduling a single command is piping it through echo:
echo "/path/to/backup.sh" | batch
After submitting a job, batch confirms the job was queued:
warning: commands will be executed using /bin/sh job 3 at Mon Dec 23 12:00:00 2025
The warning message indicates that batch uses /bin/sh to execute commands, not your current shell. This affects which shell features and environment variables are available during execution.
Scheduling from a Job File
For multiple commands or complex scripts, redirect input from a file:
batch < /path/to/jobfile.txt
The job file can contain any sequence of shell commands. Each command executes in order, and the job completes when all commands finish. However, if any command fails, subsequent commands still run unless you include explicit error handling in your script.
Viewing Queued Jobs
Use the atq command to list pending batch jobs:
atq
Example output showing two pending jobs:
3 Mon Dec 23 12:00:00 2025 b root 5 Mon Dec 23 12:05:00 2025 b root
The output columns show the job number, scheduled time, queue letter (b indicates a batch job), and the username that submitted the job. Batch jobs use the “b” queue to distinguish them from regular at jobs, which use the “a” queue.
Viewing Job Contents
Before a job executes, you can inspect its contents to verify what commands will run. Use the at -c command followed by the job number:
at -c 3
This displays the complete job script, including environment variables that will be set during execution:
#!/bin/sh
# atrun uid=1001 gid=1001
# mail user 0
umask 2
MAIL=/var/mail/user; export MAIL
USER=user; export USER
HOME=/home/user; export HOME
LOGNAME=user; export LOGNAME
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin; export PATH
LANG=C.UTF-8; export LANG
PWD=/home/user; export PWD
cd /home/user || {
echo 'Execution directory inaccessible' >&2
exit 1
}
/home/user/scripts/backup.sh
This feature helps you confirm the correct commands are queued, especially when troubleshooting jobs that do not produce expected results.
Removing Pending Jobs
To cancel a scheduled job, pass its job number to atrm:
atrm 3
This command produces no output on success. To verify the job was removed, run atq again. If you attempt to remove a job that does not exist, atrm reports an error:
Cannot find jobid 3
Practical Examples
The following examples demonstrate common batch command use cases. Each example includes the complete workflow from scheduling through verification.
Schedule a System Backup
Creating scheduled backups ensures your data is protected without requiring manual intervention. This example creates a compressed archive of a directory when system load permits.
Create the script and backup directories (see the mkdir command examples if you need a refresher):
mkdir -p /home/user/scripts /home/user/backups
Then create a backup script at /home/user/scripts/backup.sh:
#!/bin/bash
tar -czf /home/user/backups/documents_$(date +%Y%m%d_%H%M%S).tar.gz /home/user/documents
The -czf flags tell tar to create a gzip-compressed archive. The date command appends a timestamp to ensure each backup has a unique filename. If you want to review the archive later, see our guide on opening .gz and .tgz files.
Make the script executable using the chmod command:
chmod +x /home/user/scripts/backup.sh
Schedule the backup to run when system load is low:
echo "/home/user/scripts/backup.sh" | batch
Verify the job is queued:
atq
Expected output:
6 Mon Dec 23 14:30:00 2025 b user
Generate a System Health Report
System administrators often generate health reports during off-peak hours. This example creates a comprehensive report including disk usage, memory status, and active processes.
Create the script and report directories:
mkdir -p /home/user/scripts /home/user/reports
Create a health check script at /home/user/scripts/system_health.sh:
#!/bin/bash
REPORT="/home/user/reports/health_$(date +%Y%m%d_%H%M%S).txt"
echo "System Health Report - $(date)" > "$REPORT"
echo "==============================" >> "$REPORT"
echo "" >> "$REPORT"
echo "DISK USAGE:" >> "$REPORT"
df -h >> "$REPORT"
echo "" >> "$REPORT"
echo "MEMORY USAGE:" >> "$REPORT"
free -h >> "$REPORT"
echo "" >> "$REPORT"
echo "LOAD AVERAGE:" >> "$REPORT"
uptime >> "$REPORT"
echo "" >> "$REPORT"
echo "TOP 10 PROCESSES BY CPU:" >> "$REPORT"
ps aux --sort=-%cpu | head -11 >> "$REPORT"
echo "Report saved to $REPORT"
Make the script executable and schedule it:
chmod +x /home/user/scripts/system_health.sh
echo "/home/user/scripts/system_health.sh" | batch
Sample Report Output
When the job completes, a sample report might look like this:
System Health Report - Mon Dec 23 15:00:00 UTC 2025
==============================
DISK USAGE:
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 100G 45G 50G 48% /
/dev/sdb1 500G 200G 275G 43% /data
MEMORY USAGE:
total used free shared buff/cache available
Mem: 16Gi 4.2Gi 8.1Gi 256Mi 3.7Gi 11Gi
Swap: 4.0Gi 0B 4.0Gi
LOAD AVERAGE:
15:00:00 up 30 days, 2:15, 3 users, load average: 0.52, 0.78, 0.91
TOP 10 PROCESSES BY CPU:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 169936 12288 ? Ss Nov23 0:15 /sbin/init
...
Schedule Multiple Commands in Sequence
For complex maintenance tasks, you can queue multiple commands that execute in sequence. This example updates package lists, performs upgrades, and cleans up unused packages.
Create the scripts directory if it does not exist:
mkdir -p /home/user/scripts
Debian, Ubuntu, and Linux Mint: Create a maintenance file at /home/user/scripts/maintenance.txt:
apt update
apt upgrade -y
apt autoremove -y
apt clean
If you use another distribution, create a similar maintenance file with your package manager’s update and cleanup commands.
Schedule the maintenance job:
sudo batch < /home/user/scripts/maintenance.txt
When scheduling commands that require root privileges, run
batchwithsudo. The job inherits the privileges of the user who submitted it, so commands requiring root access must be submitted by root or via sudo.
Batch vs At vs Cron: When to Use Each
Linux provides multiple scheduling mechanisms, each designed for different scenarios. Understanding when to use each tool helps you choose the right approach for your tasks. The following table summarizes the key differences:
| Tool | Trigger | Recurrence | Best For |
|---|---|---|---|
| batch | System load drops below 1.5 | One-time | Backups, log processing, batch imports |
| at | Specific time (e.g., 3:00 AM) | One-time | Maintenance windows, time-sensitive tasks |
| cron | Recurring schedule | Repeating | Daily backups, weekly reports, regular maintenance |
Choosing the right tool: Use batch when the task is resource-intensive and timing is flexible, since it waits for favorable system conditions. Use at when the task must run at a specific time regardless of system load. Choose cron when the task needs to run repeatedly on a defined schedule. For related scheduling concepts, see our guide on the bash wait command for managing background processes in scripts.
Troubleshooting
Jobs Never Execute
If your batch jobs remain in the queue indefinitely, the system load may never drop below the threshold. To diagnose this issue, check the current load average:
uptime
Example output:
15:30:00 up 10 days, 5:42, 2 users, load average: 2.15, 1.98, 1.87
The three numbers represent the one-minute, five-minute, and fifteen-minute load averages. If the one-minute average consistently exceeds 1.5, batch jobs will not run unless your system uses a different threshold (for example, atd -l). On heavily loaded servers, consider using the at command instead to schedule the task at a specific off-peak time.
atd Service Not Running
If you see the error “Can’t open /run/atd.pid to signal atd. No atd running?” the scheduling daemon is not active. Start the service:
sudo systemctl start atd
Verify it started successfully:
sudo systemctl status atd
Expected output (active):
● atd.service - Deferred execution scheduler
Active: active (running) since ...
To ensure atd starts automatically on boot:
sudo systemctl enable atd
Permission Denied Errors
If batch reports permission errors, check the /etc/at.allow and /etc/at.deny files. These files control which users can schedule at and batch jobs.
The access control logic works as follows: if /etc/at.allow exists, only users listed in that file can use batch. If /etc/at.allow does not exist, all users except those listed in /etc/at.deny can use batch. By default, many distributions ship /etc/at.deny with system accounts listed, so regular users can still submit jobs unless they are explicitly blocked. Check your system’s configuration:
ls -la /etc/at.allow /etc/at.deny 2>/dev/null
Example output:
-rw-r----- 1 root daemon 144 Jun 2 00:00 /etc/at.deny
If you need access but are denied, ask your system administrator to add your username to /etc/at.allow or remove it from /etc/at.deny.
Commands Fail Silently
By default, batch mails output to the user who submitted the job. If mail is not configured on your system, you may not see error messages. To capture output manually, redirect it within your commands:
mkdir -p /home/user/logs
echo "/home/user/scripts/backup.sh > /home/user/logs/backup.log 2>&1" | batch
This redirects both standard output and standard error to a log file you can review later with the tail command.
Remove the at Package
If you no longer need batch scheduling functionality, you can remove the at package. First, ensure no pending jobs remain:
atq
Example output:
3 Mon Dec 23 16:00:00 2025 b user
If atq returns no output, there are no pending jobs.
Remove any pending jobs before uninstalling:
atrm 3 5 7
On Debian-based systems, confirm the package is not essential before removal:
apt-cache show at | grep -E '^(Essential|Priority):'
Example output:
Priority: optional
If the output shows Essential: yes or Priority: required, do not remove the package.
For Debian-based systems:
sudo apt remove at
sudo apt autoremove
The apt autoremove step removes unused dependencies that were installed with at. If you also want to purge configuration files, run sudo apt purge at after the removal step.
For Fedora (DNF5):
sudo dnf remove at
For RHEL, CentOS Stream, Rocky Linux, and AlmaLinux (DNF4):
sudo dnf remove at
For Arch Linux:
sudo pacman -Rs at
For openSUSE:
sudo zypper remove at
For Void Linux:
sudo xbps-remove at
Verify removal:
command -v batch || echo "batch not found"
Expected output after removal:
batch not found
If the command returns a path instead, the package is still installed.
Conclusion
The batch command provides efficient load-aware task scheduling for non-time-critical operations like backups, report generation, and maintenance scripts. Combined with atq for monitoring pending jobs, at -c for inspecting job contents, and atrm for cancellation, you have complete control over queued tasks. This approach ensures resource-intensive operations run only when your system has spare capacity, preventing performance degradation during peak usage periods.