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.
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
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)
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:
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 /
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)
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
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
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:
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.
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.
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.
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.
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.
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.
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
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.