Skip to content

Instantly share code, notes, and snippets.

@michaelgugino
Created April 15, 2026 12:56
Show Gist options
  • Select an option

  • Save michaelgugino/9e2b1f9d8c86b50a022f9d0eb3a6c42b to your computer and use it in GitHub Desktop.

Select an option

Save michaelgugino/9e2b1f9d8c86b50a022f9d0eb3a6c42b to your computer and use it in GitHub Desktop.
printer debug script
#!/usr/bin/env bash
set -u
printer_host="${PRINTER_HOST:-EPSON22EB48.local}"
printer_ip="${PRINTER_IP:-192.168.254.158}"
queue_name="${QUEUE_NAME:-EPSON_ET_2800_IPPS}"
queue_uri="${QUEUE_URI:-}"
submit_test_print="false"
output_path=""
usage() {
cat <<'EOF'
Usage: ./compare_fedora_printing.sh [options]
Collects a reproducible diagnostic bundle for comparing Fedora printing behavior
across systems. Safe by default: read-only unless --submit-test-print is used.
Options:
--output PATH Write output to PATH instead of stdout
--printer-host HOST Default: EPSON22EB48.local
--printer-ip IP Default: 192.168.254.158
--queue-name NAME Default: EPSON_ET_2800_IPPS
--queue-uri URI Optional explicit queue URI to record
--submit-test-print Submit one test job with lp to the queue
--help Show this message
Examples:
./compare_fedora_printing.sh --output fedora43.txt
./compare_fedora_printing.sh --output fedora41.txt --queue-name OfficePrinter
sudo ./compare_fedora_printing.sh --submit-test-print --output repro.txt
EOF
}
while [ "$#" -gt 0 ]; do
case "$1" in
--output)
output_path="${2:-}"
shift 2
;;
--printer-host)
printer_host="${2:-}"
shift 2
;;
--printer-ip)
printer_ip="${2:-}"
shift 2
;;
--queue-name)
queue_name="${2:-}"
shift 2
;;
--queue-uri)
queue_uri="${2:-}"
shift 2
;;
--submit-test-print)
submit_test_print="true"
shift
;;
--help|-h)
usage
exit 0
;;
*)
echo "Unknown option: $1" >&2
usage >&2
exit 1
;;
esac
done
if [ -n "$output_path" ]; then
exec >"$output_path" 2>&1
fi
section() {
echo ""
echo "### $1"
}
have_cmd() {
command -v "$1" >/dev/null 2>&1
}
run_with_timeout() {
local seconds="$1"
shift
if have_cmd timeout; then
timeout --signal=TERM "${seconds}" "$@" 2>&1
else
"$@" 2>&1
fi
}
run() {
local title="$1"
shift
section "$title"
if have_cmd "$1"; then
"$@" 2>&1 || echo "command failed: $*"
else
echo "missing: $1"
fi
}
run_shell() {
local title="$1"
local cmd="$2"
section "$title"
if have_cmd timeout; then
timeout --signal=TERM 30s bash -lc "$cmd" 2>&1 || echo "command failed: $cmd"
else
bash -lc "$cmd" 2>&1 || echo "command failed: $cmd"
fi
}
note() {
section "$1"
shift
printf '%s\n' "$@"
}
start_time="$(date --iso-8601=seconds)"
test_job_time=""
note "Run Context" \
"start_time: ${start_time}" \
"hostname: $(hostname)" \
"user: $(id -un)" \
"uid: $(id -u)" \
"cwd: $(pwd)" \
"printer_host: ${printer_host}" \
"printer_ip: ${printer_ip}" \
"queue_name: ${queue_name}" \
"queue_uri: ${queue_uri:-<not provided>}" \
"submit_test_print: ${submit_test_print}"
run "Date" date
run "Kernel" uname -a
run "OS Release" cat /etc/os-release
run_shell "Installed Package Versions" \
"rpm -q cups cups-client cups-filesystem cups-libs cups-filters cups-filters-driverless cups-browsed cups-ipptool ghostscript libppd 2>/dev/null"
run_shell "Backend/Filter Ownership" \
"rpm -qf /usr/lib/cups/backend/ipp /usr/lib/cups/backend/ipps /usr/lib/cups/filter/pdftopdf /usr/lib/cups/filter/gstoraster 2>/dev/null"
run_shell "RPM Verify (printing stack)" \
"rpm -V cups cups-client cups-filesystem cups-libs cups-filters cups-filters-driverless cups-browsed ghostscript libppd 2>/dev/null"
run "SELinux Mode" getenforce
run_shell "Recent AVCs" "ausearch -m AVC -ts recent | tail -n 50"
run "Systemd Status (cups)" systemctl status cups --no-pager
run "Systemd Status (cups.socket)" systemctl status cups.socket --no-pager
run "Systemd Status (cups.path)" systemctl status cups.path --no-pager
run "Systemd Status (cups-browsed)" systemctl status cups-browsed --no-pager
run "Systemd Status (avahi-daemon)" systemctl status avahi-daemon --no-pager
run_shell "Systemd Show (cups*)" \
"systemctl show cups.service cups.socket cups.path -p ActiveState,SubState,UnitFileState,Result,ExecMainStatus,ActiveEnterTimestamp,ActiveExitTimestamp"
run "CUPS Config Directory" ls -la /etc/cups
run_shell "CUPS Config Files" "sed -n '1,220p' /etc/cups/cupsd.conf && printf '\n' && sed -n '1,220p' /etc/cups/cups-browsed.conf"
run_shell "CUPS Printers Config" "sed -n '1,260p' /etc/cups/printers.conf"
run_shell "CUPS PPD Directory" "ls -la /etc/cups/ppd"
run_shell "Queue PPD Snippet" "sed -n '1,220p' /etc/cups/ppd/${queue_name}.ppd"
run "lpstat -t" lpstat -t
run "lpstat -v" lpstat -v
run "lpoptions -p queue -l" lpoptions -p "${queue_name}" -l
run "lpinfo -v" lpinfo -v
run_shell "Discovered Epson Devices" "lpinfo -v 2>/dev/null | grep -i epson"
run_shell "DNS-SD Browse (_ipp)" "avahi-browse -rt _ipp._tcp"
run_shell "DNS-SD Browse (_ipps)" "avahi-browse -rt _ipps._tcp"
section "Python IPP Probe"
if [ -x ./fetch_ipp_attrs.py ]; then
run_with_timeout 20s ./fetch_ipp_attrs.py || echo "command failed: ./fetch_ipp_attrs.py"
else
echo "missing or not executable: ./fetch_ipp_attrs.py"
fi
run_shell "Direct IPP get-printer-attributes (host)" \
"timeout --signal=TERM 20s ipptool -tv ipp://${printer_host}:631/ipp/print /usr/share/cups/ipptool/get-printer-attributes.test"
run_shell "Direct IPPS get-printer-attributes (host)" \
"timeout --signal=TERM 20s ipptool -E -tv ipps://${printer_host}:631/ipp/print /usr/share/cups/ipptool/get-printer-attributes.test"
run_shell "Direct IPPS get-printer-attributes (ip)" \
"timeout --signal=TERM 20s ipptool -E -tv ipps://${printer_ip}:631/ipp/print /usr/share/cups/ipptool/get-printer-attributes.test"
run_shell "Direct IPP get-jobs (host)" \
"timeout --signal=TERM 20s ipptool -tv ipp://${printer_host}:631/ipp/print /usr/share/cups/ipptool/get-jobs.test"
run_shell "Direct IPPS get-jobs (host)" \
"timeout --signal=TERM 20s ipptool -E -tv ipps://${printer_host}:631/ipp/print /usr/share/cups/ipptool/get-jobs.test"
run_shell "Direct IPPS get-jobs (ip)" \
"timeout --signal=TERM 20s ipptool -E -tv ipps://${printer_ip}:631/ipp/print /usr/share/cups/ipptool/get-jobs.test"
run_shell "Local Queue Attributes" \
"timeout --signal=TERM 20s ipptool -tv ipp://localhost/printers/${queue_name} /usr/share/cups/ipptool/get-printer-attributes.test"
run_shell "Local Queue Jobs" \
"timeout --signal=TERM 20s ipptool -tv ipp://localhost/printers/${queue_name} /usr/share/cups/ipptool/get-jobs.test"
run_shell "cupsfilter Test Render" \
"tmp_out=/tmp/${queue_name}_compare_test.urf; rm -f \"\$tmp_out\"; cupsfilter -p /etc/cups/ppd/${queue_name}.ppd -m image/urf /usr/share/cups/data/testprint >\"\$tmp_out\" && ls -l \"\$tmp_out\""
if [ "$submit_test_print" = "true" ]; then
test_job_time="$(date --iso-8601=seconds)"
note "Submitting Test Print" \
"submitted_at: ${test_job_time}" \
"command: lp -d ${queue_name} /usr/share/cups/data/testprint"
if have_cmd lp; then
lp -d "${queue_name}" /usr/share/cups/data/testprint 2>&1 || echo "command failed: lp -d ${queue_name} /usr/share/cups/data/testprint"
sleep 5
run "lpstat -t (after test print)" lpstat -t
run "lpstat -W not-completed -o" lpstat -W not-completed -o
run "lpstat -W completed -o | tail" bash -lc "lpstat -W completed -o | tail"
else
echo "missing: lp"
fi
fi
run_shell "Recent CUPS Journal (since start)" \
"journalctl -u cups --since '${start_time}' --no-pager"
if [ -n "$test_job_time" ]; then
run_shell "CUPS Journal (since test print)" \
"journalctl -u cups --since '${test_job_time}' --no-pager"
fi
run_shell "Recent CUPS + systemd Boot Journal" \
"journalctl -b --no-pager | grep -E 'cupsd|cups\\.service|cups\\.socket|cups\\.path|cups-browsed|gstoraster|pdftopdf|backend/ipps|backend/ipp|EPSON_ET_2800|ipp-conformance|wrong-http-version' || true"
run_shell "Current Job Snapshot" \
"lpstat -t && printf '\n' && lpq -a"
note "Comparison Checklist" \
"Run this script on Fedora 41 and Fedora 43 with the same printer state and queue name." \
"Diff the outputs, focusing on package versions, direct ipptool behavior, queue URI/options, and cups journal lines after Print-Job." \
"If Fedora 41 succeeds and Fedora 43 fails at the same layer, that layer is your bug candidate." \
"If only GUI-triggered runs fail, repeat with --submit-test-print to keep GNOME out of the repro."
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment