CUPS 打印服务完全指南 / 第 8 章:过滤器与后端
第 8 章:过滤器与后端
过滤器和后端是 CUPS 的核心组件,负责文档格式转换和打印数据传输。本章将深入解析 CUPS 的过滤器系统、后端架构以及自定义过滤器开发。
8.1 过滤器系统概述
8.1.1 过滤器在打印栈中的角色
输入文档 (PDF/PS/Text/Image/Office)
│
▼
┌──────────────────────────────────────────────┐
│ MIME 类型检测 │
│ /etc/cups/mime.types │
│ application/pdf pdf string(0,"%PDF") │
├──────────────────────────────────────────────┤
│ 过滤器链 (Filter Chain) │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐│
│ │ 过滤器 1 │──▶│ 过滤器 2 │──▶│ 过滤器 N ││
│ │ PDF→PS │ │ PS→光栅 │ │ 光栅→PCL ││
│ └──────────┘ └──────────┘ └──────────┘│
├──────────────────────────────────────────────┤
│ 打印机驱动 │
│ rastertopclx / rastertohp / ... │
├──────────────────────────────────────────────┤
│ 后端 (Backend) │
│ usb / socket / ipp / lpd / dnssd │
└──────────────────────────────────────────────┘
│
▼
打印机硬件
8.1.2 过滤器与后端文件位置
# 过滤器位置
ls /usr/lib/cups/filter/
# 后端位置
ls /usr/lib/cups/backend/
# MIME 类型定义
cat /etc/cups/mime.types
# MIME 转换规则
cat /etc/cups/mime.convs
# 查看所有过滤器
find /usr/lib/cups/filter -type f -executable
# 查看所有后端
find /usr/lib/cups/backend -type f -executable
8.1.3 核心过滤器列表
| 过滤器 | 功能 | 输入 → 输出 |
|---|---|---|
pdftops | PDF 转 PostScript | application/pdf → application/postscript |
pdftoraster | PDF 转光栅 | application/pdf → application/vnd.cups-raster |
pdftoijs | PDF 转 IJS | application/pdf → application/vnd.cups-command |
imagetops | 图像转 PS | image/* → application/postscript |
imagetoraster | 图像转光栅 | image/* → application/vnd.cups-raster |
texttops | 文本转 PS | text/plain → application/postscript |
texttopdf | 文本转 PDF | text/plain → application/pdf |
texttoraster | 文本转光栅 | text/plain → application/vnd.cups-raster |
pstopdf | PS 转 PDF | application/postscript → application/pdf |
pstops | PS 处理 | application/postscript → application/postscript |
gstopxl | GS 转 PCL-XL | application/postscript → application/vnd.hp-pclxl |
rastertopclx | 光栅转 PCL-XL | application/vnd.cups-raster → application/vnd.hp-pclxl |
rastertohp | 光栅转 PCL | application/vnd.cups-raster → application/vnd.hp-pcl |
imagetopdf | 图像转 PDF | image/* → application/pdf |
mupdftoraster | MuPDF 转光栅 | application/pdf → application/vnd.cups-raster |
8.2 MIME 类型系统
8.2.1 MIME 类型定义文件
# MIME 类型定义
cat /etc/cups/mime.types
示例内容:
# /etc/cups/mime.types
# PDF 文件检测
application/pdf pdf string(0,"%PDF")
# PostScript 文件检测
application/postscript ai eps ps string(0,"%!")
# 纯文本文件检测
text/plain txt string(0,#!) print("/bin/sh") print("/bin/bash") print("/usr/bin/env")
text/plain txt asc c cc h hh cpp cxx hxx java pl py rb
# 图像文件检测
image/jpeg jpg jpeg string(0,\377\330\377\340) string(0,\377\330\377\341)
image/png png string(0,\211PNG)
image/gif gif string(0,GIF87a) string(0,GIF89a)
image/tiff tif tiff string(0,MM\000\052) string(0,II\052\000)
image/bmp bmp string(0,BM)
# HP-GL/2 文件
application/vnd.hp-HPGL hpgl string(0,IN;) string(0,IN\n)
# CUPS 光栅数据
application/vnd.cups-raster string(0,RaSt)
application/vnd.cups-pdf string(0,%PDF)
# OpenDocument
application/vnd.oasis.opendocument.text odt zip(string(0,PK\003\004),filename="mimetype",content="application/vnd.oasis.opendocument.text")
# Microsoft Office
application/msword doc zip(string(0,PK\003\004),filename="[Content_Types].xml",content="word/")
application/vnd.openxmlformats-officedocument.wordprocessingml.document docx zip(string(0,PK\003\004),filename="[Content_Types].xml",content="word/")
8.2.2 MIME 类型检测规则
# MIME 类型检测语法
# 类型 扩展名 检测规则
# 检测规则类型:
# string(offset, "content") - 字符串匹配
# char(offset, value) - 字节匹配
# icalendar(offset) - iCalendar 检测
# pdf(offset) - PDF 特征检测
# zip(offset, filename, content) - ZIP 内文件检测
# 示例:
# 检测 PDF 文件 (%PDF 在文件开头)
application/pdf pdf string(0,"%PDF")
# 检测 ZIP 文件中的 Office 文档
application/vnd.openxmlformats-officedocument.wordprocessingml.document
docx zip(string(0,PK\003\004),
filename="[Content_Types].xml",
content="word/")
# 检测 ELF 二进制文件
application/x-executable * string(0,\177ELF)
8.2.3 自定义 MIME 类型
# 添加自定义 MIME 类型
sudo vim /etc/cups/mime.types
# 添加自定义文件类型
application/x-custom cust string(0,"CUSTOM1.0")
# 添加新的 Office 格式
application/vnd.lotus-1-2-3 wks wk1 wk3 wk4 string(0,\000\000\002\000)
8.3 MIME 转换规则
8.3.1 转换规则文件
# MIME 转换规则
cat /etc/cups/mime.convs
示例内容:
# /etc/cups/mime.convs
# PDF 转 PostScript
application/pdf application/postscript 33 pdftops
# PDF 转 CUPS Raster
application/pdf application/vnd.cups-raster 50 pdftoraster
# PostScript 转 CUPS Raster
application/postscript application/vnd.cups-raster 50 gstoraster
# 文本转 PostScript
text/plain application/postscript 33 texttops
# 文本转 CUPS Raster
text/plain application/vnd.cups-raster 50 texttoraster
# 图像转 PostScript
image/jpeg application/postscript 33 imagetops
image/png application/postscript 33 imagetops
image/gif application/postscript 33 imagetops
# 图像转 CUPS Raster
image/jpeg application/vnd.cups-raster 50 imagetoraster
# PostScript 转 PCL
application/postscript application/vnd.hp-pcl 50 gstopxl
# PostScript 转 PDF
application/postscript application/pdf 33 pstopdf
# CUPS Raster 转 PCL-XL
application/vnd.cups-raster application/vnd.hp-pclxl 50 rastertopclx
# CUPS Raster 转 HP PCL
application/vnd.cups-raster application/vnd.hp-pcl 50 rastertohp
8.3.2 转换规则语法
# 语法格式:
# 源类型 目标类型 优先级 过滤器程序
# 参数说明:
# 源类型: 输入文档的 MIME 类型
# 目标类型: 输出文档的 MIME 类型
# 优先级: 数字越小优先级越高 (0-100)
# 过滤器: 转换程序路径或名称
# 优先级说明:
# 0-10: 系统保留
# 11-30: 高优先级
# 31-50: 中优先级
# 51-70: 低优先级
# 71-100: 很少使用
8.3.3 自定义转换规则
# 添加自定义转换规则
sudo vim /etc/cups/mime.convs
# 添加 Office 文档转换规则
application/msword application/pdf 50 doc2pdf
application/vnd.openxmlformats-officedocument.wordprocessingml.document application/pdf 50 docx2pdf
# 添加自定义图像转换规则
application/x-custom application/postscript 33 custom2ps
8.4 过滤器工作流程
8.4.1 完整转换链示例
场景:打印 PDF 文件到 PCL 打印机
输入: document.pdf (application/pdf)
│
▼
过滤器 1: pdftops
│ 输入: application/pdf
│ 输出: application/postscript
│ 优先级: 33
▼
过滤器 2: gstopxl
│ 输入: application/postscript
│ 输出: application/vnd.hp-pclxl
│ 优先级: 50
▼
后端: socket
│ 传输: application/vnd.hp-pclxl
│ 目标: socket://192.168.1.100:9100
▼
打印机: HP LaserJet Pro M404
8.4.2 查看转换链
# 使用 cupsfilter 查看转换链
cupsfilter -m application/pdf -p myprinter /dev/null 2>&1
# 输出示例:
# pdftops (PID 1234) application/pdf → application/postscript
# pstops (PID 1235) application/postscript → application/postscript
# gstopxl (PID 1236) application/postscript → application/vnd.hp-pclxl
# 使用 verbose 模式查看详细信息
cupsfilter -v -m application/pdf -p myprinter /dev/null
8.4.3 测试过滤器
# 手动测试过滤器
# PDF 转 PostScript
cupsfilter -m application/postscript document.pdf > output.ps
# PDF 转光栅
cupsfilter -m application/vnd.cups-raster document.pdf > output.raster
# 文本转 PostScript
echo "Hello World" | cupsfilter -m application/postscript > output.ps
# 使用特定打印机配置
cupsfilter -d myprinter -m application/postscript document.pdf > output.ps
8.5 常用过滤器详解
8.5.1 pdftops
# pdftops 将 PDF 转换为 PostScript
# 使用 Poppler 库实现
# 测试 pdftops
pdftops document.pdf output.ps
# 选项:
# -level1 使用 PostScript Level 1
# -level2 使用 PostScript Level 2
# -level3 使用 PostScript Level 3 (默认)
# -nocrop 不裁剪页面
# -expand 扩展页面
# -noshrink 不收缩页面
# -nocenter 不居中页面
# -landscape 横向打印
# -paper size 设置纸张大小
# -form 生成表单
# 测试命令
pdftops -level2 -paper A4 document.pdf output.ps
8.5.2 pdftoraster
# pdftoraster 将 PDF 转换为 CUPS Raster 格式
# 使用 Poppler 或 MuPDF
# 测试 pdftoraster
pdftoraster document.pdf > output.raster
# CUPS Raster 格式:
# - 包含页面头信息
# - 包含光栅图像数据
# - 支持多种颜色空间
# - 支持多种分辨率
8.5.3 imagetops
# imagetops 将图像转换为 PostScript
# 支持 JPEG, PNG, GIF, BMP, TIFF 等
# 测试 imagetops
imagetops image.jpg > output.ps
# 选项通过环境变量传递:
# FINAL_CONTENT_TYPE 输出内容类型
# PRINTER 打印机名称
# copies 打印份数
# media 纸张大小
# number-up 每页多版
# orientation-requested 方向
# page-bottom 下边距
# page-left 左边距
# page-right 右边距
# page-top 上边距
# scaling 缩放比例
# sides 双面打印
8.5.4 texttops
# texttops 将纯文本转换为 PostScript
# 测试 texttops
texttops document.txt > output.ps
# 选项:
# -c columns 每页列数
# -f font-name 字体名称
# -m 使用等宽字体
# -n copies 打印份数
# -p 纵向打印
# -r 横向打印
# -s 严格换页
# 示例
texttops -f Courier -c 80 document.txt > output.ps
8.5.5 Ghostscript 过滤器
# Ghostscript 相关过滤器
ls /usr/lib/cups/filter/ | grep -i ghost
# gstoraster: PS/PDF 转 CUPS Raster
gstoraster document.ps > output.raster
# gstopxl: PS 转 PCL-XL
gstopxl document.ps > output.pxl
# gstopclm: PS 转 PCLm
gstopclm document.ps > output.pclm
# Ghostscript 设备列表
gs -h 2>&1 | grep -A 50 "Available devices:" | head -30
8.6 后端系统
8.6.1 后端概述
| 后端 | 功能 | URI 格式 |
|---|---|---|
usb | USB 打印机 | usb://Make/Model?serial=xxx |
socket | TCP/IP Socket | socket://host:port |
ipp | IPP 协议 | ipp://host/ipp/print |
ipps | IPP over TLS | ipps://host/ipp/print |
lpd | LPD 协议 | lpd://host/queue |
http | HTTP 协议 | http://host/path |
https | HTTPS 协议 | https://host/path |
smb | Samba 共享 | smb://user:pass@host/printer |
dnssd | DNS-SD 发现 | dnssd://name._ipp._tcp.local./ |
beh | 后备后端 | beh:/path/to/real/backend |
serial | 串口 | serial:/dev/ttyS0 |
parallel | 并口 | parallel:/dev/lp0 |
hp | HP 打印机 | hp:/net/Model?ip=addr |
hpfax | HP 传真 | hpfax:/net/Model?ip=addr |
snmp | SNMP 发现 | snmp://host |
8.6.2 后端权限
# 后端程序需要特殊权限
# 查看后端权限
ls -la /usr/lib/cups/backend/
# 输出示例:
# -rwxr-xr-x 1 root root 45K usb
# -rwxr-xr-x 1 root root 34K socket
# -rwxr-xr-x 1 root root 56K ipp
# -rwsr-xr-x 1 root root 23K serial # SUID 位
# USB 后端需要特殊权限
sudo chmod 700 /usr/lib/cups/backend/usb
sudo chown root:root /usr/lib/cups/backend/usb
# 串口后端需要 SUID 位
sudo chmod 4755 /usr/lib/cups/backend/serial
8.6.3 后端测试
# 测试后端
# 列出可用后端
lpinfo -v
# 测试 socket 后端
/usr/lib/cups/backend/socket 1 1 user "test" 1 "" /tmp/test.ps
# 测试 IPP 后端
/usr/lib/cups/backend/ipp 1 1 user "test" 1 "" /tmp/test.ps
# 测试设备发现
/usr/lib/cups/backend/snmp
/usr/lib/cups/backend/dnssd
8.6.4 后备后端 (beh)
# 后备后端提供故障转移功能
# 当主后端失败时,自动切换到备选后端
# URI 格式:
# beh:/number_of_retries/delay/original_backend original_uri
# 示例:重试 3 次,每次间隔 5 秒
sudo lpadmin -p MyPrinter -E \
-v "beh:/3/5/socket/socket://192.168.1.100:9100" \
-P /usr/share/ppd/HP/hp-laserjet_pro_m404.ppd
# 使用 IPP 后备
sudo lpadmin -p MyPrinter -E \
-v "beh:/3/5/ipp/ipp://192.168.1.100/ipp/print" \
-m "everywhere"
8.7 自定义过滤器开发
8.7.1 过滤器接口规范
# CUPS 过滤器命令行接口:
# filter job-id user title copies options [file]
# 参数说明:
# job-id - 任务 ID
# user - 用户名
# title - 文档标题
# copies - 打印份数
# options - 打印选项(空格分隔)
# file - 输入文件(可选,不提供则从 stdin 读取)
# 输入: stdin 或 file
# 输出: stdout
# 日志: stderr
# 返回值:
# 0 - 成功
# 1 - 错误(任务将被取消)
# 2 - 错误(任务将被重试)
8.7.2 基础过滤器模板
#!/bin/bash
# /usr/lib/cups/filter/myfilter
# 简单的自定义过滤器示例
# 获取参数
JOB_ID="$1"
USER="$2"
TITLE="$3"
COPIES="$4"
OPTIONS="$5"
FILE="$6"
# 记录日志
echo "DEBUG: Filter started - Job: $JOB_ID, User: $USER, Title: $TITLE" >&2
# 处理输入
if [ -n "$FILE" ]; then
INPUT="$FILE"
else
INPUT="/dev/stdin"
fi
# 执行转换(这里只是示例,实际应实现转换逻辑)
cat "$INPUT"
echo "DEBUG: Filter completed successfully" >&2
exit 0
# 安装过滤器
sudo cp myfilter /usr/lib/cups/filter/myfilter
sudo chmod 755 /usr/lib/cups/filter/myfilter
sudo chown root:root /usr/lib/cups/filter/myfilter
8.7.3 Python 过滤器示例
#!/usr/bin/env python3
# /usr/lib/cups/filter/pdf-watermark.py
# PDF 水印过滤器
import sys
import os
import subprocess
from pathlib import Path
def add_watermark(input_file, watermark_text):
"""为 PDF 添加水印"""
try:
# 创建水印 PDF
watermark_ps = f"""
%!PS-Adobe-3.0
%%Title: Watermark
/Helvetica-Bold findfont 60 scalefont setfont
0.5 setgray
306 396 moveto
-45 rotate
({watermark_text}) stringwidth pop -2 div 0 rmoveto
({watermark_text}) show
"""
# 使用 Ghostscript 添加水印
cmd = [
'gs', '-dNOPAUSE', '-dBATCH', '-sDEVICE=pdfwrite',
'-sOutputFile=-', '-c',
f'<< /EndPage {{ 2 eq {{ pop false }} {{ /Helvetica-Bold findfont 60 scalefont setfont 0.5 setgray 306 396 moveto -45 rotate ({watermark_text}) show true }} ifelse }} bind >> setpagedevice',
'-f', input_file
]
result = subprocess.run(cmd, capture_output=True, text=True)
return result.stdout
except Exception as e:
print(f"ERROR: {e}", file=sys.stderr)
return None
def main():
if len(sys.argv) < 6:
print("Usage: pdf-watermark job user title copies options [file]", file=sys.stderr)
sys.exit(1)
job_id = sys.argv[1]
user = sys.argv[2]
title = sys.argv[3]
copies = sys.argv[4]
options = sys.argv[5]
input_file = sys.argv[6] if len(sys.argv) > 6 else None
# 解析选项
watermark_text = "CONFIDENTIAL"
for opt in options.split():
if opt.startswith("watermark="):
watermark_text = opt.split("=", 1)[1]
# 读取输入
if input_file:
with open(input_file, 'rb') as f:
data = f.read()
else:
data = sys.stdin.buffer.read()
# 临时文件处理
import tempfile
with tempfile.NamedTemporaryFile(suffix='.pdf', delete=False) as tmp:
tmp.write(data)
tmp_path = tmp.name
try:
result = add_watermark(tmp_path, watermark_text)
if result:
sys.stdout.buffer.write(result)
else:
# 如果处理失败,输出原始文件
sys.stdout.buffer.write(data)
finally:
os.unlink(tmp_path)
print(f"DEBUG: Watermark filter completed", file=sys.stderr)
sys.exit(0)
if __name__ == "__main__":
main()
# 安装 Python 过滤器
sudo cp pdf-watermark.py /usr/lib/cups/filter/pdf-watermark
sudo chmod 755 /usr/lib/cups/filter/pdf-watermark
8.7.4 注册自定义过滤器
# 注册 MIME 类型
sudo vim /etc/cups/mime.types
# 添加:
# application/x-watermarked-pdf wpdf string(0,"%PDF")
# 注册转换规则
sudo vim /etc/cups/mime.convs
# 添加:
# application/pdf application/x-watermarked-pdf 33 pdf-watermark
# 或者注册为覆盖特定打印机的过滤器
# 在 PPD 文件中添加:
# *cupsFilter: "application/pdf 0 pdf-watermark"
8.7.5 高级过滤器示例:文件类型转换
#!/bin/bash
# /usr/lib/cups/filter/office2pdf
# Office 文档转 PDF 过滤器
JOB_ID="$1"
USER="$2"
TITLE="$3"
COPIES="$4"
OPTIONS="$5"
FILE="$6"
LOGFILE="/var/log/cups/office2pdf.log"
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') $*" >> "$LOGFILE"
}
log "Starting office2pdf filter - Job: $JOB_ID, User: $USER"
# 获取输入文件类型
if [ -n "$FILE" ]; then
INPUT="$FILE"
FILE_TYPE=$(file -b --mime-type "$FILE")
else
# 保存 stdin 到临时文件
INPUT=$(mktemp /tmp/cups-XXXXXX)
cat > "$INPUT"
FILE_TYPE=$(file -b --mime-type "$INPUT")
trap "rm -f $INPUT" EXIT
fi
log "Input file type: $FILE_TYPE"
# 根据文件类型选择转换工具
case "$FILE_TYPE" in
application/msword|application/vnd.openxmlformats-officedocument.wordprocessingml.document)
# 使用 LibreOffice 转换
log "Converting Office document to PDF"
libreoffice --headless --convert-to pdf --outdir /tmp "$INPUT" 2>> "$LOGFILE"
PDF_FILE="/tmp/$(basename "${INPUT%.*}").pdf"
if [ -f "$PDF_FILE" ]; then
cat "$PDF_FILE"
rm -f "$PDF_FILE"
else
log "ERROR: LibreOffice conversion failed"
exit 1
fi
;;
application/pdf)
# 直接输出 PDF
cat "$INPUT"
;;
*)
log "Unsupported file type: $FILE_TYPE"
exit 1
;;
esac
log "Filter completed successfully"
exit 0
8.8 cupsfilter 命令详解
8.8.1 cupsfilter 基本用法
# 基本语法
cupsfilter [选项] [文件]
# 常用选项:
# -D 调试模式
# -d printer 使用指定打印机
# -m mime/type 输出 MIME 类型
# -n copies 打印份数
# -o option=value 打印选项
# -p ppd-file 使用指定 PPD 文件
# -t title 文档标题
# 测试 PDF 到 PostScript 转换
cupsfilter -m application/postscript document.pdf > output.ps
# 使用特定打印机
cupsfilter -d myprinter -m application/postscript document.pdf > output.ps
# 使用特定 PPD 文件
cupsfilter -p /usr/share/ppd/HP/hp-laserjet_pro_m404.ppd \
-m application/postscript document.pdf > output.ps
# 测试文本到光栅转换
echo "Test Page" | cupsfilter -m application/vnd.cups-raster > output.raster
8.8.2 cupsfilter 调试
# 启用详细输出
cupsfilter -v -m application/pdf document.pdf > /dev/null
# 输出示例:
# DEBUG: Loading printer "myprinter"
# DEBUG: Finding filter for application/pdf to application/postscript
# DEBUG: Running filter: pdftops 1234 user "Test" 1 "" document.pdf
# DEBUG: Filter completed with status 0
# 列出可用转换路径
cupsfilter -t application/pdf 2>&1 | head -20
# 测试完整转换链
cupsfilter -d myprinter -v document.pdf 2>&1
8.9 高级过滤器配置
8.9.1 过滤器链优化
# /etc/cups/mime.convs
# 优化转换路径
# 直接 PDF 到光栅(跳过 PostScript)
application/pdf application/vnd.cups-raster 33 pdftoraster
# 提高特定过滤器优先级
image/jpeg application/postscript 25 imagetops
# 禁用特定过滤器
# 不使用 texttops,改用 texttoraster
# text/plain application/postscript 33 texttops
text/plain application/vnd.cups-raster 33 texttoraster
8.9.2 环境变量
# CUPS 过滤器可用的环境变量
# FINAL_CONTENT_TYPE 最终输出类型
# PRINTER 打印机名称
# DEVICE_URI 设备 URI
# CONTENT_TYPE 输入内容类型
# SERVER_ADMIN 管理员邮箱
# CUPS_SERVER CUPS 服务器地址
# IPP_PORT IPP 端口
# LOCALE 语言环境
# 在过滤器中使用环境变量
echo "Printer: $PRINTER" >&2
echo "Device: $DEVICE_URI" >&2
echo "Content: $CONTENT_TYPE → $FINAL_CONTENT_TYPE" >&2
8.10 业务场景
8.10.1 场景一:Office 文档自动转换
# 需求:自动将 Office 文档转换为 PDF 打印
# 安装 LibreOffice
sudo apt install -y libreoffice-common
# 创建 Office 转 PDF 过滤器
sudo vim /usr/lib/cups/filter/office2pdf
# (参考上面的脚本)
# 注册 MIME 类型
sudo vim /etc/cups/mime.types
# 添加:
# application/msword doc string(0,\320\317\021\340\241\261\032\341)
# application/vnd.openxmlformats-officedocument.wordprocessingml.document
# docx zip(string(0,PK\003\004))
# 注册转换规则
sudo vim /etc/cups/mime.convs
# 添加:
# application/msword application/pdf 33 office2pdf
# application/vnd.openxmlformats-officedocument.wordprocessingml.document
# application/pdf 33 office2pdf
# 测试
lp -d myprinter document.docx
8.10.2 场景二:安全打印水印
# 需求:为敏感文档自动添加水印
# 使用 Python 过滤器
sudo vim /usr/lib/cups/filter/security-watermark
# (参考上面的 Python 脚本)
# 注册过滤器
sudo vim /etc/cups/mime.convs
# application/pdf application/x-watermarked-pdf 33 security-watermark
# 测试
lp -d myprinter -o watermark="CONFIDENTIAL" sensitive-document.pdf
8.10.3 场景三:打印日志记录
#!/bin/bash
# /usr/lib/cups/filter/audit-logger
# 审计日志过滤器(透明记录)
JOB_ID="$1"
USER="$2"
TITLE="$3"
COPIES="$4"
OPTIONS="$5"
FILE="$6"
# 记录打印活动
LOGFILE="/var/log/cups/audit.log"
echo "$(date '+%Y-%m-%d %H:%M:%S') | User: $USER | Job: $JOB_ID | Title: $TITLE | Copies: $COPIES | Options: $OPTIONS" >> "$LOGFILE"
# 计算文件大小
if [ -n "$FILE" ]; then
SIZE=$(stat -c%s "$FILE" 2>/dev/null || echo "0")
else
SIZE=$(cat | wc -c)
echo "$SIZE bytes" >> "$LOGFILE"
# 重新输出内容
cat /dev/stdin
fi
# 透明传递
cat "$FILE" 2>/dev/null || cat /dev/stdin
exit 0
8.11 扩展阅读
| 资源 | 链接 |
|---|---|
| CUPS 过滤器文档 | https://www.cups.org/doc/filter.html |
| Ghostscript 文档 | https://www.ghostscript.com/doc/ |
| Poppler 文档 | https://poppler.freedesktop.org/ |
| MIME 类型参考 | https://www.iana.org/assignments/media-types/ |
| CUPS 后端文档 | https://www.cups.org/doc/backend.html |
8.12 本章小结
| 主题 | 关键要点 |
|---|---|
| 过滤器 | 负责文档格式转换,按 MIME 类型链式调用 |
| 后端 | 负责与打印设备通信,支持 USB/网络/IPP 等 |
| MIME 类型 | 定义文件类型检测规则 |
| 转换规则 | 定义源类型到目标类型的转换路径 |
| 自定义过滤器 | 使用脚本或程序实现自定义转换逻辑 |
| cupsfilter | 测试和调试过滤器的命令行工具 |
下一章预告:我们将学习 CUPS 安全配置,包括认证、加密、TLS、访问控制和审计日志。
8.13 练习题
概念题:解释 CUPS 过滤器链的工作原理,以及 MIME 类型在其中的作用。
测试题:使用
cupsfilter命令将 PDF 文件转换为 PostScript,并查看转换过程。自定义题:编写一个简单的 bash 过滤器,为所有打印任务添加时间戳水印。
后端题:比较
socket、ipp和lpd三种后端的优缺点。场景题:设计一个过滤器方案,自动将所有 Office 文档转换为 PDF 后打印。