カッププリントサーバー:リリースされるまでローカルおよびリモートジョブを維持する方法は?

カッププリントサーバー:リリースされるまでローカルおよびリモートジョブを維持する方法は?

手動で印刷が解除されるまで、すべての印刷ジョブを保留するように私のカッププリントサーバーに指示したいと思います。

使用はcupsdisable --hold <printer or class>プリンタを一時停止し、lpoptions -p <printer> -o hold-job-until=indefiniteローカルに送信された印刷ジョブに対しては機能しますが、リモートで送信されたジョブでは機能しません。手動でリリースされるまですべての作業を維持するようにカップを設定するにはどうすればよいですか?

答え1

着信する各印刷ジョブを一時停止するように設定するマグ設定オプションが見つかりませんでした。私はタスクを実行するためにbashスクリプトを書いた。

#!/bin/bash

# cups_hold_new_jobs [<printer>]

# Resume a cups printer, set all queued and newly incoming jobs on
# hold, pause printer and exit.

# Runs as long as there are jobs in the print queue. Start from cron.

DEBUG=false


# --------- do not edit below ---------
VERSION=0.3
VERSION_INFO="(c) 2024 by Adrian Zaugg under GNU General Public License Version 3."

# initiate job list
declare -a JOBS

# set defaults
LOCK="/run/$(basename "$0")"
LOCKED=false
OWNPIDPPID="$$  $PPID   "


# get job list
function get_job_list() {
    JOBS=($(lpstat -o "$PRINTER" | sed -e 's/^\('"$PRINTER"'-[0-9]\+\).*$/\1/g'))
}


# DEBUG variable must be set to true or false
if [[ "$DEBUG" != "true" && "$DEBUG" != "false" ]]; then
    DEBUG=false
fi

# cups must be running
if [ $(lpstat -r | grep -c "is running") -eq 0 ]; then
    $DEBUG && echo "[INFO] CUPS is not running. Nothing to do." >&2
    exit 0
fi

# get printer (or class?)
PRINTER="$1"

# get default printer if none was given as an argument or check given printer name
if [ -z "$PRINTER" ]; then
    PRINTER="$(lpstat -p -d 2>/dev/null | grep "^system default destination: " | sed -e 's/^system default destination: //')"
    # check
    if [ -z "$PRINTER" ]; then
        echo "[ERROR] No printer given on command line and unable to detect default printer." >&2
        exit 1
    else
        $DEBUG && echo "No printer given on command line, using default printer: $PRINTER" >&2
    fi
else
    # no space, hash, slash or newline in printer names allowed
    PRINTER="$(echo "$PRINTER" | head -1 | sed -e "s%/.*$%%" -e "s/#.*$//" -e "s/ .*$//")"
    if [ ${#PRINTER} -lt ${#1} ]; then
        echo "[ERROR] Disallowed characters in printer name found."
        exit 1
    fi

    # check given printer exists
    ERR="$(lpstat -p "$PRINTER" 2>&1)"
    if [ $? -ne 0 ]; then
        # printer does not exist or other error
        echo "[ERROR] No printer printer \"$PRINTER\" found." >&2
        exit 1
    else
        $DEBUG && echo "Using printer: $PRINTER" >&2
    fi
fi

# lock
while ! $LOCKED; do
    mkdir "$LOCK" 2>/dev/null
    if [ $? -eq 0 ]; then
        LOCKED=true
        break;
    elif [ $(ps -e -o pid,ppid,command | sed -n "s/\([0-9]\{1,\}\)[^0-9]\{1,\}\([0-9]\{1,\}\)[^0-9]\(.*\)$/\1\t\2\t\3/p" | \
             grep -v "$OWNPIDPPID" | grep -cE 'bash .*/'"$(basename "${0}")"'$') -gt 1 ]; then
        # process already started
        $DEBUG && echo "Another instance of this script is already running." >&2
        exit 0
    else
        # stale lock, remove it
        rmdir "$LOCK" 2>/dev/null
        if [ $? -ne 0 ]; then
            echo "[ERROR] Removing stale lock $LOCK failed." >&2
            exit 1
        else
            $DEBUG && echo "Removed stale lock." >&2
        fi
    fi
done

# pause printer
if [ $(lpstat -p "$PRINTER" | grep -c -m 1 "$PRINTER disabled") -eq 0 ]; then
    cupsdisable "$PRINTER"
    $DEBUG && echo "Printer paused." >&2
fi
PRINTER_PAUSED=true

# loop as long as there are jobs in the queue
get_job_list
until [ ${#JOBS[@]} -eq 0 ]; do

    # find index of last held job in new job list
    last_held_job_index=0
    unset job_id
    while [[ "${JOBS[$last_held_job_index]}" != "$last_held_job_id" && $last_held_job_index -le ${#JOBS[@]} ]]; do
        last_held_job_index=$(($last_held_job_index+1))
    done
    if [ $last_held_job_index -eq ${#JOBS[@]} ]; then
        # job not found
        last_held_job_index=-1
    fi

    # set newly queued jobs on hold
    i=0
    for job_id in ${JOBS[@]}; do
        # compare index to marker of last held index
        if [ $i -gt $last_held_job_index ]; then
            # set job on hold
            ERR="$(lp -i "$job_id" -H hold 2>&1)"
            if [ $? -eq 0 ]; then
                echo -e "[INFO] holding job $job_id" >&2
            else
                echo "[ERROR] Failed to hold job \"$job_id\": $ERR" >&2
            fi
            # remember last index
            last_held_job_index=$i
        fi
        i=$(($i+1))
    done
    last_held_job_id="${JOBS[$last_held_job_index]}"

    # wait a bit
    sleep 1

    # reread jobs in print queue
    get_job_list

    # enable printer now
    if $PRINTER_PAUSED; then
        cupsenable "$PRINTER"
        PRINTER_PAUSED=false
    fi
done

# queue is now empty disable printer
if $PRINTER_PAUSED; then
    $DEBUG && echo "Queue is empty." >&2
else
    cupsdisable "$PRINTER"
    echo "[INFO] Queue is empty now, pausing printer $PRINTER." >&2
fi

# unlock
if $LOCKED; then rmdir "$LOCK"; fi

exit 0

スクリプトは、起動時にプリンタを一時停止し、既存のすべてのジョブを一時停止するように設定し、新しく着信ジョブに対して同じタスクを実行し、プリンタの一時停止を解除してキューが空になるのを待ちます。終了後、プリンタは再び一時停止します。

アイデアは、印刷ジョブが所有者によって手動で解放またはキャンセルできることです(または、マグにMaxHoldTimeを設定して自動的にキャンセルされます)。これはシンプルなフルプリントシステムの一部です。

これはスクリプトの最初のバージョンで、競合状態があり、cronで呼び出す必要があり、ヘルプテキストが欠落しており、asfクラスに対してテストされていません。機能を追加または変更したら公開します。ダウンロードリンクこの答えから。それを使用することはあなた自身の責任です。本番で使用するのではなく、どのように実行できるかについてのアイデアを提供するためにここにあります。

Cupに入ってくるすべてのタスクを一時停止するように指示するより簡単な方法があるというニュースを聞くことができます。多くの追加ソフトウェアがなくても、Follow me 印刷システムを構築できます。


ダウンロード:タブが欠落している可能性があるため、上記の項目をコピーできませんでした。ダウンロードリンクを使用してください。https://ente.limmat.ch/ftp/pub/software/bash/cups/

関連情報