ssh

方法一:

使用下例中ssky-keygen和ssh-copy-id,仅需通过3个步骤的简单设置而无需输入密码就能登录远程Linux主机。 
ssh-keygen 创建公钥和密钥。 
ssh-copy-id 把本地主机的公钥复制到远程主机的authorized_keys文件上。
ssh-copy-id 也会给远程主机的用户主目录(home)和~/.ssh, 和~/.ssh/authorized_keys设置合适的权限 。

步骤1: 用 ssh-key-gen 在本地主机上创建公钥和密钥
ligh@local-host$ ssh-keygen -t  rsa
Enter file in which to save the key (/home/jsmith/.ssh/id_rsa):[秘钥文件名] 
Enter passphrase (empty for no passphrase): [秘钥密码(直接输入回车即为不带密码的秘钥)]
Enter same passphrase again: [重复输入秘钥密码]
Your identification has been saved in /home/jsmith/.ssh/id_rsa.
Your public key has been saved in /home/jsmith/.ssh/id_rsa.pub. 
The key fingerprint is: 33:b3:fe:af:95:95:18:11:31:d5:de:96:2f:f2:35:f9 
ligh@local-host

步骤2: 用 ssh-copy-id 把公钥复制到远程主机上
ligh@local-host$ ssh-copy-id -i ~/.ssh/id_rsa.pub  root@192.168.0.3
ligh@remote-host‘s password:
Now try logging into the machine, with ―ssh ?remote-host‘‖, and check in: 
.ssh/authorized_keys to make sure we haven‘t added extra keys that you weren‘t expecting.
[注: ssh-copy-id 把密钥追加到远程主机的 .ssh/authorized_key 上.]

步骤3: 直接登录远程主机
ligh@local-host$ ssh remote-host 
Last login: Sun Nov 16 17:22:33 2008 from 192.168.1.2 
[注: SSH 不会询问密码.] 
ligh@remote-host$ 
[注: 你现在已经登录到了远程主机上]

方法二

一、概述

1、就是为了让两个linux机器之间使用ssh不需要用户名和密码。采用了数字签名RSA或者DSA来完成这个操作

2、模型分析

假设 A 为客户机器,B 为目标机;

要达到的目的:
A机器ssh登录B机器无需输入密码;
加密方式选 rsa|dsa均可以,默认dsa

二、具体操作流程

