🖨️

DockerコンテナからRICOHの複合機に印刷物を飛ばしてみる

2023/06/14に公開

電子化(DX?)を進めていても, どうしてもまだ紙で処理しなければいけないものってありますよね.
せめて印刷作業だけでも自動化して可能な限り省力化したいなー, という思いで複合機へのプリントを自動化 & Dockerコンテナ化してみたので共有します.

オフィスに RICOH の複合機(プリンター)があって同じような境遇の方(ニッチすぎる😂)は是非参考にどうぞ.
RICOH に限らず Linux 用の PPD のドライバが配布されているプリンタであれば真似(流用)できると思いますので, 自動印刷に興味が有る方は挑戦してみてください.
今回は今私の手元にある RICOH IM C300 を例に記しますが, RICOH MP C3004 RICOH IM C5510 等でも本手順で動作確認できています.

なお今回使用しているドライバはこちらです.
対応機種に含まれていれば機種を問わず流用できるはずです.
http://support.ricoh.com/bbv2/html/dr_ut_d/mfp/history/w/bb/pub_j/dr_ut_d/4101013/4101013911/V1122/5244035/Ricoh-Basic-PS-PPDv1.12.2.tar/history.htm

Docker を使用せずにシンプルに Linux から複合機を使用する際の参考としても, どうぞご活用ください(主に Dockerfile cmd.sh run.sh 辺り).

また, 以前書いた LaTeX による文書ジェネレータと組み合わせるとより統括的(?)なシステムが作れそうな気がしますね.
https://zenn.dev/sashimi/articles/acf7189e3b4468

前提

  • Docker環境が構築されている
    • シェル環境がある
      • MacOS または Linux 環境であるか, Windows であれば WSL 環境であること
        • ただし Apple silicon 搭載 Mac の場合は一部スクリプトが動作せず(印刷自体には支障なし. 後述.)

やり方

Dockerfile を書く

まずは Dockerfile を書きます.

./Dockerfile
FROM ubuntu:latest

LABEL maintainer="example@exmaple.com"

# COPY . /opt
WORKDIR /opt

ADD ./docker/run.sh /run.sh
ADD ./docker/cmd.sh /cmd.sh

RUN /run.sh
CMD ["/cmd.sh"]

この Dockerfile では大したことはしてなくて, このあと書くファイルをコピーしたり叩いたりしているだけです.

真似して使う場合は maintainer に自分のメールアドレスを設定してビルドしてください.

ちなみに, タグが latest なのでいつか動かなくなるかもしれません.
気になる方はタグを固定するのがよいと思います.
欲を言うと alpine のようなもっと軽量なイメージを使いたいですね(弄る余裕がなくて...).


次にDockerコンテナ用のファイルを置くディレクトリを掘ります.
好みの問題なので別に掘らなくてもいいですが, その場合は適宜パスを直してください.

mkdir docker

ついでに印刷物を置くディレクトリも作成します.

mkdir docs_to_print
touch ./docs_to_print/.gitkeep  # git にコミットする場合はディレクトリが消えないようにしておきます

次にDockerコンテナ用のスクリプトを書きます.

./docker/run.sh
#!/bin/bash
set -exuo pipefail

apt -y update
apt -y install lpr cups cups-client cups-pdf
apt -y install xfonts-base xfonts-75dpi 'fonts-takao-*'
apt -y install curl inotify-tools

## 予めdockerディレクトリにダウンロードしておく場合
# tar -zxvf ./docker/Ricoh-Basic-PS-PPDv1.12.2.tar.gz
## 都度ダウンロードする場合
curl -LOJ 'https://op-drv-ds1.support.ricoh.com/seresBB/servlet/VSORPageDownloadServlet' \
  --data-raw 'PATH=w%2Fbb%2Fpub_j%2Fdr_ut_d%2F4101013%2F4101013911%2FV1122%2F5244035%2FRicoh-Basic-PS-PPDv1.12.2.tar.gz&FWID_U001=WRU001&NWID_U001=&TEST_001=&buttonName=Accept'
tar -zxvf ./Ricoh-Basic-PS-PPDv1.12.2.tar.gz

useradd -r -G lpadmin -M print
echo print:print | chpasswd

mkdir -p /opt/docs_to_print

このスクリプトは DockerfileRUN , つまり docker build フェーズで実行されるものです.

  • lpr/cups などプリンタとの通信をするためのパッケージを入れています
  • xfonts-base xfonts-75dpi 'fonts-takao-*' などは日本語が最低限きれいに印刷されるようにフォントを入れています. 好みに応じて変更してください.
./docker/cmd.sh
#!/bin/bash
set -exuo pipefail

mkdir -p /etc/cups
echo "${PRINTER_NAME} ${PRINTER_IP}" > /etc/cups/client.conf

