Created
April 15, 2026 12:56
-
-
Save michaelgugino/9e2b1f9d8c86b50a022f9d0eb3a6c42b to your computer and use it in GitHub Desktop.
printer debug script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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