Skip to content

ClamAV Antivirus Setup

💡
Before you start

You need a Linux machine (or WSL on Windows) and a terminal — nothing else to buy. ClamAV is free and open-source. Install it with your package manager: sudo apt install clamav on Debian/Ubuntu, sudo dnf install clamav on Fedora, brew install clamav on macOS. Confirm it is there with clamscan --version; any 1.x release behaves the same for what follows.

Everything below runs against files you create in a folder you own. The one “infected” file you scan is the EICAR test file — a harmless 68-byte string every antivirus is required to flag as a test. It is not malware and cannot harm anything; it exists precisely so you can prove your scanner works without touching a real virus.

What Is ClamAV

ClamAV is a free, open-source antivirus engine designed for detecting malware, viruses, trojans, and other malicious software. It is maintained by Cisco's Talos Intelligence Group and is one of the most widely deployed open-source antivirus solutions in the world.

While Linux systems are generally less targeted by malware than Windows, ClamAV is valuable in several scenarios: scanning files on a mail server before delivery, checking uploads on a web server, auditing shared drives that serve Windows clients, and verifying the integrity of downloaded software.

clamscan The command-line scanner. Loads the virus database each time it runs. Best for on-demand, one-off scans.
clamd The ClamAV daemon. Keeps the virus database loaded in memory for faster scanning. Best for frequent or automated scans.
freshclam The virus definition updater. Downloads the latest signatures from ClamAV's servers so your scanner can detect new threats.
clamdscan A client that sends scan requests to the clamd daemon. Much faster than clamscan because it does not reload the database each time.

Installing ClamAV

ClamAV is available in the default repositories of most major Linux distributions.

Ubuntu / Debian

# Install ClamAV and the daemon
sudo apt update
sudo apt install clamav clamav-daemon

# Verify installation
clamscan --version

Fedora / RHEL

sudo dnf install clamav clamav-update clamd

After installation, the freshclam service typically starts automatically to download the latest virus definitions. You can check its status:

sudo systemctl status clamav-freshclam
💡
First update takes time.

The initial virus database download can take several minutes depending on your connection speed. The database files are stored in /var/lib/clamav/ and total approximately 300-400 MB. Do not run a scan until the first update completes, or your results will be unreliable.

Updating Virus Definitions

An antivirus scanner is only as good as its virus definitions. ClamAV's freshclam tool downloads updated signature databases from ClamAV's content delivery network.

Automatic Updates

The clamav-freshclam service runs automatically and checks for updates multiple times per day. Verify it is running:

sudo systemctl status clamav-freshclam

# If not running, start and enable it
sudo systemctl start clamav-freshclam
sudo systemctl enable clamav-freshclam

Manual Updates

If you need to force an immediate update (for example, after a fresh install), stop the freshclam service first to avoid lock conflicts, then run it manually:

# Stop the service to avoid database lock
sudo systemctl stop clamav-freshclam

# Run freshclam manually
sudo freshclam

# Restart the service
sudo systemctl start clamav-freshclam

Successful output looks like:

ClamAV update process started at Mon Mar  2 10:30:00 2026
daily.cvd database is up-to-date (version: 27250)
main.cvd database is up-to-date (version: 62)
bytecode.cvd database is up-to-date (version: 335)
⚠️
Do not run freshclam while the service is active.

Running freshclam manually while clamav-freshclam.service is running causes a database lock error. Always stop the service first, update manually, then restart the service.

Freshclam Configuration

The freshclam configuration file is located at /etc/clamav/freshclam.conf. Key settings include:

Checks 24 Number of update checks per day. Default is 12 (every 2 hours). Setting to 24 checks every hour.
DatabaseMirror The server to download updates from. Default is database.clamav.net which uses a CDN for fast downloads.
NotifyClamd Path to clamd.conf. When set, freshclam notifies the clamd daemon to reload its database after an update.

Running Scans

The clamscan command is the primary tool for on-demand scanning. It loads the virus database into memory, scans the specified files or directories, and reports any detections.

Scanning a Single File

clamscan /path/to/suspicious-file.zip

Scanning a Directory

# Scan a directory (non-recursive)
clamscan /home/john/Downloads/

# Scan a directory recursively (include subdirectories)
clamscan -r /home/john/Downloads/

Scanning with Useful Options

# Recursive scan, only show infected files, log results
clamscan -r -i --log=/var/log/clamav/scan.log /home/

# Scan and automatically remove infected files
clamscan -r --remove /home/john/Downloads/

# Scan and move infected files to quarantine
clamscan -r --move=/var/quarantine /home/john/Downloads/

# Scan entire system (excluding some directories)
sudo clamscan -r --exclude-dir="^/sys" --exclude-dir="^/proc" \
  --exclude-dir="^/dev" -i /
⚠️
Use --remove with caution.

The --remove flag permanently deletes files that ClamAV identifies as infected. False positives can and do occur. It is safer to use --move=/var/quarantine so you can review the files before deletion and recover any false positives.

Understanding Scan Results

After a scan completes, ClamAV displays a summary:

----------- SCAN SUMMARY -----------
Known viruses: 8702317
Engine version: 1.3.0
Scanned directories: 142
Scanned files: 1893
Infected files: 1
Data scanned: 456.23 MB
Time: 120.456 sec (2 m 0 s)
Known viruses The total number of signatures in your virus database. A higher number means more comprehensive coverage.
Infected files The number of files that matched a malware signature. If this is 0, no threats were found.
Exit code clamscan returns 0 for clean, 1 for infected files found, and 2 for errors. Useful for scripting.

Scheduling Scans with Cron

Running scans manually is fine for spot checks, but for consistent protection you should schedule regular automatic scans using cron.

Creating a Scan Script

First, create a simple script that runs the scan and logs the results:

#!/bin/bash
# /usr/local/bin/clamav-scan.sh
# Scheduled ClamAV scan script

SCAN_DIR="/home"
LOG_FILE="/var/log/clamav/scheduled-scan.log"
QUARANTINE="/var/quarantine"

# Create quarantine directory if it does not exist
mkdir -p "$QUARANTINE"

# Run the scan
echo "=== ClamAV Scan Started: $(date) ===" >> "$LOG_FILE"
clamscan -r -i --move="$QUARANTINE" "$SCAN_DIR" >> "$LOG_FILE" 2>&1
echo "=== ClamAV Scan Finished: $(date) ===" >> "$LOG_FILE"
echo "" >> "$LOG_FILE"
# Make the script executable
sudo chmod +x /usr/local/bin/clamav-scan.sh

# Create the quarantine directory
sudo mkdir -p /var/quarantine

Adding a Cron Job

# Edit the root crontab
sudo crontab -e

# Add this line to run a scan every day at 3:00 AM
0 3 * * * /usr/local/bin/clamav-scan.sh
💡
Schedule scans during off-peak hours.

ClamAV scanning is CPU and I/O intensive. Running a full system scan during working hours can noticeably slow down the system. Schedule scans for late night or early morning when the system is idle.

Checking Scan Logs

# View the latest scan results
sudo tail -50 /var/log/clamav/scheduled-scan.log

# Search for infected files in the log
sudo grep "FOUND" /var/log/clamav/scheduled-scan.log

The clamd Daemon

For environments that require frequent or real-time scanning, the clamd daemon keeps the virus database loaded in memory. This eliminates the startup cost of loading the database for each scan, making individual scans dramatically faster.

Starting clamd

# Start the ClamAV daemon
sudo systemctl start clamav-daemon

# Enable it to start on boot
sudo systemctl enable clamav-daemon

# Check its status
sudo systemctl status clamav-daemon
💡
Memory usage.

The clamd daemon loads the entire virus database into memory, which consumes approximately 1-1.5 GB of RAM. On systems with limited memory, you may prefer to use clamscan on-demand instead of running the daemon continuously.

Scanning with clamdscan

Once clamd is running, use clamdscan instead of clamscan for much faster scanning:

# Scan a directory using the daemon
clamdscan /home/john/Downloads/

# Scan and move infected files
clamdscan --move=/var/quarantine /home/john/Downloads/

# Multi-threaded scan (uses all available threads)
clamdscan --multiscan /home/

The --multiscan flag enables parallel scanning using multiple threads, which can significantly speed up scans of large directories on multi-core systems.

clamd Configuration

The clamd configuration file is at /etc/clamav/clamd.conf. Important settings include:

MaxFileSize Maximum file size to scan. Files larger than this are skipped. Default is 25 MB. Increase for servers handling large uploads.
MaxScanSize Maximum data size scanned within an archive. Default is 100 MB. Prevents denial-of-service from zip bombs.
ExcludePath Regular expression for paths to exclude from scanning. Useful for skipping virtual filesystems like /proc and /sys.

Now Do It Yourself: Scan for Malware in Five Steps

Reading about a scanner proves nothing; watching your own copy of ClamAV flag a file and move it into quarantine proves it works. You will confirm the engine runs, create the harmless EICAR test file, scan it, read the verdict, catch a file disguised with a fake extension, and quarantine it — then use the exit code the way a real cron job does. Every line of output below was produced by running these exact commands with ClamAV 1.5 on Linux.

1
Confirm the engine runs, and update its signatures

Go: open a terminal in any folder you can write to (mkdir clamlab && cd clamlab).

Do: run clamscan --version. On your own machine, follow it with sudo freshclam once to download the latest signature database.

