How to Scan a Linux System for Malware with ClamAV
Install ClamAV on Linux, update virus signatures with freshclam, run on-demand and scheduled scans, and verify detection works with the EICAR test file.
Before you start
- ▸sudo or root access on the target system
- ▸Internet access for downloading signatures via freshclam
- ▸Basic familiarity with the terminal and systemd service management
ClamAV is the de-facto open-source antivirus engine for Linux. While Linux malware is far less common than on Windows, it is not zero — web servers get backdoors, shared hosting environments accumulate PHP shells, and cross-platform threats move through email attachments. ClamAV gives you a reliable, free way to detect all of these. This guide walks through installation, signature updates, running your first scan, and automating regular scans with a systemd timer.
Installing ClamAV
Debian and Ubuntu
sudo apt update
sudo apt install clamav clamav-daemon -y
Fedora
sudo dnf install clamav clamd clamav-update -y
RHEL, Rocky Linux, AlmaLinux
ClamAV is in the EPEL repository. Enable it first if you haven't already.
sudo dnf install epel-release -y
sudo dnf install clamav clamd clamav-update -y
Arch Linux
sudo pacman -S clamav
After installation you get two key binaries: clamscan (the on-demand scanner you run manually) and clamd (an optional background daemon that keeps signatures in memory for faster repeated scans).
Updating Virus Signatures
ClamAV ships with no signatures — you must download them before the first scan. The freshclam tool handles this. It pulls the official ClamAV database plus any community databases you configure.
Stop the daemon first (Debian/Ubuntu only)
On Debian and Ubuntu, the package starts the clamav-freshclam service automatically. Stop it before running freshclam manually so they don't conflict.
sudo systemctl stop clamav-freshclam
Run freshclam
sudo freshclam
Expected output looks like:
# Output will vary; roughly:
ClamAV update process started at ...
Main database: is up-to-date (version: 62, sigs: 6647427, ...)
Daily database: updated (version: 27382, sigs: 2042925, ...)
Bytecode database: is up-to-date ...
Signature downloads can take a minute or two on first run. Once complete, restart the freshclam service on Debian/Ubuntu so signatures stay current automatically:
sudo systemctl start clamav-freshclam
sudo systemctl enable clamav-freshclam
On Fedora and RHEL-family systems, freshclam is configured via /etc/freshclam.conf. Set DatabaseMirror database.clamav.net if it isn't already, then enable the timer:
sudo systemctl enable --now clamav-freshclam.timer
On Arch, enable the service directly:
sudo systemctl enable --now clamav-freshclam.service
Running an On-Demand Scan
clamscan is the simplest way to scan. It reads signatures from disk on each run, so it is slower than the daemon-backed clamdscan, but requires no extra setup.
Scan your home directory
clamscan --recursive --infected --bell ~/
- --recursive — descend into subdirectories
- --infected — print only infected files, not clean ones
- --bell — audible alert on detection (optional, skip on headless servers)
Scan the entire filesystem
This takes considerably longer (tens of minutes on a typical system). Exclude virtual and special filesystems to avoid noise and wasted time.
sudo clamscan \
--recursive \
--infected \
--log=/var/log/clamav/manual-scan.log \
--exclude-dir='^/sys' \
--exclude-dir='^/proc' \
--exclude-dir='^/dev' \
--exclude-dir='^/run' \
/
Create the log directory if it doesn't exist:
sudo mkdir -p /var/log/clamav
Move or remove detected files
Add --move=/quarantine to relocate infected files rather than deleting them outright. Review them before permanent removal.
sudo mkdir -p /quarantine
sudo clamscan --recursive --infected --move=/quarantine /path/to/suspect/directory
Use --remove only when you are certain you want automatic deletion — there is no undo.
Enabling the clamd Daemon (Optional but Faster)
If you scan frequently, loading signatures into memory once pays off. The daemon-backed clamdscan is noticeably faster on repeated scans.
Debian / Ubuntu
sudo systemctl enable --now clamav-daemon
Fedora / RHEL family
On these distros, the config file at /etc/clamd.d/scan.conf must have the Example line removed (or commented out) before the daemon will start.
sudo sed -i '/^Example/d' /etc/clamd.d/scan.conf
sudo systemctl enable --now clamd@scan
Arch
sudo systemctl enable --now clamav-daemon
Once the daemon is running, replace clamscan with clamdscan in your commands for significantly faster results:
clamdscan --infected --multiscan ~/
Scheduling Automatic Scans with a systemd Timer
Cron works, but a systemd timer integrates better with journald logging and service dependency management. The following creates a nightly scan of /home and /var/www.
Create the service unit
sudo tee /etc/systemd/system/clamav-scan.service <<'EOF'
[Unit]
Description=ClamAV nightly scan
After=clamav-freshclam.service
[Service]
Type=oneshot
ExecStart=/usr/bin/clamscan \
--recursive \
--infected \
--log=/var/log/clamav/nightly-scan.log \
--exclude-dir='^/sys' \
--exclude-dir='^/proc' \
--exclude-dir='^/dev' \
/home /var/www
EOF
Create the timer unit
sudo tee /etc/systemd/system/clamav-scan.timer <<'EOF'
[Unit]
Description=Run ClamAV nightly scan at 02:30
[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true
[Install]
WantedBy=timers.target
EOF
Enable and start the timer
sudo systemctl daemon-reload
sudo systemctl enable --now clamav-scan.timer
Verify the timer is scheduled
systemctl list-timers clamav-scan.timer
Output shows the next trigger time and when it last ran. The Persistent=true setting means if the system was off at 02:30, the scan runs shortly after the next boot.
Verifying ClamAV Works
The EICAR test file is an industry-standard, completely harmless string that every antivirus must detect. Use it to confirm detection is working before you trust a clean scan result.
curl -o /tmp/eicar.com https://www.eicar.org/download/eicar.com
clamscan /tmp/eicar.com
You should see output containing Eicar-Signature FOUND. If you see OK instead, your signatures did not update — rerun sudo freshclam.
rm /tmp/eicar.com
Troubleshooting
freshclam fails with "locked by another process"
The clamav-freshclam service is already running. Stop it, run freshclam manually, then restart the service — or just let the service handle updates and skip the manual run.
clamscan is extremely slow
Scanning /proc, /sys, or /dev causes hangs and false paths. Always add the --exclude-dir flags shown above. Consider switching to clamdscan with the daemon enabled for repeated scans.
clamd fails to start on Fedora/RHEL
The most common cause is the literal word Example remaining at the top of /etc/clamd.d/scan.conf. Remove it with the sed command in the daemon section above, then restart the service.
"LibClamAV Warning: datadir not found" on Arch
Run sudo freshclam to populate the database directory. ClamAV on Arch ships with an empty database path.
Frequently asked questions
- Do I really need antivirus on Linux?
- For desktop workstations the risk is low, but servers handling file uploads, email, or web content benefit significantly. ClamAV is also useful for scanning files destined for Windows users, stopping cross-platform threats at the Linux gateway.
- What is the difference between clamscan and clamdscan?
- clamscan loads signatures from disk on every run, which is slow but requires no running daemon. clamdscan connects to the clamd daemon that keeps signatures in memory, making repeated scans much faster.
- How often should I update ClamAV signatures?
- At least once per day. The official freshclam default is 12 checks per day. Running the clamav-freshclam service or timer achieves this automatically without manual effort.
- Will clamscan catch rootkits and kernel-level malware?
- No. ClamAV is a file-based scanner targeting known malware signatures — it is not designed for rootkit detection. Use dedicated tools like rkhunter or chkrootkit alongside ClamAV for broader coverage.
- Can I scan only files changed in the last 24 hours to save time?
- Yes. Pipe find output into clamscan: find /home -mtime -1 -type f | xargs clamscan --infected. This is much faster than a full recursive scan and works well for frequent automated checks.
Related guides
Manage Secrets with Ansible Vault
Encrypt Ansible secrets with AES-256 using ansible-vault: encrypt files and inline vars, automate with password files, and isolate group-level secrets with vault IDs.
AppArmor Explained
Learn how AppArmor profiles work, how to switch between enforce and complain mode, create new profiles, and diagnose access denials on Ubuntu, Debian, and Arch.
Apply CIS Benchmarks with OpenSCAP
Use OpenSCAP and scap-security-guide to evaluate, report on, and remediate Linux systems against CIS Benchmarks — covering install, eval, and automation.
How to Audit a Linux System with auditd
Set up auditd on Linux to track file access, syscalls, and privilege use. Covers persistent rules, file watches, ausearch, and aureport across major distros.