引子

HP的老旧激光打印机用来在家里给孩子打打作业什么的而是一个不错的选择。然而老旧有老旧的问题:如我的P1108只有USB口,默认情况下只能开PC打印,实在是麻烦。家里正好有常年工作的DS920+,而群晖内置的cups又基本是个废的,只好折腾一下来实现网络共享和无线打印。注意本文基本都是ssh下的终端操作。

  • Openwrt, 由于路由器的 RAM 一般都比较小,但是直接使用 cups 做打印服务器需要使用较大的资源,因此 Openwrt 系统源里面 现在已经不包含 cups 组件了。因为家里有个wdr3800老路由,安装cups带不动,所以才有了下面的折腾。

  • 任意一台 24 小时开机的 Linux 设备一台, 用于安装 CUPS 搭建 Airprint Server 使用, 如果不使用 IOS 设备,就不需要 CUPS

  • 如果家中只有 windows 和安卓设备,只需要配置 p910nd

  • 如果家中有可以 24 小时开机并且 ram 大于 1G 并且带有 USB 口的设备,只需要配置 cups

提前说结果:最后经过实践

ubuntu22.04 默认安装的cups 2.41 自带的 惠普老款驱动 3.21.12 就能驱动我的P1108打印机了,简直是折腾了个腾:)

不过还是建议你参考本文

准备工作

设备:1台P1108,一台DS920+(DSM7.1),一台工作笔记本

软件:工作笔记本上备好putty、winscp等工具,DS920+开启SSH,下载好最新的hplip和hplip-plugin。

驱动地址:HP Developers Portal | Version: 3.22.10

插件地址:HP Developers Portal | Plugins

步骤

因为相关类似的文章挺多的,我这里不全面展开了,很多内容都有成熟的文章可以参考。主要按照操作步骤梳理下, 帮助大家避坑。

**1、为什么用虚拟机不用docker。**现存的文章用docker的很多,但是我实际操作后暂时没有成功过,常见的几个docker镜像中预置的hplip都不完整或者版本陈旧,总之没有一个能正常把我的P1108驱动起来,而且因为镜像内linux用了小众发行版或者魔改严重、发行版陈旧的问题,无法正常完成hplip的自行编译安装。这条路走不通,于是干脆转向虚拟机了,920+支持VMM,实际上是基于qemu的虚拟机,可以用它跑一个最小化安装的ubuntu server。况且一个完整的linux虚拟机其实能做不少事情,多功能和一也不算浪费。

2、宿主机(群晖)准备。为了防止群晖自带cups的不可知冲突,建议干掉它,这部分因为DSM7以后的变化,实际上网上能查到的相关命令并不完整,只有一条关闭服务,并且还要在计划任务里增加杀服务的任务。实际上我们需要执行3条指令,执行完后不需要再添加计划任务了。

连接宿主机(群晖)的ssh,分别执行以下几条命令。首先停下cups:

sudo synosystemctl stop cupsd

然后禁用自启:

sudo synosystemctl disable cupsd

最后禁用服务

sudo synosystemctl mask cupsd

操作完以后群晖自带的cups就先让它byebye了。

centos

yum -y install cups-pdf #安装

systemctl start cups   #开始

systemctl enable cups  #开启

systemctl status cups   #查看

systemctl restart cups  #重启

**3、Ubuntu虚拟机安装。**这里不详细展开了,可以参考以下几篇文章,为了节省资源我是装的server版,没有安装图形界面,这个可以丰简由人。我给虚拟机分配了20G虚拟磁盘空间,主要考虑给后续其他折腾的东西做点预留。注意下可以直接在安装时候就指定好虚拟机的固定ip,并且22.04 server安装的时候可以选择最小化安装,另外记得替换国内源并开启ssh。

我没装qemu-guest-agent,可以sudo apt-get install qemu-guest-agent安装一下 我没装qemu-guest-agent,可以sudo apt-get install qemu-guest-agent安装一下

