15AH, San Francisco

California, United States.

Send Your Mail At:

tianyingkejishe@sina.cn

Working Hours

Mon-Sat: 9.30am To 7.00pm

分类标题

Autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et dolore feugait.

分类归档 Linux

【Luckfox Pico Ultra BW】RV1106G3 解决录音问题

分析原理图,实际开发板C58那里焊接的是0R电阻,所以这里接的是单端输入信号,不是差分!

我们再来看看野火开发板(LubanCat_RV06) 的麦克风接法

野火开发板使用了左右两个声道,都是差分输入。

查看当前设置 amixer controls

# amixer controls
numid=4,iface=MIXER,name='ADC ALC Left Volume'
numid=5,iface=MIXER,name='ADC ALC Right Volume'
numid=6,iface=MIXER,name='ADC Digital Left Volume'
numid=7,iface=MIXER,name='ADC Digital Right Volume'
numid=8,iface=MIXER,name='ADC HPF Cut-off'
numid=2,iface=MIXER,name='ADC MIC Left Gain'
numid=22,iface=MIXER,name='ADC MIC Left Switch'
numid=3,iface=MIXER,name='ADC MIC Right Gain'
numid=23,iface=MIXER,name='ADC MIC Right Switch'
numid=20,iface=MIXER,name='ADC MICBIAS Voltage'
numid=21,iface=MIXER,name='ADC Main MICBIAS'
numid=19,iface=MIXER,name='ADC Mode'
numid=1,iface=MIXER,name='I2STDM Digital Loopback Mode'
numid=17,iface=MIXER,name='AGC Left Approximate Sample Rate'
numid=18,iface=MIXER,name='AGC Right Approximate Sample Rate'
numid=11,iface=MIXER,name='ALC AGC Left Max Volume'
numid=13,iface=MIXER,name='ALC AGC Left Min Volume'
numid=15,iface=MIXER,name='ALC AGC Left Switch'
numid=9,iface=MIXER,name='ALC AGC Left Volume'
numid=12,iface=MIXER,name='ALC AGC Right Max Volume'
numid=14,iface=MIXER,name='ALC AGC Right Min Volume'
numid=16,iface=MIXER,name='ALC AGC Right Switch'
numid=10,iface=MIXER,name='ALC AGC Right Volume'
numid=26,iface=MIXER,name='DAC Control Manually'
numid=25,iface=MIXER,name='DAC HPMIX Volume'
numid=24,iface=MIXER,name='DAC LINEOUT Volume'

注意ADC Mode:numid=19,iface=MIXER,name=’ADC Mode’,查看当前ADC Mode设置

# amixer cget numid=19
numid=19,iface=MIXER,name='ADC Mode'
  ; type=ENUMERATED,access=rw------,values=1,items=6
  ; Item #0 'DiffadcL'
  ; Item #1 'SingadcL'
  ; Item #2 'DiffadcR'
  ; Item #3 'SingadcR'
  ; Item #4 'SingadcLR'
  ; Item #5 'DiffadcLR'
  : values=0

values=0:设置的左声道差分输入!这个和我们的硬件不匹配,修改成SingadcL

amixer cset numid=19 1

numid=19,iface=MIXER,name=’ADC Mode’
; type=ENUMERATED,access=rw——,values=1,items=6
; Item #0 ‘DiffadcL’
; Item #1 ‘SingadcL’
; Item #2 ‘DiffadcR’
; Item #3 ‘SingadcR’
; Item #4 ‘SingadcLR’
; Item #5 ‘DiffadcLR’
: values=1

再次测试录音和播放

# arecord -D plughw:0,0 -f cd -t wav -d 10 test.wav
Recording WAVE 'test.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
# aplay test.wav 
Playing WAVE 'test.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo

终于正常了,拷贝到电脑上,只有左耳机有声音。声音清晰!纠结了几天的问题终于解决了。

