537 words, 3 min read

When integrating antivirus scanning into a Linux application or upload pipeline, clamdscan is usually a much better choice than clamscan.

While clamscan starts a full standalone scan process and loads virus signatures every time, clamdscan talks to the long-running clamd daemon. This makes scans significantly faster and more suitable for production environments.

One particularly useful option is --fdpass.

What does --fdpass do?

Normally, clamd runs under its own user account, such as clamav. This can create permission issues when scanning files owned by another user or temporary upload files.

The --fdpass option solves this by passing the already opened file descriptor to the daemon instead of letting the daemon reopen the file itself.

This is especially useful for:

  • Upload processing
  • Temporary files
  • Restricted file permissions
  • CI/CD pipelines
  • Web applications

Installing ClamAV

On Debian or Ubuntu systems:

sudo apt update
sudo apt install clamav clamav-daemon

Update the virus definitions:

sudo freshclam

Enabling clamd on startup

To ensure the daemon automatically starts after a reboot:

sudo systemctl enable clamav-daemon
sudo systemctl start clamav-daemon

Verify the service is running:

sudo systemctl status clamav-daemon

On some distributions, the service may be named clamd instead.

Verifying the socket configuration

clamdscan communicates with the daemon through a Unix socket.

Check the configured socket path:

grep LocalSocket /etc/clamav/clamd.conf

Typical values are:

LocalSocket /run/clamav/clamd.ctl

or:

LocalSocket /var/run/clamav/clamd.ctl

You can also locate the socket manually:

sudo find /run /var/run -name "*.ctl"

Scanning a file

To scan a file quietly:

clamdscan --fdpass --quiet myfile.zip

If the file is clean, the command exits with status code 0.

If malware is detected, the exit code becomes 1.

Example in a shell script:

if clamdscan --fdpass --quiet upload.pdf; then
echo "File is clean"
else
echo "Virus detected"
fi

Why use clamdscan instead of clamscan?

clamdscan has several advantages:

  • Much faster scanning
  • Lower memory usage
  • Better suited for concurrent workloads
  • No repeated signature loading
  • Ideal for web servers and APIs

For applications handling many uploads or background jobs, using clamdscan --fdpass is generally the recommended setup.

Common error

If you encounter:

ERROR: Could not connect to clamd on LocalSocket

the daemon is usually not running.

Start it manually:

sudo systemctl start clamav-daemon

Then retry the scan command.

Understanding exit codes

When integrating clamdscan into an application or upload pipeline, it is important to distinguish between an actual virus detection and a technical failure.

Fortunately, clamdscan provides clear exit codes for this.

Exit code Meaning
0 No virus found
1 Virus found
2 Scanner error or operational failure

This means you should avoid parsing stdout or stderr to determine the scan result. Instead, rely on the process exit code directly.

Example:

clamdscan --fdpass --quiet upload.pdf
result=$?
case $result in
0)
echo "File is clean"
;;
1)
echo "Virus detected"
;;
2)
echo "Scan failed"
;;
esac

This distinction is especially important in automated systems:

  • Exit code 1 means the scanner worked correctly and detected malware

  • Exit code 2 means something operational failed, such as:

    • clamd not running
    • socket connection failures
    • permission issues
    • corrupted scanner configuration

In production systems, a virus detection is usually a business-level validation failure, while exit code 2 should typically trigger retries, logging, monitoring, or alerts.