clamscan --version

You should see: a line like ClamAV 1.5.3/28099/Fri Aug 21 2026. The first number is the engine version; the second is the signature-database version, and it should be recent — a scanner with stale signatures cannot recognise new malware. On this run the database held over 3,600,000 known signatures.

If not: command not found means it is not installed — go back to Before you start. If freshclam reports can't open/create /var/log/clamav/freshclam.log, run it with sudo; the signature database is owned by root.

2
Create the harmless EICAR test file and a clean file, then scan both

Go: the same clamlab folder.

Do: make one ordinary file and the EICAR test string, then scan the pair. Type the printf line exactly — the single quotes stop the shell from touching the $ and \ inside it.

echo "just an ordinary note" > report.txt
printf '%s' 'X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*' > eicar.com
clamscan --no-summary report.txt eicar.com

You should see: exactly this — one line per file:

report.txt: OK
eicar.com: Eicar-Test-Signature FOUND

That is the whole job in miniature: the clean file passes, the test file is flagged by name. You just watched signature matching work.

If not: if both say OK, your eicar.com is wrong — a text editor may have added a trailing newline or “smart quotes”. Re-run the printf line, which writes the 68 bytes with no extras, and check with wc -c eicar.com — it must print 68.

3
Read the scan summary — the number that matters is “Infected files”

Go: same folder.

Do: scan the whole folder without --no-summary so ClamAV prints its report.

clamscan .

You should see: the two per-file lines again, then a summary block. The line that matters is Infected files: 1. Known viruses and the Time will differ on your machine — the signature count grows daily and the scan takes a few seconds — but Infected files: 1 is fixed, because exactly one of your two files is the test signature.

If not: Infected files: 0 means the scan never saw eicar.com — check you are in the right folder with ls, and that the file is there.

4
Catch a file hiding behind a fake extension

Go: same folder. Real malware rarely announces itself; a common trick is invoice.pdf.exe, which looks like a PDF but runs as a program.

Do: plant a disguised copy in a sub-folder, then scan recursively (-r) showing only infected files (-i).

mkdir -p downloads/nested
cp eicar.com downloads/nested/invoice.pdf.exe
clamscan -r -i .

You should see: both copies caught, no matter how deep or what they are called — ClamAV reads the contents, not the name:

./downloads/nested/invoice.pdf.exe: Eicar-Test-Signature FOUND
./eicar.com: Eicar-Test-Signature FOUND
Infected files: 2

If not: if only eicar.com is listed, you left off -r — without it ClamAV does not descend into downloads/. The -i flag only hides the OK lines; drop it and you see every file scanned.

5
Quarantine what you find, and let the exit code drive a script

Go: same folder.

Do: make a quarantine folder, re-scan with --move so infected files are pulled out of harm’s way, then check what the exit code was.

mkdir -p quarantine
clamscan -r --move=quarantine --no-summary .
echo "scan exit code was: $?"

You should see: each infected file reported as moved to '.../quarantine/eicar.com', the files gone from their original spots, and scan exit code was: 1. That 1 is the point: ClamAV returns 0 when everything is clean and 1 when it finds something, so a nightly cron job can e-mail you only when the exit code is non-zero.

If not: can't create/write to quarantine means the target folder is not writable — create it first, in a directory you own. If the exit code is 0, the scan found nothing to move; you are scanning the wrong folder.

🎉
Check yourself before moving on

Without scrolling up: a nightly job runs clamscan -r /home and you want it to alert you only when malware is found. What does it test to decide? Answer: the exit code. clamscan exits 0 for a clean scan and 1 when it finds an infection (2 means an error), so the job checks if clamscan -r /home; then :; else notify; fi — it never has to parse the text output.

Now do it without the page: point a real recursive scan at your own Downloads folder — clamscan -r -i ~/Downloads — and read the Infected files count. It should be 0. If it is not, do not open the file it names; quarantine it with --move as in step 5 and look up the signature name it reported.

Summary

In this tutorial, you learned how to set up and use ClamAV for malware detection on Linux:

  • Installation -- installing ClamAV and its components on Ubuntu/Debian and Fedora/RHEL
  • Virus definitions -- keeping signatures up to date with freshclam (automatic and manual updates)
  • On-demand scanning -- using clamscan with options for recursive scanning, quarantine, and logging
  • Understanding results -- interpreting scan summaries and exit codes
  • Scheduled scanning -- automating regular scans with a script and cron
  • clamd daemon -- running the daemon for faster, memory-resident scanning with clamdscan
🎉
Your system is now protected!

With ClamAV installed, definitions updating automatically, and scheduled scans configured, you have a solid malware detection layer on your Linux system. Remember to periodically check your scan logs and quarantine directory.