最后非常感谢野火提供资料。看了这么多资料,感觉野火的资料最实在,干货最多。

【Linux】编译适用于NOR Flash的Linux文件系统

在嵌入式系统中,使用NOR Flash作为存储介质时,通常需要选择合适的文件系统并进行相关配置和编译。以下是实现这一目标的步骤。

1. 准备工作

  • 获取工具链:安装交叉编译工具,如 gcc-linaro 和设备树编译器 dtc
  • 下载源码: U-Boot 源码:Lichee-Pi U-Boot。 Linux 内核源码:Lichee-Pi Linux。

2. 配置和编译U-Boot

  • 配置支持NOR Flash
make ARCH=arm menuconfig
  • 设置默认启动参数: 修改 include/configs/sun8i.h 文件,添加如下内容:
#define CONFIG_BOOTCOMMAND "sf probe 0; sf read 0x41800000 0x100000 0x10000; sf read 0x41000000 0x110000 0x400000; bootz 0x41000000 - 0x41800000"
#define CONFIG_BOOTARGS "console=ttyS0,115200 root=/dev/mtdblock3 rootfstype=jffs2 rw"
  • 编译U-Boot
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j4

3. 配置和编译Linux内核

  • 配置内核选项: make ARCH=arm menuconfig 启用 Device Drivers -> Memory Technology Device (MTD) support。 启用 File systems -> Miscellaneous filesystems -> JFFS2 support。
  • 修改设备树文件: 在设备树文件(如 sun8i-v3s-licheepi-zero.dts)中添加SPI Flash节点:
&spi0 {
   status = "okay";
   flash@0 {
       compatible = "jedec,spi-nor";
       reg = <0x0>;
       spi-max-frequency = <50000000>;
   };
};
  • 编译内核和设备树
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j4
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- dtbs

4. 制作JFFS2文件系统镜像

  • 安装工具:
sudo apt-get install mtd-utils
  • 制作镜像:
mkfs.jffs2 -s 0x100 -e 0x10000 -p 0xAF0000 -d rootfs/ -o jffs2.img

5. 打包镜像

  • 将U-Boot、内核、设备树和文件系统打包为一个镜像:

dd if=/dev/zero of=flashimg.bin bs=1M count=16
dd if=u-boot-sunxi-with-spl.bin of=flashimg.bin bs=1K conv=notrunc
dd if=sun8i-v3s-licheepi-zero.dtb of=flashimg.bin bs=1K seek=1024 conv=notrunc
dd if=zImage of=flashimg.bin bs=1K seek=1088 conv=notrunc
dd if=jffs2.img of=flashimg.bin bs=1K seek=5184 conv=notrunc

6. 烧录镜像到NOR Flash

  • 使用 sunxi-fel 工具烧录镜像:
sudo sunxi-fel -p spiflash-write 0 flashimg.bin

【BLUE】蓝牙模块连接蓝牙耳机

一、测试环境

硬件:A7核 平台:ubuntu22.04

1、安装相应的依赖库文件

ntpd -d #确保能访问外网后执行 同步时间
sudo apt update 
sudo apt install bluez
sudo apt install pulseaudio-module-bluetooth
sudo apt-get install bluez bluez-firmware

2、停止蓝牙服务:在终端输入以下命令停止蓝牙服务。

sudo systemctl stop bluetooth

启动蓝牙服务:在终端输入以下命令启动蓝牙服务。

sudo systemctl start bluetooth

3、启动 pulseaudio 服务,重启开发板后要重新启动服务

insmod /oem/usr/ko/aic8800_btlpm.ko

hciattach -s 1500000 /dev/ttyS1 any 1500000 flow nosleep& #最新SDK

# 先配置好 alsa 再启动

pulseaudio –start

二、连接蓝牙耳机设备

1、配对蓝牙声卡

发现蓝牙设备:在终端输入以下命令发现蓝牙设备。

sudo bluetoothctl