这里可以选择最小化安装,对于本项任务是足够了 这里可以选择最小化安装,对于本项任务是足够了

建议换成国内源,不然后面安装依赖的时候很杀时间 建议换成国内源,不然后面安装依赖的时候很杀时间

记得开启ssh 记得开启ssh

参考1:群晖+vmm虚拟机套件安装Ubuntu详细教程(一) - 知乎 (zhihu.com)

参考2:Ubuntu 20.04 live server版安装(详细版) - 运维密码 - 博客园 (cnblogs.com)

4、打印机驱动安装前的一些小准备。这里主要是对环境进行进一步配置,比如重要的cups安装。首先使用putty开启ssh连接至虚拟机(前面安装虚拟机时候可以手动设置地址或者自动获取,记住那个ip)

sudo apt-get update

sudo apt-get upgrade

sudo apt-get install cups

安装完成后需要配置下

sudo vi /etc/cups/cupsd.conf

注意vi下面按下insert键后进去插入模式可以编辑文本,编辑完成后按esc退出编辑,再键入:wq并回车保存退出。主要是访问权限的设置,不然后续会打不开设置页面。如果只工作在自家局域网,可以把所有的验证改成none,并且删除要求系统管理员的条目,并允许所有访客,各个区段里的样子类似这样。这里我也不熟悉,不多说了,可以找点专业的文章看看。

修改配置文件为

`修改为AuthType None`

Order Allow,Deny下面增加 Allow from All

Browsing Off 修改为 Browsing On

`Listen localhost:631 修改为 Listen 631`

需要外网访问的在

WebInterface Yes

ServerAlias
*

另外监听的网络地址也要从localhost改为0.0.0.0。或是 `Listen localhost:631 修改为 Listen 631`全部完成后重启cups。

sudo /etc/init.d/cups restart

下面是我的ubuntu 22.04 197 cups完整配置文件,以供参考

#
# Configuration file for the CUPS scheduler.  See "man cupsd.conf" for a
# complete description of this file.
#

# Log general information in error_log - change "warn" to "debug"
# for troubleshooting...
LogLevel warn
PageLogFormat

# Specifies the maximum size of the log files before they are rotated.  The value "0" disables log rotation.
MaxLogSize 0

# Default error policy for printers
ErrorPolicy retry-job

# Only listen for connections from the local machine.
Listen 0.0.0.0:631
Listen /run/cups/cups.sock

# Show shared printers on the local network.
Browsing No
BrowseLocalProtocols dnssd

# Default authentication type, when authentication is required...
DefaultAuthType Basic

# Web interface setting...
WebInterface Yes

ServerAlias *

# Timeout after cupsd exits if idle (applied only if cupsd runs on-demand - with -l)
IdleExitTimeout 60

# Restrict access to the server...
<Location />
  Order allow,deny
  Allow all
</Location>

# Restrict access to the admin pages...
<Location /admin>
  Order allow,deny
  Allow all
</Location>

# Restrict access to configuration files...
<Location /admin/conf>
  AuthType None
  Require user @SYSTEM
  Order allow,deny
  Allow all
</Location>

# Restrict access to log files...
<Location /admin/log>
  AuthType None
  Require user @SYSTEM
  Order allow,deny
</Location>