service lpd start
service cups start

DRIVER_DIR=Ricoh-Basic_PSv1.12.2
# カラー用
# DRIVER_PPD=Ricoh-Basic_PS_Color.ppd
# モノクロ用
DRIVER_PPD=Ricoh-Basic_PS_B_W.ppd
DRIVER_PPD_PATH=/opt/${DRIVER_DIR}/${DRIVER_PPD}
# NOTE: Windows PC とかでは使ってない項目だけどここ以外に任意文字列を入れられる場所が見つからない
sed -i "s|^[\*]*DefaultUserID.*$|*DefaultUserID: Custom.${PRINTER_USER}|" $DRIVER_PPD_PATH
# NOTE: これは効いてなさそう
# sed -i "s|^[\*]*DefaultLoginID.*$|*DefaultLoginID: Custom.${PRINTER_USER}|" $DRIVER_PPD_PATH
sed -i "s|^[\*]*DefaultJobPassword.*$|*DefaultJobPassword: Custom.${PRINTER_PW}|" $DRIVER_PPD_PATH
sed -i "s|^[\*]*DefaultJobType.*$|*DefaultJobType: LockedPrint|" $DRIVER_PPD_PATH
lpadmin -p $PRINTER_NAME -E -v "ipp://${PRINTER_IP}/ipp/print" -P $DRIVER_PPD_PATH$DRIVER_PPD_PATH

export TERM=xterm

rm ./docs_to_print/.gitkeep

# 以下, docs_to_print ディレクトリへのファイル追加を検知して自動で印刷を行うデモです
# NOTE: Apple silicon の qemu 仮想下では inotify 系の API は動作しない
#       同じようなことがしたければ Python とかで書けば良いと思う
inotifywait -m -e create --format '%w%f' -r ./docs_to_print | \
while read file_path; do
    echo "Printing ${file_path}"
    lp -d $PRINTER_NAME -oColorModel=Gray $file_path
    echo 'Removing...'
    rm $file_path
    echo 'Done.'
    # TODO: WEBHOOK通知したい.
    # sleep 60
done

このスクリプトは DockerfileCMD なので, docker run 時に実行されるものです.
lpdcupsstartRUN ではなく CMD である必要があります.

  • 印刷関係のサービスを起動し, ドライバの設定をして複合機を登録しています
  • 各環境変数(${VALUE} / $VALUE)は docker run 時に流し込みます
  • 最後に, inotifywait でディレクトリを監視し, ファイルが追加されたら自動で複合機に送信する処理をしています
    • ただし, Apple silicon 搭載 Mac の Docker 環境では inotifywait が動作しません.
      • シェルで頑張らずとも, Python などで印刷コマンドを発行するなどワークアラウンド手段はいくらでもあります
        Pythonからの印刷コマンド発行例
        import subprocess
        
        # ...
        
        cmd = 'lp -d RICOH_IM_C300 -oColorModel=Gray sample.pdf'
        try:
            subprocess.check_call(cmd.split())
        except Exception as e:
            pass
        
        # ...
        

最後に環境変数のファイルを設置します.

./.env
PRINTER_NAME=RICOH_IM_C300
PRINTER_IP=192.0.2.1
# 半角8文字以内に収めること
PRINTER_USER=docker
# 4-8文字の数字であること
PRINTER_PW=1234

ファイル名に特に深い意味はないです.
docker run 時に --env-file で渡して使います.


ここまでを通して, 下記のような構成になっていたら正解です.

% tree
.
├── .env
├── Dockerfile
├── docker
│   ├── cmd.sh
│   └── run.sh
└── docs_to_print

docker run してみる

(ちなみに最近は docker run よりも docker container run のほうが良いらしいですね)

docker build -t print-on-docker .

docker run -d -it --restart=always \
  --name print-on-docker \
  --env-file .env \
  -v $PWD/docs_to_print:/opt/docs_to_print \
  print-on-docker

起動できたら適宜ログを確認してみてください.

docker logs -f print-on-docker

下記のようにサンプルファイルをディレクトリに置いてあげると実際に複合機に飛ばされます
(ログを見ているならターミナルの別窓から叩いてください)

cp ./sample.pdf ./docs_to_print/

複合機を見に行くと docker さんから印刷物が届いています!

複合機の操作パネルに届いている

LockedPrint にしたので暗証番号が求められますね! (๑•̀ㅂ•́)و✧ヨシッ!

暗証番号もしっかりかかっている

当たり前ですが崩れもなくしっかり印刷できました!

印刷も問題なし

以上です. 「いかがだったでしょうか?」とか言わないんで, 誰かの何かの役に立てば嬉しいです. 👋🏻

Discussion