power on  # 使能控制器
pairable on # 设置控制器可配对

扫描设备:在蓝牙控制台中输入以下命令扫描设备。

scan on
scan off

选择设备:当蓝牙声卡出现在设备列表中时,输入以下命令选择设备。

pair [设备地址]

输入PIN码:当系统提示输入PIN码时,出现pin码时输入yes,输入默认的PIN码“0000”。

连接设备:在蓝牙控制台中输入以下命令连接设备。

connect [设备地址]

2、设置默认音频设备

查看当前音频设备:在终端输入以下命令查看当前音频设备。

pacmd list-sinks

设置默认音频设备:找到蓝牙声卡对应的设备索引,然后在终端输入以下命令设置默认音频设备。

pacmd set-default-sink [设备索引]

3、检查音量设置

查看音量设置:在终端输入以下命令查看音量设置。

amixer

调整音量:如果音量设置过低,请调整音量。

amixer set Master [音量值]

设置绝对音量,0%-100%,1表示声卡号或者名字。

pactl set-sink-volume 1 90%

设置相对音量,增大10%

pactl set-sink-volume 1 +10%

设置相对音量,减小10%

pactl set-sink-volume 1 -10%

【Linux】Ubuntu 拦截并监听 power button 的关机消息

一、解决方法

Instead, adding a single line to /etc/systemd/logind.conf was enough to do the trick:
#HandlePowerKey=poweroff
HandlePowerKey=suspend
Now, pressing the power button causes instant suspend.

修改/etc/systemd/logind.conf文件,找到HandlePowerKey,并且可以使用下面几个参数:

  • suspend 系统会被挂起,如果我的设备终端有屏幕,而且装了相应的桌面,还会进入锁屏界面;
  • ignore 电源按键的消息会被忽略,即我按下按键之后什么事情都没有发生;

监听按键:

cat /proc/bus/input/devices

得到如下结果:

I: Bus=0019 Vendor=0000 Product=0003 Version=0000
N: Name="Sleep Button"
P: Phys=PNP0C0E/button/input0
S: Sysfs=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0E:00/input/input0
U: Uniq=
H: Handlers=kbd event0 
B: PROP=0
B: EV=3
B: KEY=4000 0 0

I: Bus=0019 Vendor=0000 Product=0001 Version=0000
N: Name="Power Button"
P: Phys=PNP0C0C/button/input0
S: Sysfs=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0C:00/input/input1
U: Uniq=
H: Handlers=kbd event1 
B: PROP=0
B: EV=3
B: KEY=10000000000000 0

I: Bus=0019 Vendor=0000 Product=0001 Version=0000
N: Name="Power Button"
P: Phys=LNXPWRBN/button/input0
S: Sysfs=/devices/LNXSYSTM:00/LNXPWRBN:00/input/input2
U: Uniq=
H: Handlers=kbd event2 
B: PROP=0
B: EV=3
B: KEY=10000000000000 0

所以,可能需要监听event1或者event2,可以通过以下的代码直接监听事件的输入信息;

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <time.h>
#include <linux/input.h>
 
struct input_event event;
 