# Set the default printer/job policies...
<Policy default>
  # Job/subscription privacy...
  JobPrivateAccess default
  JobPrivateValues default
  SubscriptionPrivateAccess default
  SubscriptionPrivateValues default

  # Job-related operations must be done by the owner or an administrator...
  <Limit Create-Job Print-Job Print-URI Validate-Job>
    Order deny,allow
  </Limit>

  <Limit Send-Document Send-URI Hold-Job Release-Job Restart-Job Purge-Jobs Set-Job-Attributes Create-Job-Subscription Renew-Subscription Cancel-Subscription Get-Notifications Reprocess-Job Cancel-Current-Job Suspend-Current-Job Resume-Job Cancel-My-Jobs Close-Job CUPS-Move-Job CUPS-Get-Document>
    Require user @OWNER @SYSTEM
    Order deny,allow
  </Limit>

  # All administration operations require an administrator to authenticate...
  <Limit CUPS-Add-Modify-Printer CUPS-Delete-Printer CUPS-Add-Modify-Class CUPS-Delete-Class CUPS-Set-Default CUPS-Get-Devices>
    AuthType None
    Require user @SYSTEM
    Order deny,allow
  </Limit>

  # All printer operations require a printer operator to authenticate...
  <Limit Pause-Printer Resume-Printer Enable-Printer Disable-Printer Pause-Printer-After-Current-Job Hold-New-Jobs Release-Held-New-Jobs Deactivate-Printer Activate-Printer Restart-Printer Shutdown-Printer Startup-Printer Promote-Job Schedule-Job-After Cancel-Jobs CUPS-Accept-Jobs CUPS-Reject-Jobs>
    AuthType None
    Require user @SYSTEM
    Order deny,allow
  </Limit>

  # Only the owner or an administrator can cancel or authenticate a job...
  <Limit Cancel-Job CUPS-Authenticate-Job>
    Require user @OWNER @SYSTEM
    Order deny,allow
  </Limit>

  <Limit All>
    Order deny,allow
  </Limit>
</Policy>

# Set the authenticated printer/job policies...
<Policy authenticated>
  # Job/subscription privacy...
  JobPrivateAccess default
  JobPrivateValues default
  SubscriptionPrivateAccess default
  SubscriptionPrivateValues default

  # Job-related operations must be done by the owner or an administrator...
  <Limit Create-Job Print-Job Print-URI Validate-Job>
    AuthType None
    Order deny,allow
  </Limit>

  <Limit Send-Document Send-URI Hold-Job Release-Job Restart-Job Purge-Jobs Set-Job-Attributes Create-Job-Subscription Renew-Subscription Cancel-Subscription Get-Notifications Reprocess-Job Cancel-Current-Job Suspend-Current-Job Resume-Job Cancel-My-Jobs Close-Job CUPS-Move-Job CUPS-Get-Document>
    AuthType None
    Require user @OWNER @SYSTEM
    Order deny,allow
  </Limit>

  # All administration operations require an administrator to authenticate...
  <Limit CUPS-Add-Modify-Printer CUPS-Delete-Printer CUPS-Add-Modify-Class CUPS-Delete-Class CUPS-Set-Default>
    AuthType None
    Require user @SYSTEM
    Order deny,allow
  </Limit>

  # All printer operations require a printer operator to authenticate...
  <Limit Pause-Printer Resume-Printer Enable-Printer Disable-Printer Pause-Printer-After-Current-Job Hold-New-Jobs Release-Held-New-Jobs Deactivate-Printer Activate-Printer Restart-Printer Shutdown-Printer Startup-Printer Promote-Job Schedule-Job-After Cancel-Jobs CUPS-Accept-Jobs CUPS-Reject-Jobs>
    AuthType None
    Require user @SYSTEM
    Order deny,allow
  </Limit>

  # Only the owner or an administrator can cancel or authenticate a job...
  <Limit Cancel-Job CUPS-Authenticate-Job>
    AuthType None
    Require user @OWNER @SYSTEM
    Order deny,allow
  </Limit>

  <Limit All>
    Order deny,allow
  </Limit>
</Policy>

