commit dc7ff2e8adab1de242d36268f442588a11566a5d Author: jonas Date: Thu Feb 29 17:13:53 2024 +0100 first commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..7a9e272 --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ +# Printer Admin Script for IServ +A small collection of useful commands not available out-of-the-box to manage CUPS printers on an IServ server. + +## Running the script +Either use wget/curl to download the script and run it seperately like so: + +``` +# wget -O printer.sh "" +# bash printer.sh ... +``` + +or run it directly from the web (usually rather discouraged): + +``` +# wget -O- "" | bash - +``` + +## Usage +``` +printer.sh list Lists all printers +printer.sh duplicate Duplicates a printer +printer.sh dup Alias of 'duplicate' +printer.sh rename Renames a printer internally +printer.sh ren Alias of 'rename' +printer.sh clear-queue Clears the current queue of a printer +printer.sh cq Alias of 'clear-queue' +``` \ No newline at end of file diff --git a/printer.sh b/printer.sh new file mode 100644 index 0000000..8a0bef0 --- /dev/null +++ b/printer.sh @@ -0,0 +1,216 @@ +#!/bin/bash +set -e + +function usage { + echo "Script usage:" + echo "" + echo "${0} list Lists all printers" + echo "${0} duplicate Duplicates a printer" + echo "${0} dup Alias of 'duplicate'" + echo "${0} rename Renames a printer internally" + echo "${0} ren Alias of 'rename'" + echo "${0} clear-queue Clears the current queue of a printer" + echo "${0} cq Alias of 'clear-queue'" +} + +## +# Ensures the 'uuid' command is installed +## +function ensure_uuid_command { + if ! which uuid >/dev/null; then + echo "Installing required 'uuid' package via apt-get..." + DEBIAN_FRONTEND=noninteractive apt-get install -q --yes uuid >/dev/null + echo "OK" + fi +} + +## +# Lists all internal names of available printers +# +# @echo List of all available printers +## +function list { + echo "Available printers:" + lpstat -v | awk '!/ iserv:/{ gsub(":", "", $3); print $3 }' +} + +## +# Creates a duplicate of an existing printer +# +# @param $1 Internal name of the printer +## +function printer_duplicate { + ensure_uuid_command + + PRINTER=${1} + echo "Duplicating printer '${PRINTER}'..." + + if [ "${PRINTER}" = "" ]; then + echo "No printer specified!" + exit 1 + elif [ "${PRINTER}" = "iserv" ]; then + echo "IServ built-in printer 'iserv' cannot be duplicated!" + exit 1 + fi + + TEMP_CONF_FILE=$(mktemp) + sed -n '//,/<\/Printer>/p' /etc/cups/printers.conf > ${TEMP_CONF_FILE} + + if (( $(stat --printf="%s" ${TEMP_CONF_FILE}) == 0 )); then + echo "Printer not found!" + rm ${TEMP_CONF_FILE} + exit 1 + fi + + NEXT_ID=$(next_printer_id) + + # Set printer ID + sed -i 's/^PrinterId [0-9]\+/PrinterId '${NEXT_ID}'/' ${TEMP_CONF_FILE} + + # Change printer UUID + sed -i 's/^UUID urn:uuid:.\+$/UUID urn:uuid:'$(uuid)'/' ${TEMP_CONF_FILE} + + # Append '_duplicate' to printer name + sed -i 's/^$//' ${TEMP_CONF_FILE} + + # Update printer description + sed -i 's/^Info \(.\+\),/Info Duplicate of \1,/' ${TEMP_CONF_FILE} + + # Change ConfigTime to now + sed -i 's/^ConfigTime [0-9]\+/ConfigTime '$(date +%s)'/' ${TEMP_CONF_FILE} + + # Change StateTime to now + sed -i 's/^StateTime [0-9]\+/StateTime '$(date +%s)'/' ${TEMP_CONF_FILE} + + # Set printer state to idle + sed -i 's/^State .\+$/State Idle/' ${TEMP_CONF_FILE} + sed -i 's/^StateMessage .\+$//' ${TEMP_CONF_FILE} + sed -i 's/^Reason .\+$//' ${TEMP_CONF_FILE} + + # Add new configuration to CUPS + systemctl stop cups + cat ${TEMP_CONF_FILE} >> /etc/cups/printers.conf + systemctl start cups + + rm "${TEMP_CONF_FILE}" + echo "OK" +} + +## +# Renames a printer internally +# +# @param $1 Current internal name of the printer +# @param $2 New internal name of the printer +## +function printer_rename { + PRINTER=${1} + NEW_NAME=${2} + echo "Renaming printer '${PRINTER}' to '${NEW_NAME}'..." + + if [ "${PRINTER}" = "" ]; then + echo "No printer specified!" + exit 1 + elif [ "${NEW_NAME}" = "" ]; then + echo "No new name specified!" + exit 1 + elif [ "${PRINTER}" = "iserv" ]; then + echo "IServ built-in printer 'iserv' cannot be renamed!" + exit 1 + fi + + if ! grep -qE '^[a-zA-Z0-9_]+$' <<< "${NEW_NAME}"; then + echo "Invalid characters in new name '${NEW_NAME}'!" + echo "Valid characters are: A-Z a-z 0-9 _" + exit 1 + fi + + if ! grep -qE "^" /etc/cups/printers.conf; then + echo "Printer not found!" + exit 1 + fi + + echo "Renaming the printer will drop all current pages in the queue!" + echo -n "Continue ? " + read CHOICE + + if [ "${CHOICE}" != "y" ]; then + echo "Operation cancelled" + exit 1 + fi + + cp /etc/cups/printers.conf /etc/cups/printers.conf.ren_bak + + # Stop CUPS, rename, restart CUPS + systemctl stop cups + sed -i 's/$//' /etc/cups/printers.conf + systemctl start cups + + echo "OK" +} + +## +# Clears the printing queue of a printer +# +# @param $1 Internal name of the printer +## +function printer_clear_queue { + PRINTER=${1} + echo "Clearing printing queue of '${PRINTER}'..." + + if [ "${PRINTER}" = "" ]; then + echo "No printer specified!" + exit 1 + fi + + if ! lpstat -e | grep -q "${PRINTER}"; then + echo "Printer not found!" + exit 1 + fi + + lprm -P "${PRINTER}" - + echo "OK" +} + +## +# Fetches the next free printer ID +# +# @echo Next available printer ID +## +function next_printer_id { + HIGHEST_ID=-1 + + while read LINE; do + if grep -qE "^PrinterId" <<< "${LINE}"; then + PRINTER_ID=$(awk '/PrinterId/{ print $2 }' <<< "${LINE}") + + if (( PRINTER_ID > HIGHEST_ID )); then + HIGHEST_ID=${PRINTER_ID} + fi + fi + done < /etc/cups/printers.conf + + (( HIGHEST_ID++ )) + echo ${HIGHEST_ID} +} + +case "$1" in + duplicate|dup) + shift + printer_duplicate $@ + ;; + rename|ren) + shift + printer_rename $@ + ;; + clear-queue|cq) + shift + printer_clear_queue $@ + ;; + list) + list + ;; + *) + usage + exit 1 + ;; +esac \ No newline at end of file