单向登陆的操作过程(能满足上边的目的):
1、登录A机器 
2、ssh-keygen -t [rsa|dsa],将会生成密钥文件和私钥文件 id_rsa,id_rsa.pub或id_dsa,id_dsa.pub
3、将 .pub 文件复制到B机器的 .ssh 目录, 并 cat id_rsa.pub >> ~/.ssh/authorized_keys
4、大功告成,从A机器登录B机器的目标账户,不再需要密码了;(直接运行 #ssh 用户名@ip )

http://blog.csdn.net/kongqz/article/details/6338690

以下两点注意:

1、配置私钥
a、使用命令ssh-keygen -t rsa生成密钥,会生成一个私钥和一个公钥,在提示输入passphrase时如果不输入,直接回车,那么以后你登录服务器就不会验证密码,否则会要求你输入passphrase,默认会将私钥放在/(用户名)/.ssh/id_rsa公钥放在
/用户名/.ssh/id_rsa.pub。
b、将公钥拷贝到远程服务器上的/(用户名)/.ssh/authorized_keys文件
(scp /用户名/.ssh/id_rsa.pub server:/用户名/.ssh/authorized_keys),注意,文件名一定要叫authorized_keys。权限600
c、客户端上保留私钥,公钥留不留都可以。也就是服务器上要有公钥,客户端上要有私钥。这样就可以实现无密码验证登录了。
2、如果想要获得最大化的安全性,禁止口令登录,可以修改远程主机上/etc/ssh/sshd_conf中的
PasswordAuthentication yes 改为
PasswordAuthentication no
也即只能使用密匙认证的openssh,禁止使用口令认证

1.禁用 root 用户通过 ssh 登录: 编辑 /etc/ssh/sshd_config,设置 PermitRootLogin 为 no 可禁止普通用户以 root 用户身份远程登录。
2.禁止对 SSH 进行基于密码的身份验证:编辑 /etc/ssh/sshd_config,设置 PasswordAuthentication 为 no 可禁止对 SSH 进行基于密码的身份验证。
注:若要禁止基于密码的身份验证,但允许对 root 执行基于私钥的身份验证,可设置 PermitRootLogin 为 prohibit-password 。

1、/etc/ssh/ssh_config配置文件

选项参数                                      说明
Host *                      选项“Host”只对能够匹配后面字串的计算机有效。“*”表示所有的计算机。
ForwardAgent no             设置连接是否经过验证代理(如果存在)转发给远程计算机。
ForwardX11 no                设置X11连接是否被自动重定向到安全的通道和显示集(DISPLAY set)
RhostsAuthentication no        设置是否使用基于rhosts的安全验证
RhostsRSAAuthentication no       设置是否使用用RSA算法的基于rhosts的安全验证
RSAAuthentication yes              设置是否使用RSA算法进行安全验证
PasswordAuthentication yes        设置是否使用口令验证
FallBackToRsh no                      设置如果用ssh连接出现错误是否自动使用rsh
UseRsh no                           设置是否在这台计算机上使用“rlogin/rsh”
BatchMode no            如果设为“yes”,passphrase/password(交互式输入口令)的提示将被禁止。当不能交互式输入口令的时候,这个选项对脚本文件和批处理任务十分有用
CheckHostIP yes         设置ssh是否查看连接到服务器的主机的IP地址以防止DNS欺骗。建议设置为“yes”
StrictHostKeyChecking no   如果设置成“yes”,ssh就不会自动把计算机的密匙加入“$HOME/.ssh/known_hosts”文件,并且一旦计算机的密匙发生了变化,就拒绝连接
IdentityFile ~/.ssh/identity        设置从哪个文件读取用户的RSA安全验证标识
Port 22                                   设置连接到远程主机的端口
Cipher blowfish                           设置加密用的密码
EscapeChar ~                              设置escape字符

2、/etc/ssh/sshd_config配置文件

Port 22            SSH 预设使用 22 这个 port,您也可以使用多的 port !
Protocol 2,1    选择的 SSH 协议版本,可以是 1 也可以是 2 ,如果要同时支持两者,就必须要使用 2,1 
ListenAddress 0.0.0.0       监听的主机适配卡!举个例子来说,如果您有两个 IP,分别是 192.168.0.100 及 192.168.2.20 ,那么只想要开放 192.168.0.100 时,就可以写如同下面的样式:
ListenAddress 192.168.0.100     只监听来自 192.168.0.100 这个 IP 的SSH联机。如果不使用设定的话,则预设所有接口均接受 SSH
PidFile /var/run/sshd.pid        可以放置 SSHD 这个 PID 的档案!左列为默认值
LoginGraceTime 600                当使用者连上 SSH server 之后,会出现输入密码的画面,在该画面中,在多久时间内没有成功连上 SSH server ,就断线!时间为秒!
Compression yes                                是否可以使用压缩指令?
HostKey /etc/ssh/ssh_host_key                  SSH version 1 使用的私钥
HostKey /etc/ssh/ssh_host_rsa_key              SSH version 2 使用的 RSA 私钥
HostKey /etc/ssh/ssh_host_dsa_key              SSH version 2 使用的 DSA 私钥
KeyRegenerationInterval 3600                    由前面联机的说明可以知道, version 1 会使用 server 的 Public Key ,每隔一段时间来重新建立一次!时间为秒!
ServerKeyBits 768                               Server key 的长度!
SyslogFacility AUTH                             当有人使用 SSH 登入系统的时候,SSH会记录信息
LogLevel INFO                                   登录记录的等级—》全部
PermitRootLogin no                               是否允许 root 登入!预设是允许的,但是建议设定成 no!
UserLogin no                                    在 SSH 底下本来就不接受 login 这个程序的登入!
StrictModes yes                          当使用者的 host key 改变之后,Server 就不接受联机
RSAAuthentication yes                    是否使用纯的 RSA 认证!?仅针对 version 1 !
PubkeyAuthentication yes                  是否允许 Public Key ?只有 version 2
AuthorizedKeysFile   .ssh/authorized_keys   设定若要使用不需要密码登入的账号时,那么那个账号的存放档案所在名
RhostsAuthentication no                       本机系统不使用 .rhosts , .rhosts 不安全!
IgnoreRhosts yes                              是否取消使用 ~/.ssh/.rhosts 来做为认证!
RhostsRSAAuthentication no    针对version 1使用 rhosts 档案在/etc/hosts.equiv配合 RSA 演算方式来进行认证!
HostbasedAuthentication no     这个项目与上面的项目类似,不过是给 version 2 使用的!
IgnoreUserKnownHosts no         是否忽略家目录内的 ~/.ssh/known_hosts 这个档案所记录的主机内容
PasswordAuthentication yes      密码验证当然是需要的!
PermitEmptyPasswords no         上面那一项如果设定为 yes 的话,这一项就最好设定为 no ,这个项目在是否允许以空的密码登入!
ChallengeResponseAuthentication yes   挑战任何的密码认证!所以,任何 login.conf 规定的认证方式,均可适用!
PAMAuthenticationViaKbdInt yes    是否启用其它的 PAM 模块!启用这个模块将会导致 PasswordAuthentication 设定失效!
 
与Kerberos 有关的参数设定!底下不用设定
KerberosAuthentication no
KerberosOrLocalPasswd yes
KerberosTicketCleanup yes
KerberosTgtPassing no
 
有关在 X-Window 底下使用的相关设定
X11Forwarding yes
X11DisplayOffset 10
X11UseLocalhost yes
 
PrintMotd no   登入后是否显示出一些信息呢?例如上次登入的时间、地点等,预设是 yes 为了安全,可以考虑改为 no 
PrintLastLog yes   显示上次登入的信息!预设也是 yes
KeepAlive yes       一般而言,如果设定这项目的话,那么 SSH Server 会传送KeepAlive 的讯息给 Client 端,以确保两者的联机正常!在这个情况下,任何一端死掉后, SSH 可以立刻知道!而不会有僵尸程序的发生!
UsePrivilegeSeparation yes    使用者的权限设定项目!
MaxStartups 10                同时允许几个尚未登入的联机画面
DenyUsers *                   设定受抵挡的使用者名称
AllowUsers *                  设定允许的使用者名称

zerotier 内网穿透

安装:curl -s https://install.zerotier.com | sudo bash

一.配置 Linux 的数据转发和路由控制

  • Linux 系统内核可以通过 sysctliptables 两个命令控制网络数据转.
  • 查看内核 IP 转发设置,0 表示处于关闭状态:
  • $ sudo sysctl net.ipv4.ip_forward
  • net.ipv4.ip_forward = 0
  • 编辑配置文件开启 Linxu 内核的 IP 数据转发:
  • sudo vim /etc/sysctl.conf
  • 将第 28 行的注释去掉,设置 net.ipv4.ip_forward=1
  • net.ipv4.ip_forward=1 # lin 28
  • 激活配置文件设置:
  • $ sudo sysctl -p
  • net.ipv4.ip_forward = 1
  • 查看内核 IP 转发设置,1 表示开启状态:
  • $ sudo sysctl net.ipv4.ip_forward
  • net.ipv4.ip_forward = 1

二.查看网口信息

$ ifconfig
可以发现,在 Ubuntu 上 enp123s0f0 用来接入真实物理网络,zt7u3fcxwr 用来接入 zerotier 虚拟网络. 注意后续命令中使用网口名称的地方~
使用 iptables 启用 enp123s0f0 及zt7u3fcxwr  的网络地址转换和 IP 伪装:
sudo iptables -t nat -A POSTROUTING -o enp123s0f0 -j MASQUERADE
sudo iptables -t nat -A POSTROUTING -o zt7u3fcxwr -j MASQUERADE

iptables -I FORWARD -i zthxxxx -j ACCEPT
iptables -I FORWARD -o zthxxxx -j ACCEPT
iptables -t nat -I POSTROUTING -o zthxxxx -j MASQUERADE





允许流量转发和跟踪活动连接:
sudo iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
接下来设置从zt7u3fcxwr 到 enp123s0f0 流量转发。 反向规则不是必需的,因为在本文所述场景下没有用到:
sudo iptables -A FORWARD -i zt7u3fcxwr -o enp123s0f0 -j ACCEPT

linux流量转发

iptables -t nat -A POSTROUTING -o vmbr0(真实网卡) -j MASQUERADE

iptables -A FORWARD -m conntrack –ctstate RELATED,ESTABLISHED -j ACCEPT

 iptables -A FORWARD -i zero网卡 -o vmbr0(真实网卡) -j ACCEPT

安装 apt-get install iptables-persistent

netfilter-persistent save (保持iptables规则)

  1. 加入网络命令‌:
    • 加入网络:zerotier-cli join 网络ID
    • 查看当前连接的网络列表:zerotier-cli listnetworks
  2. 查看状态和服务命令‌:
    • 查看Zerotier服务状态:zerotier-cli info
    • 启动Zerotier服务:sudo systemctl start zerotier-one.service
    • 设置Zerotier服务开机自启动:sudo systemctl enable zerotier-one.service
    • 停止Zerotier服务:sudo systemctl stop zerotier-one.service

流量转发

sudo iptables -t nat -A POSTROUTING -o $PHY_IFACE -j MASQUERADE sudo iptables -A FORWARD -i $PHY_IFACE -o $ZT_IFACE -m state –state RELATED,ESTABLISHED -j ACCEPT sudo iptables -A FORWARD -i $ZT_IFACE -o $PHY_IFACE -j ACCEPT

这三条 iptables 规则用于配置网络地址转换(NAT)和数据包转发;

含义如下:

  1. 规则 1: sudo iptables -t nat -A POSTROUTING -o $PHY_IFACE -j MASQUERADE这条规则在 nat 表的 POSTROUTING 链中添加了一条规则。-o $PHY_IFACE 表示这条规则适用于所有通过 $PHY_IFACE 这个网络接口(通常是物理接口)出去的数据包。-j MASQUERADE 指定了 NAT 操作中的伪装(masquerading)。这意味着,当数据包从 $PHY_IFACE 发送出去时,其源 IP 地址会被替换为 $PHY_IFACE 的 IP 地址。这通常用于允许内部网络通过一个公共 IP 地址进行外部通信;
  2. 规则 2: sudo iptables -A FORWARD -i $PHY_IFACE -o $ZT_IFACE -m state --state RELATED,ESTABLISHED -j ACCEPT这条规则在 filter 表的 FORWARD 链中添加了一条规则。-i $PHY_IFACE 表示适用于从 $PHY_IFACE 这个接口进入的数据包,-o $ZT_IFACE 表示这些数据包要转发到 $ZT_IFACE 这个接口。-m state --state RELATED,ESTABLISHED 指定了只有那些与已有连接相关或已经建立的连接的数据包才被接受(ACCEPT)。这个规则通常用于允许来自外部网络的返回流量进入内部网络,从而支持诸如 HTTP 会话等;
  3. 规则 3: sudo iptables -A FORWARD -i $ZT_IFACE -o $PHY_IFACE -j ACCEPT这条规则在 filter 表的 FORWARD 链中添加了一条规则。-i $ZT_IFACE 表示适用于从 $ZT_IFACE 这个接口进入的数据包,-o $PHY_IFACE 表示这些数据包要转发到 $PHY_IFACE 这个接口。-j ACCEPT 表示这些数据包会被接受并转发。这条规则允许来自 $ZT_IFACE 的流量经过路由器转发到 $PHY_IFACE,从而实现网络之间的数据传输;总结:
  • 第一条规则用于设置源地址伪装,允许内部网络设备通过一个公共 IP 地址进行外部通信;
  • 第二条规则允许返回流量和已经建立的连接的数据包从外部网络进入内部网络;
  • 第三条规则允许来自内部网络的数据包被转发到外部网络;

转发

# 启用 IPv4 转发 echo ‘net.ipv4.ip_forward=1’ >> /etc/sysctl.conf sysctl -p # 配置 NAT 和转发规则 iptables -t nat -A POSTROUTING -o <内网网卡> -j MASQUERADE iptables -A FORWARD -i <ZeroTier虚拟网卡> -o <内网网卡> -m state –state RELATED,ESTABLISHED -j ACCEPT iptables -A FORWARD -i <内网网卡> -o <ZeroTier虚拟网卡> -j ACCEPT # 保存规则(OpenWrt) /etc/init.d/firewall save

甲骨文云服务器Oracle cloud 分配并启用 IPv6 地址教程

过程1: 创建IPv6 CIDR块

(1)打开Oracle 虚拟云网络控制台

(2)选择需要添加IPv6的VCN
添加CIDR

(3)点击左侧菜单栏中的CIDR Blocks/Prefixes

(4)点击右侧界面中的 Add CIDR Block/IPv6 Prefix
添加CIDR

(5)勾选Assign an Oracle allocated IPv6 /56 preflx,并点击添加CIDR按钮

添加CIDR

(6)稍等一会后,你会发现在CIDR Blocks界面中多出了一个 /56 的 IPv6 段了

    将IPv6 CIDR块与子网关联

    1. 打开Oracle 虚拟云网络控制台
    2. 点击页面左侧边栏的 子网
    3. 选择使用中的子网
    4. 在做侧边栏中找到IPv6 Prefixes 进入并在右侧界面中点击Add IPv6 Prefix
    5. 在弹出的界面中勾选Assign an Oracle allocated IPv6 /64 prefix 在下面的输入框中输入2位16进制的代码

    过程2:更新安全列表规则

    要使实例能够通过 IPv6 发送和接收流量,您必须更新安全组规则以包含 IPv6 地址的规则。比如你的网站 80端口

    更新入站安全组规则

    1. 打开Oracle 虚拟云网络控制台
    2. 点击页面左侧边栏的 安全列表 并选择正在使用的列表。
    3. 在入站规则选项卡中,选择编辑入站规则。
    4. 对于允许 IPv4 流量的每条规则,选择添加规则并配置该规则以允许相应的 IPv6 流量。例如,要添加允许通过 IPv6 的所有 HTTP 流量的规则,请为“类型 ”和“源”选择HTTP。::/0
    5. 保存规则。

    过程3:更新路由表

    更新公有子网的路由表

    1. 打开Oracle 虚拟云网络控制台
    2. 点击页面左侧边栏的 路由表。选择正在使用的路由表
    3. 选择路由表。选择添加路由规则
    4. 选择添加路线。选择::/0目的地 。
    5. 保存更改。

    为实例分配IPv6地址

    1. 打开实例控制台
    2. 进入需要改为IPv6的实例详情页面
    3. 找到左侧边栏里的附加的 VNIC,并点击右侧的VNIC
    4. 选择左侧边栏里的IPv6 地址后选择右侧的分配IPv6地址,在弹出的页面中选择自动从 IPv6 前缀中分配
    5. 现在我们回到实例的管理面板,查看主机的详细信息,就会发现已经被分配了新的IPv6地址了。

    Linux win 系统使用 USBIP 远程共享 USB 设备

    操作步骤

    配置 USB Server

    • 在本地计算机上(Ubuntu),依次执行以下命令,安装 USBIP 并加载相关的内核模块。
      1. sudo apt-get install usbip
      2. sudo modprobe usbip-core
      3. sudo modprobe vhci-hcd
      4. sudo modprobe usbip_host
    • 插入 USB 设备,并执行以下命令,查询可用的 USB 设备。
      1. usbip list --local
      例如,在本地计算机上插入一个usb,返回如下结果:
    • busid 1-1 (1bc0:0055)
      unknown vendor : unknown product (1bc0:0055)
    • 记录 busid 的值,并依次执行以下命令,启动监听服务,指定 USBIP 端口号,共享 USB 设备。
      1. sudo usbipd -D [--tcp-port PORT]sudo usbip bind -b [busid]
      例如,USBIP 指定端口号为3240端口(即 USBIP 的默认端口),busid 为1-1,则执行以下命令:
      1. sudo usbipd -D
      2. sudo usbip bind -b 1-1
    • (可选)执行以下命令,创建 SSH 隧道,并使用端口监听。 说明没有公网 IP 的本地计算机,请执行此步骤。如您的本地计算机有公网 IP,请跳过此步骤。
      1. ssh -Nf -R USB/IP指定端口号:localhost:USB/IP指定端口号 root@your_hostyour_host
      表示云服务器的 IP 地址。 例如,USBIP 的端口号为3240端口,云服务器的 IP 地址为192.168.15.24,则执行以下命令:
      1. ssh -Nf -R 3240:localhost:3240 root@192.168.15.24
    • unknown vendor : unknown product (1bc0:0055)

    配置 USB Client

    1. 依次执行以下命令,下载 USB/IP 源。
      1. rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
      2. rpm -ivh http://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm
    2. 依次执行以下命令,安装 USBIP。
      1. yum -y install kmod-usbip usbip-utils
      2. modprobe usbip-core
      3. modprobe vhci-hcd
      4. modprobe usbip-host
    3. 执行以下命令,查询云服务器可用的 USB 设备。
      1. usbip list --remote 127.0.0.1
      例如,找到usb 的信息,返回如下结果:
      1. Exportable USB devices
      2. ======================
      3. -127.0.0.1 1-1.3: unknown vendor : unknown product (1bc0:0055) product(096e:031b):/sys/devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.3:(Defined at Interface level)(00/00/00)
    4. 执行以下命令,将 USB 设备绑定至服务器中。
      1. usbip attach --remote=127.0.0.1 --busid=1-1.3
    5. 执行以下命令,查看当前 USB 设备列表。
      1. lsusb
      返回类似如下信息,即表示共享成功。

    配置 WIN Client

    1.下载usbip-win-0.3.6-dev

    https://github.com/cezanne/usbip-win

    1. 执行以下命令,查询云服务器可用的 USB 设备。
      1. usbip list --remote 127.0.0.1
      例如,找到usb 的信息,返回如下结果:
      1. Exportable USB devices
      2. ======================
      3. -127.0.0.1 1-1.3: unknown vendor : unknown product (1bc0:0055) product(096e:031b):/sys/devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.3:(Defined at Interface level)(00/00/00)
    2. 执行以下命令,将 USB 设备绑定至
      1. usbip attach --remote=127.0.0.1 --busid=1-1.3

    jq

    1.  jq简介与安装    

        jq是一款命令行下处理JSON数据的工具。

        其可以接受标准输入,命令管道或者文件中的JSON数据,经过一系列的过滤器(filters)和表达式的转后形成我们需要的数据结构并将结果输出到标准输出中。

        jq的这种特性使我们可以很容易地在Shell脚本中调用它。

    1) jq编译安装
    jq 的源代码可以从其代码仓库中获得。编译 jq 的指令如下:
    [root@ss-server ~]# git clone https://github.com/stedolan/jq.git
    [root@ss-server ~]# cd jq
    [root@ss-server ~]# autoreconf -i
    [root@ss-server ~]# ./configure --disable-maintainer-mode
    [root@ss-server ~]# make
    [root@ss-server ~]# make install
     
    2)jq直接安装(centos7可以直接yum安装jq)
    [root@ss-server ~]# yum install -y jq
    [root@ss-server ~]# jq --version
    jq-1.5

    2.  基本用法

    一.  格式化

    1.  将一行数据使用json格式输出

    [root@k8s-master ~]# echo -n '{"id":1, "name":"zhangsan", "score":[75, 85, 90]}'|jq .
    {
      "id": 1,
      "name": "zhangsan",
      "score": [
        75,
        85,
        90
      ]
    }

    (2).  将json格式输出到一行

    [root@k8s-master ~]# jq -c . <<eof
    > {
    >   "id": 1,
    >   "name": "zhangsan",
    >   "score": [
    >     75,
    >     85,
    >     90
    >   ]
    > }
    > eof
    {"id":1,"name":"zhangsan","score":[75,85,90]} 

    二.  属性提取

    1.  取id的值

    [root@k8s-master ~]# echo  '{"id":1, "name":"zhangsan", "score":[75, 85, 90]}' | jq '.id'
    1

    2.  取name的值

    [root@k8s-master ~]# echo  '{"id":1, "name":"zhangsan", "score":[75, 85, 90]}' | jq '.name'
    "zhangsan"

    3.  取name的值,去掉双引号

    [root@k8s-master ~]# echo  '{"id":1, "name":"zhangsan", "score":[75, 85, 90]}' | jq -r '.name'
    zhangsan

     4.  取多层值

    [root@k8s-master ~]# echo -n '{"id":1, "name":"zhangsan", "attr":{"height":1.78,"weight":"60kg"}}'|jq '.attr.height'
    1.78

    5.  取数组值

    $ echo -n '{"id":1, "name":"zhangsan", "score":[75, 85, 90]}'|jq -r '.score[0]'
    75
     
    $ echo -n '[75, 85, 90]'|jq -r '.[0]'
    75
     
    # 数组截取
    $ echo -n '[75, 85, 90]'|jq -r '.[1:3]'
    [
      85,
      90
    ]
     
    # []展开数组
    $ echo -n '[75, 85, 90]'|jq '.[]'
    75
    85
    90

     6.  展开所有结构

    [root@k8s-master ~]# echo  '{"id":1, "name":"zhangsan", "score":[75, 85, 90]}' | jq -c '..'
    {"id":1,"name":"zhangsan","score":[75,85,90]}
    1
    "zhangsan"
    [75,85,90]
    75
    85
    90

    7.  其他情况

    # 从非对象类型中提取字段,会报错
    $ echo -n '{"id":1, "name":"zhangsan", "attr":{"height":1.78,"weight":"60kg"}}'|jq '.name.alias'
    jq: error (at <stdin>:0): Cannot index string with string "alias"
     
    # 使用?号可以避免这种报错
    $ echo -n '{"id":1, "name":"zhangsan", "attr":{"height":1.78,"weight":"60kg"}}'|jq '.name.alias?'
     
    # //符号用于,当前面的表达式取不到值时,执行后面的表达式
    $ echo -n '{"id":1, "name":"zhangsan", "attr":{"height":1.78,"weight":"60kg"}}'|jq '.alias//.name'
    "zhangsan"

    三.  管道,逗号与括号

    1.  管道可以将值从前一个命令传送到后一个命令

    [root@k8s-master ~]# echo -n '{"id":1, "name":"zhangsan", "attr":{"height":1.78,"weight":"60kg"}}'|jq '.attr|.height'
    1.78

    2.  可以做一些简单的运算

    $ echo -n '{"id":1, "name":"zhangsan", "attr":{"height":1.78,"weight":"60kg"}}'|jq '.attr|.height*100|tostring + "cm"'
    "178cm"

    3. 使用逗号可以输出多个结果

    [root@k8s-master ~]# echo -n '{"id":1, "name":"zhangsan", "attr":{"height":1.78,"weight":"60kg"}}'|jq -r '.attr.height,.attr.weight'
    1.78
    60kg

    四.  将读取的元素,都当作字符串,使用-R参数

    [root@k8s-master ~]# seq 4 | jq -R '.'
    "1"
    "2"
    "3"
    "4"

    五.  将json元素,变成json数组元素

    [root@k8s-master ~]# echo -n '{"id":1, "name":"zhangsan"}' | jq -s '.'
    [
      {
        "id": 1,
        "name": "zhangsan"
      }
    ]

    六.  数据构造

    $ cat data.txt
    id  name      age  score
    1   zhangsan  17   75
    2   lisi      16   80
    3   wangwu    18   85
    4   zhaoliu   18   90
     
    # 每行分割成数组,[]构造新的数组输出
    $ tail -n+2 data.txt|jq -R '[splits("\\s+")]' -c
    ["1","zhangsan","17","75"]
    ["2","lisi","16","80"]
    ["3","wangwu","18","85"]
    ["4","zhaoliu","18","90"]
     
    $ jq -n '{id:1, name:"zhangsan"}' -c
    {"id":1,"name":"zhangsan"}
     
    # 每行转换为对象,{}构造新的对象格式输出
    $ tail -n+2 data.txt|jq -R '[splits("\\s+")] | {id:.[0]|tonumber, name:.[1], age:.[2], score:.[3]}' -c
    {"id":1,"name":"zhangsan","age":"17","score":"75"}
    {"id":2,"name":"lisi","age":"16","score":"80"}
    {"id":3,"name":"wangwu","age":"18","score":"85"}
    {"id":4,"name":"zhaoliu","age":"18","score":"90"}
     
    # \()字符串占位变量替换
    $ cat data.json
    {"id":1,"name":"zhangsan","age":"17","score":"75"}
    {"id":2,"name":"lisi","age":"16","score":"80"}
    {"id":3,"name":"wangwu","age":"18","score":"85"}
    {"id":4,"name":"zhaoliu","age":"18","score":"90"}
     
    $ cat data.json |jq '"id:\(.id),name:\(.name),age:\(.age),score:\(.score)"' -r
    id:1,name:zhangsan,age:17,score:75
    id:2,name:lisi,age:16,score:80
    id:3,name:wangwu,age:18,score:85
    id:4,name:zhaoliu,age:18,score:90 

    七.  基础函数

    # has函数,检测对象是否包含key
    $ echo -n '{"id":1,"name":"zhangsan","age":"17","score":"75"}'|jq 'has("id")'
    true
     
    # del函数,删除某个属性
    $ echo -n '{"id":1,"name":"zhangsan","age":"17","score":"75"}'|jq 'del(.id)' -c
    {"name":"zhangsan","age":"17","score":"75"}
     
    # map函数,对数组中每个元素执行表达式计算,计算结果组织成新数组
    $ seq 4|jq -s 'map(. * 2)' -c
    [2,4,6,8]
     
    # 上面map函数写法,其实等价于这个写法
    $ seq 4|jq -s '[.[]|.*2]' -c
    [2,4,6,8]
     
    # keys函数,列出对象属性
    $ echo -n '{"id":1,"name":"zhangsan","age":"17","score":"75"}'|jq 'keys' -c
    ["age","id","name","score"]
     
    # to_entries函数,列出对象键值对
    $ echo -n '{"id":1,"name":"zhangsan","age":"17","score":"75"}'|jq 'to_entries' -c
    [{"key":"id","value":1},{"key":"name","value":"zhangsan"},{"key":"age","value":"17"},{"key":"score","value":"75"}]
     
    # length函数,计算数组或字符串长度
    $ jq -n '[1,2,3,4]|length'
    4
     
    # add函数,计算数组中数值之和
    $ seq 4|jq -s 'add'
    10
     
    # tostring与tonumber,类型转换
    $ seq 4|jq 'tostring|tonumber'
    1
    2
    3
    4
     
    # type函数,获取元素类型
    $ jq 'type' <<eof
    1
    "zhangsan"
    true
    null
    {"id":1}
    [75, 80, 85]
    eof
     
    "number"
    "string"
    "boolean"
    "null"
    "object"
    "array"

    八.  过滤,排序,分组函数

    $ cat data.json
    {"id":1,"name":"zhangsan","sex": 0, "age":"17","score":"75"}
    {"id":2,"name":"lisi","sex": 1, "age":"16","score":"80"}
    {"id":3,"name":"wangwu","sex": 0, "age":"18","score":"85"}
    {"id":4,"name":"zhaoliu","sex": 0, "age":"18","score":"90"}
     
    # select函数用于过滤,类似SQL中的where
    $ cat data.json |jq 'select( (.id>1) and (.age|IN("16","17","18")) and (.name != "lisi") or (has("attr")|not) and (.score|tonumber >= 90) )' -c
    {"id":3,"name":"wangwu","sex":0,"age":"18","score":"85"}
    {"id":4,"name":"zhaoliu","sex":0,"age":"18","score":"90"}
     
    # 有一些简化的过滤函数,如arrays, objects, iterables, booleans, numbers, normals, finites, strings, nulls, values, scalars
    # 它们根据类型过滤,如objects过滤出对象,values过滤出非null值等
    $ jq -c 'objects' <<eof
    1
    "zhangsan"
    true
    null
    {"id":1}
    [75, 80, 85]
    eof
     
    {"id":1}
     
    $ jq -c 'values' <<eof
    1
    "zhangsan"
    true
    null
    {"id":1}
    [75, 80, 85]
    eof
     
    1
    "zhangsan"
    true
    {"id":1}
    [75,80,85]
     
    # 选择出id与name字段,类似SQL中的select id,name
    $ cat data.json|jq -s 'map({id,name})[]' -c
    {"id":1,"name":"zhangsan"}
    {"id":2,"name":"lisi"}
    {"id":3,"name":"wangwu"}
    {"id":4,"name":"zhaoliu"}
     
    # 提取前2行,类似SQL中的limit 2
    $ cat data.json|jq -s 'limit(2; map({id,name})[])' -c
    {"id":1,"name":"zhangsan"}
    {"id":2,"name":"lisi"}
     
    # 按照age、id排序,类似SQL中的order by age,id
    $ cat data.json|jq -s 'sort_by((.age|tonumber), .id)[]' -c
    {"id":2,"name":"lisi","sex":1,"age":"16","score":"80"}
    {"id":1,"name":"zhangsan","sex":0,"age":"17","score":"75"}
    {"id":3,"name":"wangwu","sex":0,"age":"18","score":"85"}
    {"id":4,"name":"zhaoliu","sex":0,"age":"18","score":"90"}
     
     
    # 根据sex与age分组,并每组聚合计算count(*)、avg(score)、max(id)
    $ cat data.json |jq -s 'group_by(.sex, .age)[]' -c
    [{"id":1,"name":"zhangsan","sex":0,"age":"17","score":"75"}]
    [{"id":3,"name":"wangwu","sex":0,"age":"18","score":"85"},{"id":4,"name":"zhaoliu","sex":0,"age":"18","score":"90"}]
    [{"id":2,"name":"lisi","sex":1,"age":"16","score":"80"}]
     
    $ cat data.json |jq -s 'group_by(.sex, .age)[]|{sex:.[0].sex, age:.[0].age, count:length, avg_score:map(.score|tonumber)|(add/length), scores:map(.score)|join(","), max_id:map(.id)|max }' -c                
    {"sex":0,"age":"17","count":1,"avg_score":75,"scores":"75","max_id":1}
    {"sex":0,"age":"18","count":2,"avg_score":87.5,"scores":"85,90","max_id":4}
    {"sex":1,"age":"16","count":1,"avg_score":80,"scores":"80","max_id":2}

    九.  字符串操作函数

    # contains函数,判断是否包含,实际也可用于判断数组是否包含某个元素
    $ echo hello | jq -R 'contains("he")'
    true
     
    # 判断是否以he开头
    $ echo hello | jq -R 'startswith("he")'
    true
     
    # 判断是否以llo结尾
    $ echo hello | jq -R 'endswith("llo")'
    true
     
    # 去掉起始空格
    $ echo ' hello '|jq -R 'ltrimstr(" ")|rtrimstr(" ")'
    "hello"
     
    # 大小写转换
    $ echo hello|jq -R 'ascii_upcase'
    "HELLO"
     
    $ echo HELLO|jq -R 'ascii_downcase'
    "hello"
     
    # 字符串数组,通过逗号拼接成一个字符串
    $ seq 4|jq -s 'map(tostring)|join(",")'
    "1,2,3,4"
     
    # json字符串转换为json对象
    $ echo -n '{"id":1,"name":"zhangsan","age":"17","attr":"{\"weight\":56,\"height\":178}"}'|jq '.attr = (.attr|fromjson)' -c
    {"id":1,"name":"zhangsan","age":"17","attr":{"weight":56,"height":178}}
     
    # json对象转换为json字符串
    $ echo -n '{"id":1,"name":"zhangsan","age":"17","attr":{"weight":56,"height":178}}'|jq '.attr = (.attr|tojson)'
    {
      "id": 1,
      "name": "zhangsan",
      "age": "17",
      "attr": "{\"weight\":56,\"height\":178}"
    }
     
    $ cat data.txt
    id:1,name:zhangsan,age:17,score:75
    id:2,name:lisi,age:16,score:80
    id:3,name:wangwu,age:18,score:85
    id:4,name:zhaoliu,age:18,score:90
     
    # 正则表达式过滤,jq使用的是PCRE
    $ cat data.txt|jq -R 'select(test("id:\\d+,name:\\w+,age:\\d+,score:8\\d+"))' -r
    id:2,name:lisi,age:16,score:80
    id:3,name:wangwu,age:18,score:85
     
    # 正则拆分字符串
    $ cat data.txt|jq -R '[splits(",")]' -cr
    ["id:1","name:zhangsan","age:17","score:75"]
    ["id:2","name:lisi","age:16","score:80"]
    ["id:3","name:wangwu","age:18","score:85"]
    ["id:4","name:zhaoliu","age:18","score:90"]
     
    # 正则替换字符串
    $ cat data.txt |jq -R 'gsub("name"; "nick")' -r
    id:1,nick:zhangsan,age:17,score:75
    id:2,nick:lisi,age:16,score:80
    id:3,nick:wangwu,age:18,score:85
    id:4,nick:zhaoliu,age:18,score:90
     
    # 正则表达式捕获数据
    $ cat data.txt|jq -R 'match("id:(?<id>\\d+),name:(?<name>\\w+),age:\\d+,score:8\\d+")' -cr
    {"offset":0,"length":30,"string":"id:2,name:lisi,age:16,score:80","captures":[{"offset":3,"length":1,"string":"2","name":"id"},{"offset":10,"length":4,"string":"lisi","name":"name"}]}
    {"offset":0,"length":32,"string":"id:3,name:wangwu,age:18,score:85","captures":[{"offset":3,"length":1,"string":"3","name":"id"},{"offset":10,"length":6,"string":"wangwu","name":"name"}]}
     
    # capture命名捕获,生成key是捕获组名称,value是捕获值的对象
    $ cat data.txt|jq -R 'capture("id:(?<id>\\d+),name:(?<name>\\w+),age:\\d+,score:8\\d+")' -rc
    {"id":"2","name":"lisi"}
    {"id":"3","name":"wangwu"}
     
    # 正则扫描输入字符串
    $ cat data.txt|jq -R '[scan("\\w+:\\w+")]' -rc
    ["id:1","name:zhangsan","age:17","score:75"]
    ["id:2","name:lisi","age:16","score:80"]
    ["id:3","name:wangwu","age:18","score:85"]
    ["id:4","name:zhaoliu","age:18","score:90"]

    十.  日期函数

    # 当前时间缀
    $ jq -n 'now'
    1653820640.939947
     
    # 将时间缀转换为0时区的分解时间(broken down time),形式为 年 月 日 时 分 秒 dayOfWeek dayOfYear
    $ jq -n 'now|gmtime' -c
    [2022,4,29,10,45,5.466768980026245,0,148]
     
    # 将时间缀转换为本地时区的分解时间(broken down time)
    $ jq -n 'now|localtime' -c
    [2022,4,29,18,46,5.386353015899658,0,148]
     
    # 分解时间转换为时间串
    $ jq -n 'now|localtime|strftime("%Y-%m-%dT%H:%M:%S")' -c
    "2022-05-29T18:50:33"
     
    # 与上面等效
    $ jq -n 'now|strflocaltime("%Y-%m-%dT%H:%M:%SZ")'
    "2022-05-29T19:00:40Z"
     
    # 时间串解析为分解时间
    $ date +%FT%T|jq -R 'strptime("%Y-%m-%dT%H:%M:%S")' -c
    [2022,4,29,18,51,27,0,148]
     
    # 分解时间转换为时间缀
    $ date +%FT%T|jq -R 'strptime("%Y-%m-%dT%H:%M:%S")|mktime'
    1653850310 

    十一.  高级用法

    $ cat data.json
    {"id":1,"name":"zhangsan","sex": 0, "age":"17","score":"75"}
    {"id":2,"name":"lisi","sex": 1, "age":"16","score":"80"}
    {"id":3,"name":"wangwu","sex": 0, "age":"18","score":"85"}
    {"id":4,"name":"zhaoliu","sex": 0, "age":"18","score":"90"}
     
    # 单变量定义
    $ cat data.json| jq '.id as $id|$id'
    1
    2
    3
    4
     
    # 对象展开式变量定义
    $ cat data.json |jq '. as {id:$id,name:$name}|"id:\($id),name:\($name)"'
    "id:1,name:zhangsan"
    "id:2,name:lisi"
    "id:3,name:wangwu"
    "id:4,name:zhaoliu"
     
    $ cat data.json
    ["1","zhangsan","17","75"]
    ["2","lisi","16","80"]
    ["3","wangwu","18","85"]
    ["4","zhaoliu","18","90"]
     
    # 数组展开式变量定义
    $ cat data.json|jq '. as [$id,$name]|"id:\($id),name:\($name)"'
    "id:1,name:zhangsan"
    "id:2,name:lisi"
    "id:3,name:wangwu"
    "id:4,name:zhaoliu"
     
    # 分支结构
    $ cat data.json|jq '. as [$id,$name]|if ($id>"1") then "id:\($id),name:\($name)" else empty end'
    "id:2,name:lisi"
    "id:3,name:wangwu"
    "id:4,name:zhaoliu"
     
    # 循环结构,第一个表达式条件满足时,执行只每二个表达式
    # 循环结构除了while,还有until、recurse等
    $ echo 1|jq 'while(.<100; .*2)'
    1
    2
    4
    8
    16
    32
    64
     
    # 自定义计算3次方的函数
    $ echo 2|jq 'def cube: .*.*. ; cube'
    8

    CDN 筛选

    #!/bin/bash
    ##版本:V2.1.2
    #新功能,支持ip地址全自动下载,更新优选完毕后推送至TG,再也不怕脚本没有成功运行了。
    #使用脚本需要安装jq和timeout,新增openwrt专用cf_RE.sh文件,运行cf_RE.sh即可在openwrt安装jq和timeout两个扩展。
    #其他linux请自行安装jq和timeout。
    #主程序为ip_down.sh。

    ###################################################################################################
    export LANG=zh_CN.UTF-8
    ###################################################################################################

    ##cloudflare配置
    #cloudflare账号邮箱
    x_email=*********************
    #填写需要DDNS的完整域名
    #支持多域名:域名需要填写在括号中,每个域名之间用“空格”相隔。
    #例如:(cdn.test.com) 或者 (cdn1.test.com cdn2.test.com cdn3.test.com)
    CDNhostname=****************
    #区域ID
    zone_id=********************************
    #Global API Key(获取你的API令牌,你的API密钥就是你的登陆密码)
    api_key=****************************
    $CLIEN=v2raya.service
    ###################################################################################################
    ##CloudflareST配置
    #测速地址
    CFST_URL=https://download.parallels.com/desktop/v15/15.1.5-47309/ParallelsDesktop-15.1.5-47309.dmg
    #测速线程数量;越多测速越快,性能弱的设备 (如路由器) 请勿太高;(默认 200 最多 1000 )
    CFST_N=200
    # 指定测速端口;延迟测速/下载测速时使用的端口;(默认 443 端口)
    CFST_TP=8443
    #下载测速数量;延迟测速并排序后,从最低延迟起下载测速的数量;(默认 10 个)
    CFST_DN=10
    #平均延迟上限;只输出低于指定平均延迟的 IP,可与其他上限/下限搭配;(默认9999 ms 这里推荐配置250 ms)
    CFST_TL=250
    #平均延迟下限;只输出高于指定平均延迟的 IP,可与其他上限/下限搭配、过滤假墙 IP;(默认 0 ms 这里推荐配置40)
    CFST_TLL=40
    #下载速度下限;只输出高于指定下载速度的 IP,凑够指定数量 [-dn] 才会停止测速;(默认 0.00 MB/s 这里推荐5.00MB/s)
    CFST_SL=3
    #更新几个 默认10个
    CFST_P=10
    #####################################################################################################
    # 定义下载链接和保存路径
    download_url=”https://zip.baipiao.eu.org/”
    save_path=”/root/txt.zip”
    extracted_folder=”/root/txt” # 解压后的文件夹路径
    ###################################################################################################

    # 定义最大尝试次数
    max_attempts=10
    current_attempt=1
    ###################################################################################################
    # 关闭开启科学上网
    systemctl stop $CLIEN;
    #sleep 20s
    # 循环尝试下载
    while [ $current_attempt -le $max_attempts ]
    do
    # 下载文件
    wget “${download_url}” -O $save_path

    # 检查是否下载成功
    if [ $? -eq 0 ]; then
    break
    else
    echo “Download attempt $current_attempt failed.”
    current_attempt=$((current_attempt+1))
    fi
    done
    ###################################################################################################

    # 检查是否下载成功
    if [ $current_attempt -gt $max_attempts ]; then
    echo “Failed to download the file after $max_attempts attempts.”
    else
    # 删除原来的txt文件夹内容
    rm -rf $extracted_folder/*

    # 解压文件
    unzip $save_path -d $extracted_folder

    # 删除压缩包
    rm $save_path

    echo “File downloaded and unzipped successfully.”
    ###################################################################################################
    # 合并文件为ip.txt
    # 合并所有含有-1-443.txt的文本文件到一个新文件中
    merged_file=”/root/CloudflareST/merged_ip.txt”
    cat $extracted_folder/*-1-$CFST_TP.txt > $merged_file
    ###################################################################################################
    # 移动到ip.txt到程序总目录

    # 将合并后的文件移动到/root/CloudflareST/ip.txt并覆盖原文件
    mv -f “$merged_file” “/root/cdn/ip.txt”
    echo “Merged text files containing ‘-1-$CFST_TP.txt’ moved and renamed as ‘ip.txt’ in /root/cdn.”
    fi
    ###################################################################################################
    ipv4Regex=”((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])”;
    #默认关闭小云朵
    proxy=”false”;
    #验证cf账号信息是否正确
    res=$(curl -s -X GET “https://api.cloudflare.com/client/v4/zones/${zone_id}” -H “X-Auth-Email:$x_email” -H “X-Auth-Key:$api_key” -H “Content-Type:application/json”);
    resSuccess=$(echo “$res” | jq -r “.success”);
    if [[ $resSuccess != “true” ]]; then
    pushmessage=”登陆错误,检查cloudflare账号信息填写是否正确!”
    # source cf_push;
    exit 1;
    fi
    echo “Cloudflare账号验证成功”;
    #停止科学上网服务

    systemctl stop $CLIEN;
    echo “已停止$CLIEN”;


    #判断是否配置测速地址
    if [[ “$CFST_URL” == http* ]] ; then
    CFST_URL_R=”-url $CFST_URL”;
    else
    CFST_URL_R=””;
    fi

    if [ “$IP_ADDR” = “ipv6” ] ; then
    #开始优选IPv6
    ./CloudflareST $CFST_URL_R -tp $CFST_TP -n $CFST_N -dn $CFST_DN -tl $CFST_TL -tll $CFST_TLL -sl $CFST_SL -p $CFST_P -f ipv6.txt
    else
    #开始优选IPv4
    ./CloudflareST $CFST_URL_R -tp $CFST_TP -n $CFST_N -dn $CFST_DN -tl $CFST_TL -tll $CFST_TLL -sl $CFST_SL -p $CFST_P
    fi
    echo “测速完毕”;
    #systemctl start $CLIEN;
    #echo “已重启$CLIEN”;
    echo “为保证cloudflareAPI连接正常 将在30秒后开始更新域名解析”;
    sleep 3s;
    #开始循环
    echo “正在更新域名,请稍后…”;
    x=0;
    #while [[ ${x} -lt $num ]]; do
    # CDNhostname=${hostname[$x]};
    #获取优选后的ip地址

    # ipAddr=$(sed -n “$((x + 2)),1p” result.csv | awk -F, ‘{print $1}’);
    # echo “开始更新第$((x + 1))个—$ipAddr”;

    while (($x<3))
    do
    ipAddr[$x]=$(sed -n “$((x + 2)),1p” result.csv | awk -F, ‘{print $1}’);
    echo “更新的IP${ipAddr[$x]}”;
    let “x++”;
    done
    #开始DDNS
    #if [[ $ipAddr =~ $ipv4Regex ]]; then
    recordType=”A”;
    # else
    recordType=”AAAA”;
    # fi
    # listDnsApi=”https://api.cloudflare.com/client/v4/zones/${zone_id}/dns_records?type=${recordType}&name=${CDNhostname}”;
    # createDnsApi=”https://api.cloudflare.com/client/v4/zones/${zone_id}/dns_records”;

    # res=$(curl -s -X GET “$listDnsApi” -H “X-Auth-Email:$x_email” -H “X-Auth-Key:$api_key” -H “Content-Type:application/json”);



    # 获取现有记录ID(如果存在)
    res=$(curl -s -X GET “https://api.cloudflare.com/client/v4/zones/${zone_id}//dns_records?type=A&name=$CDNhostname” \
    -H “Authorization: Bearer $api_key” \
    -H “X-Auth-Email:$x_email” \
    -H “X-Auth-Key:$api_key”\
    -H “Content-Type:application/json”)
    #EXISTING_RECORD_ID=$(echo “$res” | jq -r “.result[$id].id”)
    # echo ${EXISTING_RECORD_ID};

    i=0;
    for IP in “${ipAddr[@]}”
    do
    recordId=$(echo “$res” | jq -r “.result[$i].id”);
    recordIp=$(echo “$res” | jq -r “.result[$i].content”);
    echo “$recordId”
    if [[ $recordIp = “$IP” ]]; then
    echo “更新失败,获取最快的IP与云端相同”;
    resSuccess=false;
    elif [[ $recordId = “null” ]]; then
    sleep 3s;
    res_Success =$(curl -s -X POST “https://api.cloudflare.com/client/v4/zones/$zone_id/dns_records” \
    -H “Authorization: Bearer $api_key” \
    -H “X-Auth-Email:$x_email” \
    -H “X-Auth-Key:$api_key”\
    -H “Content-Type: application/json” \
    –data ‘{
    “type”: “A”,
    “name”: “‘$CDNhostname'”,
    “content”: “‘$IP'”,
    “ttl”: 60,
    “proxied”: false
    }’);
    resSuccess=$(echo “res_Success” | jq -r “.success”);
    # echo “Added A record for $CDNhostname with IP: $IP”;
    else
    sleep 3s;
    res_Success=$(curl -s -X PUT “https://api.cloudflare.com/client/v4/zones/$zone_id/dns_records/$recordId” \
    -H “Authorization: Bearer $api_key” \
    -H “X-Auth-Email:$x_email” \
    -H “X-Auth-Key:$api_key”\
    -H “Content-Type: application/json” \
    –data ‘{
    “type”: “A”,
    “name”: “‘$CDNhostname'”,
    “content”: “‘$IP'”,
    “ttl”: 60,
    “proxied”: false
    }’);
    #echo “Updated A record for $CDNhostname with IP: $IP”
    resSuccess=$(echo “$res_Success” | jq -r “.success”);
    # echo “Updated A record for $CDNhostname with IP: $IP”;
    fi

    if [[ $resSuccess = “true” ]]; then
    echo “$CDNhostname更新成功$IP”;
    else
    echo “$CDNhostname更新失败$IP”;
    fi
    let “i++”;

    #会生成一个名为informlog的临时文件作为推送的内容。
    done > informlog
    pushmessage=$(cat informlog);
    systemctl start $CLIEN;
    echo “已停止$CLIEN”;
    #source cf_push;
    exit 0;

    青龙

    
    
    
    

    拉取:docker pull whyour/qinglong

    指定拉取:docker pull whyour/qinglong:******

    运行:docker run -dit -v $PWD/ql:/ql/data -p 5700:5700 –name qinglong –hostname qinglong –restart unless-stopped whyour/qinglong:latest

    NodeJs 下:

    ts-md5
    @types/node
    prettytable
    node-telegram-bot-api
    tslib
    ql
    common
    fs
    typescript
    axios
    png-js
    axios
    ws@7.4.3
    crypto-js
    jieba
    global-agent
    jsdom -g
    moment
    form-data
    date-fns
    node-jsencrypt
    require
    js-base64
    tough-cookie
    json5
    jsdom
    dotenv
    qs

    Python3下:
    ping3
    canvas
    requests
    jieba
    PyExecJS
    httpx

    Linux下:

    lxml
    bizMsg
    bizCode
    gcc
    python-devel
    aiohttp
    magic

    常用命令

    查看容器名:docker ps -a

    重启青龙容器:docker restart 你的容器名

    更新青龙(或者直接面板更新):docker exec -it qinglong ql update

    更新青龙并编译:docker exec -it qinglong ql restart

    Jellyfin安装

    proxychains4 代理

    apt install proxychains4

    在添加Jellyfin源的地方有2个方式,如果用extrepo方式,就不必1到3步骤编号

    • root@server:~# apt update
    • root@server:~# apt install extrepo
    • root@server:~# extrepo enable jellyfin
    • # 1
    • root@server:~# apt update root@server:~# apt install curl gnupg
    • # 2
    • root@server:~# mkdir /etc/apt/keyrings
    • root@server:~# curl -fsSL https://repo.jellyfin.org/$( awk -F’=’ ‘/^ID=/{ print $NF }’ /etc/os-release )/jellyfin_team.gpg.key | gpg –dearmor -o /etc/apt/keyrings/jellyfin.gpg # 3
    • root@server:~# cat <<EOF | tee /etc/apt/sources.list.d/jellyfin.sources
    • Types: deb
    • URIs: https://repo.jellyfin.org/$( awk -F’=’ ‘/^ID=/{ print $NF }’ /etc/os-release ) Suites: $( awk -F’=’ ‘/^VERSION_CODENAME=/{ print $NF }’ /etc/os-release )
    • Components: main
    • Architectures: $( dpkg –print-architecture )
    • Signed-By: /etc/apt/keyrings/jellyfin.gpg
    • EOF

    添加源后,就可以更新,安装Jellyfin

    • # 4 root@server:~# apt update
    • root@server:~# apt install jellyfin
    • # 5 重启Jellyfin
    • root@server:~# systemctl restart jellyfin
    • # 6 关闭Jellyfin
    • root@server:~# systemctl stop jellyfin
    • # 7 启动Jellyfin
    • root@server:~# systemctl start jellyfin
    • # 8 开机启动Jellyfin
    • root@server:~# systemctl enable jellyfin

    配置Nginx的反向代理,需要修改配置DNS指向,配置域名证书,在路由器上配置端口转发到内部的IP端口即可。

    server {
    listen 443 ssl;
    server_name 你的域名;

    client_max_body_size 100M;
    
    
    ssl_certificate /root/certs/域名证书.cer;
    ssl_certificate_key /root/certs/域名证书.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers 'TLS-CHACHA20-POLY1305-SHA256:TLS-AES-256-GCM-SHA384:TLS-AES-128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
    ssl_prefer_server_ciphers on;    
    
    
    
    
    location / {
        proxy_pass http://127.0.0.1:8096;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Protocol $scheme;
        proxy_set_header X-Forwarded-Host $http_host;
    
        # Disable buffering when the nginx proxy gets very resource heavy upon streaming
        proxy_buffering off;
    }
    
    location = /web/ {
        proxy_pass http://127.0.0.1:8096/web/index.html;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Protocol $scheme;
        proxy_set_header X-Forwarded-Host $http_host;
    }
    
    location /socket {
        proxy_pass http://127.0.0.1:8096;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Protocol $scheme;
        proxy_set_header X-Forwarded-Host $http_host;
    }

    }

    防火墙设置

    1、Centos防火墙相关

    • 开启防火墙

    systemctl start firewalld.service

    • 放行指定端口

    firewall-cmd --zone=public --add-port=端口号/tcp --permanentCopy

    • 重启防火墙

    systemctl restart firewalld.service

    • 查看所有端口号

    firewall-cmd --list-ports 或 netstat -ntlp #此命令如果无法运行请先安装:yum install net-tools -y

    • 查看指定端口是否被占用

    lsof -i tcp:6666 #查看所有6666端口使用情况 或 netstat -ntulp |grep 6666 #查看所有6666端口使用情况,此命令也可以查出占用端口的进程

    • 查看&关闭占用进程

    查看进程详细信息:ps 11111 #11111为进程的PID 杀掉进程:kill -9 11111

    • 禁止开机启动

    systemctl disable firewalld.service

    • 开启开机启动

    systemctl enable firewalld.service

    • 查看防火墙状态

    systemctl status firewalld.service

    • 关闭防火墙

    临时停止防火墙:systemctl stop firewalld.service 永久关闭防火墙:systemctl disable firewalld.service

    2、Debian&Ubuntu防火墙相关

    • 安装防火墙(有两种防火墙,可自由选择,当然在后面的命令中需要选择对应的命令方可执行,一般系统会自带方案二,方案一可能需要安装,自己可以先试

    方案一: apt-get update apt-get install iptables-persistent 方案二: apt-get update apt-get install ufw

    • 开启防火墙

    service iptables start #方案一选择此命令 ufw enable #方案二选择此命令

    • 放行指定端口

    iptables -A INPUT -p tcp --dport 端口号 -j ACCEPT 方案二选择以下: 放行tcp或者udp端口:ufw allow 端口号/tcp 放行tcp与udp端口:ufw allow 端口号 删除指定端口:ufw delete allow 端口号

    • 重启防火墙

    service iptables restart #方案一选择此命令 ufw reload #方案二选择此命令

    • 查看防火墙现有规则

    iptables -L -n -v #方案一选择此命令 ufw status #方案二选择此命令 ufw show added #查看刚添加的规则,方案二可用此命令

    • 查看所有端口号

    netstat -ntlp #此命令如果无法运行请先安装:apt-get install net-tools -y

    • 查看指定端口是否被占用

    lsof -i tcp:6666 #查看所有6666端口使用情况 或 netstat -ntulp |grep 6666 #查看所有6666端口使用情况,此命令也可以查出占用端口的进程

    • 查看&关闭占用进程

    kill -9 PID

    • 禁止开机启动

    service iptables stop #方案一选择此命令 ufw disable #方案二选择此命令

    • 开启开机启动

    service iptables save #方案一选择此命令 ufw enable #方案二选择此命令

    • 查看防火墙状态

    service iptables status #方案一选择此命令 ufw status verbose #方案二选择此命令

    • 关闭防火墙

    service iptables stop #方案一选择此命令 ufw disable #方案二选择此命令

    • 重置防火墙配置
    ufw reset

    V2Board 面板搭建机场

    1.防火墙设置

    firewall-cmd –zone=public –add-port=端口号/tcp –permanent

    2.安装宝塔面板国际版

    yum install -y wget && wget -O install.sh http://www.aapanel.com/script/install_6.0_en.sh && bash install.sh aapanel

    • 所需安装的插件
      • Nginx 1.17
      • MySQL 5.6
      • PHP 7.4
      • Supervisor
      • 面板设置:
        • 安装Redis、fileinfo
          • aaPanel 面板 > App Store > 找到PHP 7.4点击Setting > Install extentions > redis,fileinfo 进行安装。
        • 解除被禁止的函数
          • aaPanel 面板 > App Store > 找到PHP 7.4点击Setting > Disabled functions 将 putenv proc_open pcntl_alarm pcntl_signal 从列表中删除。
        • 添加站点
          • aaPanel 面板 > Website > Add site

    3.安装V2Board

    • aaPanel 面板 > Website > 点击网站根目录——把根目录下的四个文件删除
      • 四个文件:.htaccess、404.html、index.html、.user.ini(这一个要多删除一次)
    • 下载v2board项目文件
      • 点击Website——点击网站根目录——点击Remote download——打开【项目下载地址】——找到1.73版——右键复制链接地址——把它粘贴到URL address——点击Confirm——下载完成后——点击解压——然后全选——剪切——粘贴到根目录
      • 进入网站根目录,然后执行命令安装依赖包以及V2board
      • sh init.sh

    4.配置站点目录、伪静态和SSL证书

    • 添加完成后编辑添加的站点 > Site directory > Running directory 选择 /public 保存。
    • 添加完成后编辑添加的站点 > URL rewrite 填入伪静态信息。
    • location /downloads { } location / { try_files $uri $uri/ /index.php$is_args$query_string; } location ~ .*\.(js|css)?$ { expires 1h; error_log off; access_log /dev/null; }
    • 申请安全证书
      • aaPanel 面板 > Website > 点击Conf > 点击SSL

    5.配置定时任务

    • aaPanel 面板 > Cron
      • 在 Type of Task 选择 Shell Script
      • 在 Name of Task 填写 v2board(可自定义)
      • 在 Period 选择 N Minutes 1 Minute
      • 在 Script content 填写 php /www/wwwroot/路径/artisan schedule:run
    • 根据上述信息添加每1分钟执行一次的定时任务。

    6、启动队列服务

    • aaPanel 面板 > App Store > Tools
    • 找到Supervisor进行安装,安装完成后点击设置 > Add Daemon按照如下填写
      • 在 Name 填写 V2board(可自定义)
      • 在 Run User 选择 www
      • 在 Run Dir 选择 站点目录 在 Start Command 填写 php artisan horizon 在 Processes 填写 1
    • 填写后点击Confirm添加即可运行。