int main(int argc, char **argv)
{
    char          name[64];           /* RATS: Use ok, but could be better */
    char          buf[256] = { 0, };  /* RATS: Use ok */
    unsigned char mask[EV_MAX/8 + 1]; /* RATS: Use ok */
    int           version;
    int           fd = 0;
    int           rc;
    int           i, j;
    char          *tmp;
 
#define test_bit(bit) (mask[(bit)/8] & (1 << ((bit)%8)))
 
    for (i = 0; i < 32; i++) {
        sprintf(name, "/dev/input/event%d", i);
        if ((fd = open(name, O_RDONLY, 0)) >= 0) {
            ioctl(fd, EVIOCGVERSION, &version);
            ioctl(fd, EVIOCGNAME(sizeof(buf)), buf);
            ioctl(fd, EVIOCGBIT(0, sizeof(mask)), mask);
            printf("%s\n", name);
            printf("    evdev version: %d.%d.%d\n",
                   version >> 16, (version >> 8) & 0xff, version & 0xff);
            printf("    name: %s\n", buf);
            printf("    features:");
            for (j = 0; j < EV_MAX; j++) {
                if (test_bit(j)) {
                    const char *type = "unknown";
                    switch(j) {
                    case EV_KEY: type = "keys/buttons"; break;
                    case EV_REL: type = "relative";     break;
                    case EV_ABS: type = "absolute";     break;
                    case EV_MSC: type = "reserved";     break;
                    case EV_LED: type = "leds";         break;
                    case EV_SND: type = "sound";        break;
                    case EV_REP: type = "repeat";       break;
                    case EV_FF:  type = "feedback";     break;
                    }
                    printf(" %s", type);
                }
            }
            printf("\n");
            close(fd);
        }
    }
 
    if (argc > 1) {
        sprintf(name, "/dev/input/event%d", atoi(argv[1]));
        if ((fd = open(name, O_RDWR, 0)) >= 0) {
            printf("%s: open, fd = %d\n", name, fd);
            for (i = 0; i < LED_MAX; i++) {
                event.time.tv_sec  = time(0);
                event.time.tv_usec = 0;
                event.type         = EV_LED;
                event.code         = i;
                event.value        = 0;
                write(fd, &event, sizeof(event));
            }
            
            while ((rc = read(fd, &event, sizeof(event))) > 0) {
                printf("%-24.24s.%06lu type 0x%04x; code 0x%04x;"
                       " value 0x%08x; ",
                       ctime(&event.time.tv_sec),
                       event.time.tv_usec,
                       event.type, event.code, event.value);
                switch (event.type) {
                case EV_KEY:
                    if (event.code > BTN_MISC) {
                        printf("Button %d %s",
                               event.code & 0xff,
                               event.value ? "press" : "release");
                    } else {
                        printf("Key %d (0x%x) %s",
                               event.code & 0xff,
                               event.code & 0xff,
                               event.value ? "press" : "release");
                               
                    }
                    break;
                case EV_REL:
                    switch (event.code) {
                    case REL_X:      tmp = "X";       break;
                    case REL_Y:      tmp = "Y";       break;
                    case REL_HWHEEL: tmp = "HWHEEL";  break;
                    case REL_DIAL:   tmp = "DIAL";    break;
                    case REL_WHEEL:  tmp = "WHEEL";   break;
                    case REL_MISC:   tmp = "MISC";    break;
                    default:         tmp = "UNKNOWN"; break;
                    }
                    printf("Relative %s %d", tmp, event.value);
                    break;
                case EV_ABS:
                    switch (event.code) {
                    case ABS_X:        tmp = "X";        break;
                    case ABS_Y:        tmp = "Y";        break;
                    case ABS_Z:        tmp = "Z";        break;
                    case ABS_RX:       tmp = "RX";       break;
                    case ABS_RY:       tmp = "RY";       break;
                    case ABS_RZ:       tmp = "RZ";       break;
                    case ABS_THROTTLE: tmp = "THROTTLE"; break;
                    case ABS_RUDDER:   tmp = "RUDDER";   break;
                    case ABS_WHEEL:    tmp = "WHEEL";    break;
                    case ABS_GAS:      tmp = "GAS";      break;
                    case ABS_BRAKE:    tmp = "BRAKE";    break;
                    case ABS_HAT0X:    tmp = "HAT0X";    break;
                    case ABS_HAT0Y:    tmp = "HAT0Y";    break;
                    case ABS_HAT1X:    tmp = "HAT1X";    break;
                    case ABS_HAT1Y:    tmp = "HAT1Y";    break;
                    case ABS_HAT2X:    tmp = "HAT2X";    break;
                    case ABS_HAT2Y:    tmp = "HAT2Y";    break;
                    case ABS_HAT3X:    tmp = "HAT3X";    break;
                    case ABS_HAT3Y:    tmp = "HAT3Y";    break;
                    case ABS_PRESSURE: tmp = "PRESSURE"; break;
                    case ABS_DISTANCE: tmp = "DISTANCE"; break;
                    case ABS_TILT_X:   tmp = "TILT_X";   break;
                    case ABS_TILT_Y:   tmp = "TILT_Y";   break;
                    case ABS_MISC:     tmp = "MISC";     break;
                    default:           tmp = "UNKNOWN";  break;
                    }
                    printf("Absolute %s %d", tmp, event.value);
                    break;
                case EV_MSC: printf("Misc"); break;
                case EV_LED: printf("Led");  break;
                case EV_SND: printf("Snd");  break;
                case EV_REP: printf("Rep");  break;
                case EV_FF:  printf("FF");   break;
                    break;
                }
                printf("\n");
            }
            printf("rc = %d, (%s)\n", rc, strerror(errno));
            close(fd);
        }
    }
    return 0;
}