# Set the kerberized printer/job policies...
<Policy kerberos>
  # Job/subscription privacy...
  JobPrivateAccess default
  JobPrivateValues default
  SubscriptionPrivateAccess default
  SubscriptionPrivateValues default

  # Job-related operations must be done by the owner or an administrator...
  <Limit Create-Job Print-Job Print-URI Validate-Job>
    AuthType Negotiate
    Order deny,allow
  </Limit>

  <Limit Send-Document Send-URI Hold-Job Release-Job Restart-Job Purge-Jobs Set-Job-Attributes Create-Job-Subscription Renew-Subscription Cancel-Subscription Get-Notifications Reprocess-Job Cancel-Current-Job Suspend-Current-Job Resume-Job Cancel-My-Jobs Close-Job CUPS-Move-Job CUPS-Get-Document>
    AuthType Negotiate
    Require user @OWNER @SYSTEM
    Order deny,allow
  </Limit>

  # All administration operations require an administrator to authenticate...
  <Limit CUPS-Add-Modify-Printer CUPS-Delete-Printer CUPS-Add-Modify-Class CUPS-Delete-Class CUPS-Set-Default>
    AuthType None
    Require user @SYSTEM
    Order deny,allow
  </Limit>

  # All printer operations require a printer operator to authenticate...
  <Limit Pause-Printer Resume-Printer Enable-Printer Disable-Printer Pause-Printer-After-Current-Job Hold-New-Jobs Release-Held-New-Jobs Deactivate-Printer Activate-Printer Restart-Printer Shutdown-Printer Startup-Printer Promote-Job Schedule-Job-After Cancel-Jobs CUPS-Accept-Jobs CUPS-Reject-Jobs>
    AuthType None
    Require user @SYSTEM
    Order deny,allow
  </Limit>

  # Only the owner or an administrator can cancel or authenticate a job...
  <Limit Cancel-Job CUPS-Authenticate-Job>
    AuthType Negotiate
    Require user @OWNER @SYSTEM
    Order deny,allow
  </Limit>

  <Limit All>
    Order deny,allow
  </Limit>
</Policy>

这时候可以开浏览器看看有没有跑起来,访问[虚拟机ip]:631,如192.168.1.197:631,出现以下页面即可。

image-20230802082424162 看到这个cups安装基本问题不大

下面准备hplip的编译安装环境,主要有几个坑,ubuntu上同时有python2.X和3.X。hplip会默认识别到2.X并导致一系列问题,为避免问题,安装一个小插件即可:

sudo apt install python-is-python3

另外如果缺失libavahi-core也会编译出错,这里预先安装上:

sudo apt install libavahi-core-dev

另外因为国内访问python的官方源非常慢,建议预先将源改至国内镜像。

