How to Use the Batch Command in Linux

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 atd daemon using the -l option. For example, atd -l 2.0 would 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 batch with sudo. 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:

ToolTriggerRecurrenceBest For
batchSystem load drops below 1.5One-timeBackups, log processing, batch imports
atSpecific time (e.g., 3:00 AM)One-timeMaintenance windows, time-sensitive tasks
cronRecurring scheduleRepeatingDaily 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.

Leave a Comment