按下电源按键之后,最终实践发现是event2,可以监听到key code以及按键的动作;

	...
	/dev/input/event2: open, fd = 3
Thu Mar 21 21:38:28 2019.801129 type 0x0001; code 0x0074; value 0x00000001; Key 116 (0x74) press
Thu Mar 21 21:38:28 2019.801129 type 0x0000; code 0x0000; value 0x00000000; 
Thu Mar 21 21:38:28 2019.801159 type 0x0001; code 0x0074; value 0x00000000; Key 116 (0x74) release
Thu Mar 21 21:38:28 2019.801159 type 0x0000; code 0x0000; value 0x00000000; 
Thu Mar 21 21:38:35 2019.038000 type 0x0001; code 0x0074; value 0x00000001; Key 116 (0x74) press
Thu Mar 21 21:38:35 2019.038000 type 0x0000; code 0x0000; value 0x00000000; 
Thu Mar 21 21:38:35 2019.038028 type 0x0001; code 0x0074; value 0x00000000; Key 116 (0x74) release
Thu Mar 21 21:38:35 2019.038028 type 0x0000; code 0x0000; value 0x00000000; 

【Linux】系统如何监听电源键powerkey

1、系统会根据以下文件配置进行电源键事件监听

打开文件 /etc/systemd/logind.conf,找到(或添加)以下行,并将默认的 poweroff 改为 ignore:

HandlePowerKey=ignore

2、可以通过 libevdev 库监听电源键

sudo apt-get install libevdev-dev

3、确定哪个是电源按键

sudo apt-get install evtest

sudo evtest /dev/input/eventX

【Linux】定时网络限速

一、安装依赖软件

sudo apt-get install wondershaper
sudo modprobe sch_netem

二、功能配置

00 18   * * *   root    wondershaper clear eth0
00 1    * * *   root    wondershaper eth0 10000 5000
00 10   * * *   root    wondershaper clear eth0
00 14   * * *   root    wondershaper eth0 10000 5000

#限制eth0网卡下载速度10000K,上传速度5000K

sudo wondershaper 网卡名字 10000 5000

#清除eth0网卡的网速限制

sudo wondershaper clear 网卡名字

三、定时启动

# 查看服务状态
sudo  service cron status
# 开启服务
sudo service cron start
# 停止服务
sudo service cron stop
# 重启服务
sudo service cron restart

1、例子

# 如果服务没有开启,开启该服务
sudo service cron restart
# 输入该命令,修改crontab配置。第一次输入该命令时,会提示选择编辑工具,一般选择vim(vi)即可。
crontab –e
# 在上一步打开的终端中(第一次使用该命令的话,在选择编辑工具后),输入下面的内容
# 该内容表示,在每天的0点0分,执行脚本MakeProject.sh
0 0 * * * /home/linduo/Project/MakeProject.sh
 
Crontab定时任务命令格式
 