相关内容可参考:[How to Install the Latest HPLIP Driver in Ubuntu 20.04 [Fix Dependency Issue] | UbuntuHandbook](https://ubuntuhandbook.org/index.php/2021/07/install-latest-hplip-ubuntu-20-04-fix/#:~:text=HPLIP is an open-source Linux drivers for HP’s,the official binary to get new devices support.)

5、编译安装hplip驱动。这里仍旧是在虚拟机的ssh操作,将前面下载好的3个hplip和hplip-plugin及校验包推至虚拟机,可以用winscp推上去,这里假设放在/tmp/,即文件的路径分别为/tmp/hplip-3.22.10.run 、/tmp/hplip-3.22.10-plugin.run和/tmp/hplip-3.22.10-plugin.run.asc。

首先赋予执行权限:

chmod +x /tmp/hplip*.run

然后运行安装

sh /tmp/hplip-3.22.10.run

安装模式可以选自动或手动,如果是单一打印的老式单usb机器,可以在手动模式下把所有模块都关掉,可以减少依赖要求,安装出错可能性减少。

一些安装选项 一些安装选项

选择后需要验证下登录用户密码。

继续一些配置 继续一些配置

后面基本就都是yes和enter,如果预先配置好python和ubuntu的国内镜像源,应该不会有什么问题,直至完成安装即可。

6、安装hp-plugin。很多docker镜像里就缺这东西。在虚拟机ssh执行:

hp-plugin -i

三个选项建议选p并指定至/tmp/hplip-3.22.10-plugin.run,从官方下载会非常慢,后面如果提示文件校验不了选择忽略就行。我已经安好了,就不继续下一步截图了。

安装hplip-plugin 安装hplip-plugin

**7、安装并驱动打印机。**这里需要开启打印机电源、usb口插在群晖上,然后在群晖的VMM里进行如下设置。(这个动作后续会用脚本自动化)

这里选中打印机,然后点确定 这里选中打印机,然后点确定

然后继续在虚拟机ssh中执行:

lsusb

可以看到打印机已经被系统识别,记住这个id,后面用的到:

Bus 001 Device 003: ID 03f0:002a HP, Inc LaserJet P1102

执行打印机安装,这里需要sudo,不然识别不到

sudo hp-setup -i

应该就能识别到usb打印机,基本一路y就行,最后可以打印测试页,能打印就说明驱动完成。记得开启共享。回到cups页面也能看到打印机了。

image-20230802082852660

cups里可以看到完成安装的打印机

**8、应对打印机自动关机引发的问题。**P1108会自动关机,关机后再开机,宿主机(群晖)并不会自动把这个usb设备附加到虚拟机中,那不就完蛋了么,为应对这个问题继续操作(话说这机器在PC上是可以设置不自动关机的,不过我设置不成功,可能需要USB直连时候才能正常设置,回头再试,先解决重新开机后自动附加到虚拟机上的问题)。

这里我们用到udev匹配设备插入动作,并使用virsh自动向虚拟机附加usb设备。以下在**宿主机(群晖)**的ssh运行,首先查看虚拟机的name:

sudo virsh list –all

可以看到所有现存的虚拟机,记下配置了打印机的这个虚拟机的name,就是中间那一串hex数字加连字符:

Id Name State

-—————————————————–

1 864bf6fa-628e-46f0-a1f1-e8274axxxxxx running

下面写一个udev的触发规则,为了不和系统自带规则搞混,把规则放在/etc/udev/rules.d/下,由于群晖没有自带这个规则,可能需要mkdir创建两级目录,并给与755权限。

sudo mkdir /etc/udev

sudo chmod 755 /etc/udev

sudo mkdir /etc/udev/rules.d

sudo chmod 755 /etc/udev/rules.d

新建一条规则,注意优先级给高一点,比如99,文件名规则就是:数字-文件名.rules。我这里如下创建:

sudo vi /etc/udev/rules.d/99-usb-hp.rules

进入vi后按insert开始编辑,输入以下两条规则

ACTION==“add”, SUBSYSTEM==“usb”, DRIVER==“usb”, ATTRS{idVendor}==“03f0”, ATTRS{idProduct}==“002a”, RUN+="/usr/bin/sh /etc/udev/rules.d/usb_udev.sh"

ACTION==“remove”, SUBSYSTEM==“usb”, DRIVER==“usb”, ATTRS{idVendor}==“03f0”, ATTRS{idProduct}==“002a”, RUN+="/usr/bin/sh /etc/udev/rules.d/usb_udev_rm.sh"

这里的ATTRS{idVendor}和ATTRS{idProduct}分别是前面lsusb时候记下的id里冒号前后的数字。RUN+=后是需要执行的命令,这里执行的命令需要指定到命令的二进制文件地址,我才疏学浅没找到virsh在群晖里的二进制位置,只能退而求其次写两个脚本实现功能。完成编辑后先esc然后:wq回车保存退出。

继续写两个脚本,分别是插入usb设备和取下时候的动作,其实可以合并一个脚本加个action判断,不过我懒。

sudo vi /etc/udev/rules.d/usb_udev.sh

里面内容是

#!/bin/bash

virsh attach-device 864bf6fa-628e-46f0-a1f1-e8274axxxxxx /etc/udev/rules.d/hpusb.xml

中间那一串是刚记下的虚拟机name,后面那个是usb设备的描述,等会写它。

vi保存退出,给脚本赋权:

sudo chmod +x /etc/udev/rules.d/usb_udev.sh

再写拔下设备的脚本

sudo vi /etc/udev/rules.d/usb_udev_rm.sh

里面内容如下,注意attach变成detach

#!/bin/bash

virsh detach-device 864bf6fa-628e-46f0-a1f1-e8274axxxxxx /etc/udev/rules.d/hpusb.xml

vi保存退出,给脚本赋权:

sudo chmod +x /etc/udev/rules.d/usb_udev_rm.sh

继续写hpusb.xml:

sudo vi /etc/udev/rules.d/hpusb.xml

里面内容:

注意vendorid和productid和前面的规则里保持一致。保存退出。

至此规则写完,让udev重新加载规则:

sudo udevadm control –reload

sudo synosystemctl daemon-reload

这样就OK了。打印机重启或者usb拔下重插后会自动附加到虚拟机里。不需要人工去VMM挂上。

**9、打印机共享。**这里没什么需要设置的,局域网里的PC能直接识别到。如果是安卓设备可以装个Mopria Print,连上局域网同网段WIFI也可以自动识别到打印机。

这里设置的关闭自动关机不成功,回头usb直连试试。

安卓手机识别到的打印机 安卓手机识别到的打印机

到这里基本就折腾完了,P1108本身没有内置的纸槽,所以我没有完全无人值守的需求,那个不自动关机的设置对我来说没有非常大的必要所以一直没有直连测试。孩子打作业就自己开打印机放上纸,然后平板上操作打印完事。

安装与配置p910nd

安装cups,p910nd

$ sudo apt update
$ sudo apt upgrade
$ sduo apt install -y cups printer-driver-foo2zjs p910nd

配置文件

$ sudo nano /etc/default/p910nd
内容
P910ND_NUM=0
P910ND_OPTS="-f /dev/usb/lp0"
P910ND_START=1
$ sudo systemctl restart p910nd

我自己的玩客云p910nd配置文件 sudo nano /etc/default/p910nd

# Printer number, if not 0
P910ND_NUM="0"
# Additional daemon arguments, see man 8 p910nd
P910ND_OPTS="-f /dev/usb/lp0"

# Debian specific (set to 1 to enable start by default)
P910ND_START=1

#禁用双向模式
P910ND_bidirectional=1

多个USB打印机设置

$ sudo nano /etc/init.d/p910nd

内容如下

#! /bin/sh
### BEGIN INIT INFO
# Provides:          p910nd
# Required-Start:    $remote_fs $syslog $network
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: p910nd daemon providing network printer access
# Description:       Start p910nd to provide port 9100+n printer service
### END INIT INFO

# Author: Mario Izquierdo (mariodebian) <[email protected]>
#

# Do NOT "set -e"

# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="network print daemon"
NAME=p910nd
DAEMON=/usr/sbin/$NAME
PIDFILE=/var/run/p9100d.pid
PIDFILE1=/var/run/p9101d.pid
SCRIPTNAME=/etc/init.d/$NAME

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

# create /var/run and /var/lock/p910nd (Debian policy 3.8.1)
[ ! -d /var/run ] && mkdir -p /var/run
[ ! -d /var/lock/p910nd ] && mkdir -p /var/lock/p910nd

P910ND_OPTS=""
P910ND_NUM=""
P910ND_OPTS1=""
P910ND_NUM1=""

# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME

DAEMON_ARGS=" $P910ND_OPTS $P910ND_NUM"
DAEMON_ARGS1=" $P910ND_OPTS1 $P910ND_NUM1"

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions

#
# Function that starts the daemon/service
#
do_start()
{
    # Return
    #   0 if daemon has been started
    #   1 if daemon was already running
    #   2 if daemon could not be started
    start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
        || return 1
    start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
        $DAEMON_ARGS \
        || return 2
    start-stop-daemon --start --quiet --pidfile $PIDFILE1 --exec $DAEMON -- \
        $DAEMON_ARGS1 \
        || return 2
}

#
# Function that stops the daemon/service
#
do_stop()
{
    # Return
    #   0 if daemon has been stopped
    #   1 if daemon was already stopped
    #   2 if daemon could not be stopped
    #   other if a failure occurred
    start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
    RETVAL="$?"
    [ "$RETVAL" = 2 ] && return 2
    start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE1 --name $NAME
    RETVAL="$?"
    [ "$RETVAL" = 2 ] && return 2

    # Wait for children to finish too if this is a daemon that forks
    # and if the daemon is only ever run from this initscript.
    # If the above conditions are not satisfied then add some other code
    # that waits for the process to drop all resources that could be
    # needed by services started subsequently.  A last resort is to
    # sleep for some time.
    start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
    [ "$?" = 2 ] && return 2
    # Added for second daemon but may not be necessary
    start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
    [ "$?" = 2 ] && return 2

    # Many daemons don't delete their pidfiles when they exit.
    rm -f $PIDFILE
    # return "$RETVAL"
    rm -f $PIDFILE1
    return "$RETVAL"

}

case "$1" in
  start)
    # disable start
    if [ "$P910ND_START" != "1" ]; then
            log_warning_msg "Not starting p910nd daemon. Please edit /etc/default/p910nd first."
            exit 0
        fi

    log_daemon_msg "Starting $DESC" "$NAME"
    do_start
    case "$?" in
        0|1) log_end_msg 0 ;;
        2)   log_end_msg 1 ;;
    esac
    ;;
  stop)
    log_daemon_msg "Stopping $DESC" "$NAME"
    do_stop
    case "$?" in
        0|1) log_end_msg 0 ;;
        2)   log_end_msg 1 ;;
    esac
    ;;
  restart|force-reload)
    #
    # If the "reload" option is implemented then remove the
    # 'force-reload' alias
    #
    log_daemon_msg "Restarting $DESC" "$NAME"
    do_stop
    case "$?" in
      0|1)
        do_start
        case "$?" in
            0) log_end_msg 0 ;;
            1) log_end_msg 1 ;; # Old process is still running
            *) log_end_msg 1 ;; # Failed to start
        esac
        ;;
      *)
        # Failed to stop
        log_end_msg 1
        ;;
    esac
    ;;
  *)
    echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
    exit 3
    ;;