# 格式如下
# minute hour day-of-month month-of-year day-of-week commands
# 00-59 00-23 01-31 01-12 0-6 (0 is sunday) 
 
# 每天0点0分,执行指定脚本
0 0 * * * /home/linduo/Project/MakeProject.sh
 
# 星期1到星期5,11点30分,执行指定脚本
30 11 * * 1,2,3,4,5 /home/linduo/Project/MakeProject.sh
 
# 星期1、星期3、星期5,23点00,执行指定脚本,并将内容重定向到文件(使用日期命名)
# 获取日期命令,必须使用如下格式,否则会导致cron执行失败。
00 23 * * 1,3,5 /home/linduo/Project/MakeProject.sh all >> "/home/linduo/Project/Build_$(date +"\%Y-\%m-\%d")".log 2>&1

2、格式

 crontab 任务配置基本格式:*  *  *  *  command

第1列表示分钟0~59 每分钟用*或者 */1表示
第2列表示小时0~23(0表示0点)
第3列表示日期1~31
第4列表示月份1~12
第5列标识号星期0~6(0,7都可表示星期天)
第6列要运行的命令

3、添加新指令

crontab -e
00 18   * * *   root    wondershaper clear eth0
00 1    * * *   root    wondershaper eth0 10000 5000
00 10   * * *   root    wondershaper clear eth0
00 14   * * *   root    wondershaper eth0 10000 5000

【Linux】调度策略和优先级

一、背景

在Linux中,线程是一种轻量级的执行单元,可以在进程内独立运行。线程可以分为普通线程和实时线程,它们之间的区别在于其调度和优先级设置。

  SCHED_OTHER,普通的调度(非实时线程),应用层设置优先级0,调度器总会给此类线程分配一定的CPU资源,只不过是被分配到的频次和时间片长度较少。每1s中实时线程和普通线程的时间比例是95 :5。

  普通线程没有固定的响应时间要求,它们的优先级由系统动态调整。Linux使用CFS调度器来管理普通线程。CFS调度器采用一种称为红黑树的数据结构来维护线程的优先级。每个线程都有一个vruntime值,它表示线程在运行队列中消耗的虚拟时间。CFS调度器会根据线程的vruntime值来确定运行的顺序。优先级较高的线程vruntime值较小,因此能够更早地获得CPU的时间片。

  适用场景:实时性要求不高,但要求必须能被执行的线程。

  SCHED_FIFO,抢占式调度(实时线程),实时先行,应用层设置优先级1-99,同一优先级的多个线程中,一旦某个抢占式线程获取CPU,除非被更高优先级线程抢占(比如在非实时线程中创建一个更高优先级的实时线程),或该线程主动让出CPU资源,否则该线程将会一直占用CPU(但总会分配一点资源给SCHED_OTHER非实时线程)。

  适用场景:实时性要求高,不希望被频繁打断的任务。

  SCHED_RR,轮询式调度(实时线程),实时循环,设置优先级1-99,以循环方式运行,每个线程都有一个时间片来执行任务,时间片耗尽后,该线程将被放入队列的末尾,而较低优先级的线程有机会执行。

  适用场景:实时性要求高,允许被频繁打断的任务。

  在Linux中,可以使用sched_setscheduler函数。这个函数允许我们选择普通线程或实时线程。对于普通线程,可以使用nice函数来动态调整优先级。对于实时线程,可以使用sched_setscheduler函数来设置其类型和优先级。

  关于优先级高低和数值大小的关系,在应用层和内核中二者是相反的。

  设置线程的优先级需要谨慎,因为过高的优先级可能会导致系统资源的过度占用,从而影响其他线程和进程的正常运行。另外,需要注意的是,只有具有足够权限的用户才能设置较高的实时线程优先级。

  总结起来,Linux中的线程分为普通线程和实时线程。普通线程的优先级由系统动态调整,而实时线程的优先级由用户显式设置。通过合理地设置线程的优先级,可以提高系统的性能和响应时间。然而,设置线程的优先级需要慎重考虑,以避免影响其他线程和进程的正常运行。

二、方法

    pthread_t pis_task;
    pthread_attr_t attr;
    struct sched_param sched_param;
// 初始化线程属性
    pthread_attr_init(&attr);

    // 设置线程为实时线程
    pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
    pthread_attr_setschedpolicy(&attr, SCHED_FIFO);

    // 设置线程优先级
    sched_param.sched_priority = THREAD_PRIORITY;
    pthread_attr_setschedparam(&attr, &sched_param);

    pthread_create(&pis_task, &attr, PrtMgr_Decode_Task, (void *)&PrintMgr_Init_colorId);
    pthread_setname_np(pis_task, "name");

【Linux】打印机环境安装二

前言

传统USB打印机如何实现网络打印机转变,发挥打印机余热。目前好多不用的机顶盒,我们刷成Linux系统。把打印机的USB线插到机顶盒上,机顶盒通过网线或者wifi连接到路由器上,实现USB到网络转换。那路由器Linux到底需要做哪些操作呢,接下来咱们一起聊聊。

一、安装打印机驱动环境

CUPS是开源的打印机服务开源框架,已集成成千上万的各式打印机驱动,我们不用重复造轮子。

1、安装cups

登陆机顶盒调试,会Linux开发的大家都明白。

apt install cups

2、修改 CUPS 配置文件 /etc/cups/cupsd.conf

将 Listen 修改为 0.0.0.0:631

将 Browsing 修改为 Yes

对应位置加上 Allow all

# Only listen for connections from the local machine.
Listen localhost:631 // [!code --]
Listen 0.0.0.0:631 // [!code ++]
Listen /run/cups/cups.sock 
​
# Show shared printers on the local network.
Browsing Off // [!code --]
Browsing Yes // [!code ++]
BrowseLocalProtocols dnssd
​
# Restrict access to the server...

  Order allow,deny
  Allow all // [!code ++]

​
# Restrict access to the admin pages...

  Order allow,deny
  Allow all // [!code ++]

​
# Restrict access to configuration files...

  AuthType Default
  Require user @SYSTEM
  Order allow,deny
  Allow all // [!code ++]

​
# Restrict access to log files...

  AuthType Default
  Require user @SYSTEM
  Order allow,deny
  Allow all // [!code ++]

3、重启cups服务

systemctl restart cups

4、登陆服务器web,进行打印机添加

访问 https://ip:631 进入 CUPS 的 Web UI,点击添加 Add Printer

5、windows添加网络打印机

【Linux】打印机环境安装一

一、环境配置

 sudo apt-get update
 sudo apt-get upgrade
 sudo apt install cups  #公共UNIX打印系统

二、驱动安装

sudo apt-get install hplip

三、打印机安装

hp-setup -i #第一个选0,第二个按p
xiaobao@armbian:~/software/shareprint$ hp-setup -i

HP Linux Imaging and Printing System (ver. 3.23.12)
Printer/Fax Setup Utility ver. 9.0

Copyright (c) 2001-18 HP Development Company, LP
This software comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to distribute it
under certain conditions. See COPYING file for more details.

(Note: Defaults for each question are maked with a '*'. Press <enter> to accept the default.)


--------------------------------
| SELECT CONNECTION (I/O) TYPE |
--------------------------------

  Num       Connection  Description
            Type
  --------  ----------  ----------------------------------------------------------
  0*        usb         Universal Serial Bus (USB)
  1         net         Network/Ethernet/Wireless (direct connection or JetDirect)

Enter number 0...1 for connection type (q=quit, enter=usb*) ? 0

Using connection type: usb

Setting up device: hp:/usb/DeskJet_1110_series?serial=CN75J28090069Z



---------------------
| PRINT QUEUE SETUP |
---------------------