esac

:

重新启动服务

$ sudo systemctl daemon-reload
$ sudo systemctl restart p910nd

cups添加p910nd网络打印机步骤

然后执行以下步骤:

  1. 在浏览器中打开 https://ipadder:631

  2. 点击 Administration - Add Printer, 输入登录系统并且已经加到 lpadmin 组的账户的用户名密码

  3. 选择 AppSocket/HP JetDirect - Continue

  4. Connection 中输入 socket://openwrtip:9100 - Continue

  5. 给最终 share 的打印机取名,必须勾选 Share This Printer - Continue, 这一步 非常重要 , 这里填写的名字,是 以后在 windows 中添加打印机的 uri, 必须勾选共享选项局域网中别的设备才可以发现这台打印机。

  6. 打印机品牌选择 hp - continue

  7. 打印机型号选择 HP LaserJet 1020 Foomatic/foo2zjs-z1 (recommended) - Add Printer

  8. image-20230802083958991

    如图,cups 的配置就已经完成了。

实现热插拨

vi /etc/udev/rules.d/99-usb-p910nd.rules

SUBSYSTEM=="usb", ACTION=="add", RUN+="/root/p910nd.sh"

/root/p910nd.sh

#!/bin/sh
sudo systemctl restart p910nd

以上文章参考

https://post.smzdm.com/p/a905p290/

https://www.imtxc.com/home-printer-server-hp1020plus.html

https://v2rayssr.com/airprint.html