Please enter a name for this print queue (m=use model name:'DeskJet_1110'*, q=quit) ?
Using queue name: DeskJet_1110
Locating PPD file... Please wait.

Found PPD file: hplip:0/ppd/hplip/HP/hp-deskjet_1110_series.ppd
Description:

Note: The model number may vary slightly from the actual model number on the device.

Does this PPD file appear to be the correct one (y=yes*, n=no, q=quit) ?
Enter a location description for this printer (q=quit) ?
Enter additonal information or notes for this printer (q=quit) ?

Adding print queue to CUPS:
Device URI: hp:/usb/DeskJet_1110_series?serial=CN75J28090069Z
Queue name: DeskJet_1110
PPD file: hplip:0/ppd/hplip/HP/hp-deskjet_1110_series.ppd
Location:
Information:


You do not have permission to add a printer. You need authentication.
Username: root
Password:


---------------------
| PRINTER TEST PAGE |
---------------------


Would you like to print a test page (y=yes*, n=no, q=quit) ? y

HP Linux Imaging and Printing System (ver. 3.23.12)
Testpage Print Utility ver. 6.0

Copyright (c) 2001-18 HP Development Company, LP
This software comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to distribute it
under certain conditions. See COPYING file for more details.


HP Linux Imaging and Printing System (ver. 3.23.12)
System Tray Status Service ver. 2.0

Copyright (c) 2001-18 HP Development Company, LP
This software comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to distribute it
under certain conditions. See COPYING file for more details.

warning: No display found.
error: hp-systray requires Qt4 GUI and DBus support. Exiting.
warning: Unable to connect to dbus. Is hp-systray running?
Printing test page to printer DeskJet_1110...
请求 ID 为 DeskJet_1110-1 (1 个文件)
Test page has been sent to printer.

note: If an error occured, or the test page failed to print, refer to the HPLIP website
note: at: http://hplip.sourceforge.net for troubleshooting and support.


Done.

Done.

linux 获取OS盘符的方法

在服务器测试中,对硬盘的测试有很多,有些测试用例需要我们写一下自动化的脚本,比如给服务器所有的盘施加压力,这个就需要我们把除了OS盘的所有盘遍历出来,下面介绍几种方法来筛选OS盘
我们知道,判断os 盘的方法一般是看其有没有boot分区,通常用两个指令来获取:lsblk和df -h 下面一次介绍一下这两种方法的写法

1、 lsblk 如图所示 带有boot 分区的就是OS盘

系统盘是sda

系统盘是nvme0n1

shell命令行:

lsblk -l  |grep -i boot -B 1 |grep -i disk |awk '{print $1}'

筛选除了OS外所有的盘符

lsblk -l  |grep -vw sda |grep -i disk |awk '{print $1}'
lsblk -l  |grep -vw nvme0n1 |grep -i disk |awk '{print $1}'

2、 df -h

系统盘是sda

shell命令行

df -h | awk '{print $1}' | grep -iE "/dev/sd" | sed 's/[0-9]//g' |sort -u |awk -F "/" {'print $NF'}

系统盘是nvme0n1

shell 命令行

 df -h | awk '{print $1}' | grep -iE "/dev/nvme" | sed 's/p[0-9]//g' |sort -u |awk -F "/" {'print $NF'}

对此可以写成一个小脚本来判断OS,代码如下:

#!/bin/bash
bootdisk=`df -h |grep -i boot | awk '{print $1}' | grep -iE "/dev/sd" | sed 's/[0-9]//g' |sort -u|awk -F "/" '{print $NF}'`
if  test -z "$bootdisk"
then
        bootdisk=`df -h |grep -i boot| awk '{print $1}' | grep -iE "/dev/nvme" | sed 's/p[0-9]*//g' |sort -u|awk -F "/" '{print $NF}'`
        echo "os disk os $bootdisk"
else
        echo "os disk is $bootdisk"
fi

运行结果如下图: