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添加即可运行。

Aria2

1.软件库里面安装Aria2

apt-get install aria2

2.配置文件

mkdir /etc/aria2

touch /etc/aria2/aria2.session

chmod 777 /etc/aria2/aria2.session

nano /etc/aria2/aria2.conf

3.把下面的aria2配置文件模板写入“aria2.conf”,需要修改的有下载目录“dir”以及连接秘钥“rpc-secret”,其他内容可以不动,模板里面都有详细文字说明:

##===================================## ## 文件保存相关 ## ##===================================## # 文件保存目录 dir=/home/ubuntu/Downloads # 启用磁盘缓存, 0为禁用缓存, 需1.16以上版本, 默认:16M disk-cache=16M # 断点续传 continue=true #日志保存 log=aria2.log # 文件预分配方式, 能有效降低磁盘碎片, 默认:prealloc # 预分配所需时间: none < falloc ? trunc < prealloc # falloc和trunc则需要文件系统和内核支持 # NTFS建议使用falloc, EXT3/4建议trunc, MAC 下需要注释此项 file-allocation=prealloc ##===================================## ## 下载连接相关 ## ##===================================## # 最大同时下载任务数, 运行时可修改, 默认:5 max-concurrent-downloads=100 # 同一服务器连接数, 添加时可指定, 默认:1 # 官方的aria2最高设置为16, 如果需要设置任意数值请重新编译aria2 max-connection-per-server=16 # 整体下载速度限制, 运行时可修改, 默认:0(不限制) max-overall-download-limit=0 # 单个任务下载速度限制, 默认:0(不限制) max-download-limit=0 # 整体上传速度限制, 运行时可修改, 默认:0(不限制) max-overall-upload-limit=0 # 单个任务上传速度限制, 默认:0(不限制) max-upload-limit=0 # 禁用IPv6, 默认:false disable-ipv6=false # 最小文件分片大小, 添加时可指定, 取值范围1M -1024M, 默认:20M # 假定size=10M, 文件为20MiB 则使用两个来源下载; 文件为15MiB 则使用一个来源下载 min-split-size=10M # 单个任务最大线程数, 添加时可指定, 默认:5 # 建议同max-connection-per-server设置为相同值 split=16 ##===================================## ## 进度保存相关 ## ##===================================## # 从会话文件中读取下载任务 input-file=/etc/aria2/aria2.session # 在Aria2退出时保存错误的、未完成的下载任务到会话文件 save-session=/etc/aria2/aria2.session # 定时保存会话, 0为退出时才保存, 需1.16.1以上版本, 默认:0 save-session-interval=60 ##===================================## ## RPC相关设置 ## ##此部分必须启用,否则无法使用WebUI ##===================================## # 启用RPC, 默认:false enable-rpc=true # 允许所有来源, 默认:false rpc-allow-origin-all=true # 允许外部访问, 默认:false rpc-listen-all=true # RPC端口, 仅当默认端口被占用时修改 rpc-listen-port=6800 # 设置的RPC授权令牌, v1.18.4新增功能, 取代 –rpc-user 和 –rpc-passwd 选项 rpc-secret=666666 # 设置的RPC访问用户名, 此选项新版已废弃, 建议改用 –rpc-secret 选项 #rpc-user= # 设置的RPC访问密码, 此选项新版已废弃, 建议改用 –rpc-secret 选项 #rpc-passwd= # 启动SSL # rpc-secure=true # 证书文件, 如果启用SSL则需要配置证书文件, 例如用https连接aria2 # rpc-certificate= # rpc-private-key= ##===================================## ## BT/PT下载相关 ## ##===================================## # 当下载的是一个种子(以.torrent结尾)时, 自动开始BT任务, 默认:true follow-torrent=true # BT监听端口, 当端口被屏蔽时使用, 默认:6881-6999 listen-port=51413 # 单个种子最大连接数, 默认:55 #bt-max-peers=55 # 打开DHT功能, PT需要禁用, 默认:true enable-dht=true # 打开IPv6 DHT功能, PT需要禁用 enable-dht6=true # DHT网络监听端口, 默认:6881-6999 dht-listen-port=6881-6999 # 本地节点查找, PT需要禁用, 默认:false bt-enable-lpd=true # 种子交换, PT需要禁用, 默认:true enable-peer-exchange=true # 每个种子限速, 对少种的PT很有用, 默认:50K bt-request-peer-speed-limit=50K # 客户端伪装, PT需要 peer-id-prefix=-TR2770- user-agent=Transmission/2.77 # 当种子的分享率达到这个数时, 自动停止做种, 0为一直做种, 默认:1.0 seed-ratio=0 # 强制保存会话, 即使任务已经完成, 默认:false # 较新的版本开启后会在任务完成后依然保留.aria2文件 force-save=true # BT校验相关, 默认:true #bt-hash-check-seed=true # 继续之前的BT任务时, 无需再次校验, 默认:false bt-seed-unverified=true # 保存磁力链接元数据为种子文件(.torrent文件), 默认:false bt-save-metadata=true # 单个种子最大连接数, 默认:55 0表示不限制 bt-max-peers=0 # 最小做种时间, 单位:分 # seed-time = 60 # 分离做种任务 bt-detach-seed-only=true #BT Tracker List ;下载地址:https://github.com/ngosang/trackerslist bt-tracker=udp://tracker.coppersurfer.tk:6969/announce,udp://tracker.internetwarriors.net:1337/announce,udp://tracker.opentrackr.org:1337/announce

4.进行测试:

前台运行 aria2c –conf-path=/etc/aria2/aria2.conf

后台运行 aria2c –conf-path=/etc/aria2/aria2.conf -D

5.aria2c 开机启动

在 /lib/systemd/system/ aria2.service

编写如下脚本    

[Unit]     Description= aria2    

After=

aria2.service          

[Service]    

#PIDFile=/run/aria2.pid    

ExecStart=/usr/bin/ aria2c -c –conf-path=/etc/aria2/aria2c.conf              

[Install]     WantedBy=multi-user.target

然后  systemctl daemon-reload ;systemctl enable aria2.service  ;  systemctl start aria2.service 即可开机启动 2) aria2.service aria2.service aria2c -c –conf-path=/etc/aria2/aria2c.conf

Linux硬盘分区基本概念

Linux中硬盘需要挂载之后才可以使用,挂载步骤:添加硬盘-分区-格式化文件系统-挂载

Linux 磁盘挂载2(文件系统格式化、磁盘挂载)-CSDN博客
硬盘设备的文件名 /dev/sd[a-z]

/dev

根据FHS了解这是一个设备文件

sd

根据udev 这是一个硬盘文件

a-z

指的是识别号码(内核识别硬盘),并不是指插槽的位置,与插槽没有直接关系

此字母是由内核的识别顺序来决定的(而大部分主板的插槽顺序就是系统内核的识别顺序)

 即:如果识别码为b,并不代表此硬盘在第二个插槽,也有可能是在第一个插槽

     只是代表此硬盘是内核识别的第二个硬盘(硬件设备)

分区的编码

如果硬盘分区后,就会存在分区编号

这个编号并不代表分区的个数,以编号5举例子

5并不代表这是设备上的第5个分区,5只能表示编号为5的分区(对于MBR分区来说,编号5一定是逻辑分区)

注意:分区的编号可以手工指定,所以编号5也不能表示此硬盘最少有5个分区

Linux磁盘分区类型

磁盘分区主要分为MBR分区和GPT分区两种类型

MBR分区特点

主引导记录,将硬盘分区划分为主分区、扩展分区、逻辑分区

最大支持4个主分区(逻辑分区不限数量),最大只支持对2T硬盘进行分区

分区信息存储在主引导扇区

GPT分区特点

GPT的分区信息存放在单独的分区中

GPT的每一个分区都是独立存在的,都是主分区;没有扩展分区、逻辑分区的概念

分区在理论上没有限制,但是实际上一般最大配置128个主分区

最大支持对18EB的硬盘进行分区

GPT的分区表以及GPT头都有备份,可靠性更高

MBR分区介绍

硬盘设备是由大量的扇区(一般一个扇区为512字节)组成的,其中第一个扇区最重要,保存着主引导记录和主分区表信息

其中主引导记录(MRB)占用446字节,主分区表占用64字节(有4个分区,每主个分区16字节),结束符占用2字节

其余扇区存放着用户的实际数据

扩展分区的作用

此时我们看到主分区只有4个,这个分区的数量显然是不够的,所以我们设计了扩展分区的概念,扩展分区的作用就是扩展更多的分区

扩展分区与主分区一样都是存在于主分区表中,它会占用一个主分区号(即如果使用扩展分区的话,主分区表中变为3个主分区,1个扩展分区;如果不创建扩展分区的话,主分区表就可以创建4个主分区)

逻辑分区的作用

扩展分区必须分成若干个逻辑分区来使用(扩展分区不存放信息,逻辑分区才存放信息)

扩展分区并不是一个真正的分区,因此扩展分区不能够直接使用,它更像是一个指针,能够指到另一个全新的扇区上面的分区(逻辑分区),通过全新的逻辑分区来存储更多的数据

硬盘分区可以分为三类

主分区(可以马上使用但是不能再分区)

扩展分区(必须再次进行分区后才可以使用(需要再次分为逻辑分区))

逻辑分区(由扩展分区再次分区而建立起来的分区)

注意事项

主分区+扩展分区的数量加起来最多4个(其中主分区最少1个,最多4个;扩展分区最少0个,最多1个);一般为3个主分区+1个扩展分区

逻辑分区的数量没有限制,不过所有逻辑分区加起来的总容量无法超过扩展分区

分区编号

1-4为主分区/扩展分区(主和扩展分区共同占用1-4,即编号1可以为主,也可以为扩展)

5以后的分区为逻辑分区

识别硬盘的文件名

/dev/sda4

 表示此硬盘是设备第一个识别的硬盘,并且是编号为4的分区(此分区可能是主分区,也可能是扩展分区)

/dev/sdb6

 表示此硬盘是设备第二个识别的硬盘,并且是编号为6的分区(此分区一定是逻辑分区)

GPT分区介绍

GPT(GUID Partition Table)全局唯一标识分区符,是一种比MBR分区更灵活、先进的磁盘分区模式

GPT分区结构

主GPT记录分区表与分区表项的简要信息

分区表可以细分为分区表项(主分区),记录分区表项的详细信息

分区区域实际主分区存储的数据

Protective MBR 保护MBR

第一个扇区,0号扇区;存储的也是MBR主引导信息(与MBR分区不同的是不存储分区信息)

前446字节存储的是MBR主引导记录,中间64字节用来表示此磁盘为GPT格式,防止磁盘错误识别,最后2字节为结束符

这个表项GPT基本不用,主要是为了让系统认为这个磁盘是合法的

主部分

Promary GPT Header 主GPT分区表标头

第二个扇区,1号扇区;在创建GPT磁盘时生成

记录了每个分区表的位置(起使位置与结束位置)以及其校验和,每个分区表项的大小、总个数等信息

系统可以根据该校验码来判断GPT是否正确,如果GPT错误可以通过备用记录区来取得备份的GPT来恢复GPT的正常运行

长度(字节)


含义

8


签名  固定为ASCII码

4


版本号

4


GPT头的字节总数

4


GPT头的CRC校验和

4


保留

8


GPT头所在的扇区号

8


GPT头备份所在的扇区号

8


GPT分区区域的起始发扇区号

8


GPT分区区域的结束扇区号

16


磁盘GUID

8


GPT分区表起始扇区号

4


分区表项数

4


每个分区表项的字节数

4


分区表的CRC校验和

420


保留

分区表

GPT磁盘上的第3个扇区到第34个扇区(共32个分区表),也就是2到33号扇区

分区表存放的就是分区表项信息(也就是主分区信息)

理论上可以在该分区表下创建无限个主分区,但是实际上最大创建128个分区后,之后创建的分区无法格式化

所以一般来说,每个分区表会存储4个分区表项(每个表项128字节),一共可以划分32*4=128个分区表项(即128个主分区)

每个分区表项记录的内容为分区的起始、结束地址,分区类型的GUID,分区的名字,分区的属性和分区的GUID

长度(字节)


含义

16


分区类型GUID(标识每个分区)

16


分区GUID

8


分区起始地址

8


分区结束地址

8


分区属性

72


分区名

分区区域

实际进行用户数据存储的区域

分区区域的起使地址和结束地址由GPT头定义

备用部分

分区表备份

对分区表32个扇区的完整备份,如果主的分区表被破环,系统会自动读取分区表备份,保证正常识别分区

分区表备份的地址在GPT头的备份扇区中有描述

Seconday GPT Header 备GPT分区表标头

在GPT磁盘的最后一个扇区,对主GPT分区表标头进行备份

不过该备份并非完整的GPT头备份,可能某些参数不一致,恢复的时候根据实际情况更改即可

GPT分区编号

GPT分区只有主分区,最大128个主分区

磁盘查看命令
df 显示磁盘空间使用情况

df 【参数】 【文件或目录】————列出文件系统的整个磁盘空间使用情况,并查看磁盘已用空间和剩余空间

   -a  显示所有系统文件(包括隐藏文件)

   -h 以容易阅读的方式显示

   -t  只显示指定类型的文件系统

   -T  输出时显示文件系统类型

 文件系统名/路径               总量         使用      可用  使用比例  挂载点

lsblk 查看系统的磁盘使用情况

新加入的硬盘是没有分区和挂载点的

lsblk -a  查看所有磁盘设备的使用情况

lsblk -f   显示磁盘设备的文件系统信息

lsblk -m  查案磁盘设备的归属以及权限信息

lsblk -s   查看系统所有SCSI类型的磁盘信息

磁盘分区命令
fdisk 命令

默认通过MBR分区方式进行磁盘分区,也可以进行GPT分区

更改磁盘分区类型可以通过parted命令来更改

可以将磁盘设备划分为多个分区(主、扩展、逻辑)

命令格式

fdisk 【参数】 磁盘文件   为此磁盘创建分区(fdisk是交互式的配置方式来配置分区的)

 fdisk -l  查看当前系统分区情况

磁盘交互指令

   d  删除分区

   l   列举分区的标识符

   n  新建分区

   p  查看此硬盘的分区表

   t   修改分区的标识符

   w  保存并退出

   q   退出

分区类型(p表示主分区、e表示扩展分区,l表示逻辑分区-前提是扩展分区已经创建)

输入结束的扇区时,可以简写 +300M 表示此扇区300M

注意事项

当分区表显示不全时,进行一下操作

使用partprobe更新分区表

如果更新分区表后还是显示不全,此时需要重启系统

如果以上操作都不行,可能是用户的配置错误

通过/dev/sdb为磁盘创建1个5G的主分区,然后创建1个10G的扩展分区,1个5G的逻辑分区

创建5G的主分区

创建10G的扩展分区

创建5G的逻辑分区(逻辑分区的容量是在扩展分区容量中分出来的)

查看分区创建结果并保存退出

查看内核是否识别新分区

cat /proc/partitions

如果内核没有识别新分区,则需要通知内核重新读取硬盘分区表

partx -a /dev/sdb

之后进行文件格式化和挂载

gdisk 命令

只可以通过GPT分区方式进行磁盘分区,也是通过交互式的配置方式来进行磁盘划分

对于硬盘的交互指定与fdisk类似

交互指令

   d  删除分区

   c  更改分区名称

   b  将GPT数据备份到一个文件

   l   列举分区的标识(列出已知的分区类型)

   i   显示分区的详细信息

   n  新建分区

   u  改变显示记录单位

   p  查看此硬盘的分区表项

   t   修改分区的标识符

   o  创建一个新的空白的GPT分区表

   w  保存并退出

   q   退出

  ? 显示帮助信息

安装gdisk

yum -y install fdisk

创建磁盘分区

创建2G的主分区1

创建1G的主分区2

查看分区结果并保存退出

查看内核是否识别新分区

cat /proc/partitions

如果内核没有识别新分区,则需要通知内核重新读取硬盘分区表

partx -a /dev/sdb

之后进行文件格式化和挂载

parted 命令

parted为高级分区工具,主要体现在以下方面

支持创建多种分区类型:既可以做GPT分区,也可以做MBR分区;不过主要是用来做GPT的分区类型

允许用户调整分区大小、移动和复制分区

支持命令行配置方式和交互指令方式来配置分区

parted两种配置方式

命令行模式—一般不使用此模式,本次不做重点介绍

parted 【参数】 【设备-磁盘】 【指令】

参数


描述

h


显示求助信息

l


列出系统中所有的磁盘设备

m


进入交互模式(如果不加设备则对第一个磁盘操作)

s


脚本模式

v


显示版本

指令


描述

mkpart  分区类型   起始点  终止点 


创建一个分区

mkpartfs 分区类型 文件系统类型 起始点  终止点 


创建一个带有文件系统的分区

print 【devices|free|list|all|number】


显示分区表、活动设备、空闲设备、所有分区等

交互指令

parted -m 设备 或者 parted 设备————进入到交互界面

常用交互指令


描述

help 【指令】


显示所有的命令帮助

mklabel/mklable  分区类型


创建新的分区表-表示后续通过哪种分区类型进行分区(msdos为mbr分区,gpt为gpt分区)

mkpart


在分区表下创建分区表项(主分区)

print 【devices|free|list|all|number】


显示分区表、活动设备、空闲设备、所有分区等

set NUMBER


改变分区标记

rm NUMBER


删除分区

name


给分区命名

version


显示版本

unit


设置默认单位(两次Tab键可以查看有哪些单位)

quit


退出

注意事项

当通过mklabel更改分区类型后,当使用fdisk对新的硬盘分区是,也采用该分区类型

即:mklabel的更改对fdisk也生效,对gdisk不生效

创建gpt分区1,5G大小

更改分区类型

进行磁盘分区的创建(此处指定了文件系统,在进行格式化时也需要格式化为该文件系统)

之后可以直接q退出

parted相比于fdisk和gdisk,parted在配置后会自动保存,配置完成后直接退出就可以

查看内核是否识别新分区

cat /proc/partitions

如果内核没有识别新分区,则需要通知内核重新读取硬盘分区表

partx -a /dev/sdc

之后进行文件格式化和挂载

————————————————
版权声明:本文为CSDN博主「静下心来敲木鱼」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_49864110/article/details/129097305

挂载硬盘

df 命令用于显示磁盘空间使用情况。du 命令用于计算目录或文件的磁盘使用情况。lsblk 命令用于列出块设备(如硬盘、分区等)的信息。fdisk 命令用于显示磁盘分区表信息。

步骤1:添加2块20G的SCSI硬盘(过程省略);

步骤2:使用lsblk命令查看硬盘信息、ls /dev/sd*查看硬盘目录信息;

root@aml-s812:~# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 223.6G 0 disk
└─sda1 8:1 0 223.6G 0 part
mmcblk0 179:0 0 7.3G 0 disk
├─mmcblk0p1 179:1 0 488M 0 part /boot
└─mmcblk0p2 179:2 0 6.6G 0 part /
mmcblk0boot0 179:32 0 4M 1 disk
mmcblk0boot1 179:64 0 4M 1 disk

步骤3:使用fdisk /dev/sda 对第2块磁盘分区;

欢迎使用 fdisk (util-linux 2.23.2)。
 
更改将停留在内存中,直到您决定将更改写入磁盘。
使用写入命令前请三思。
 
Device does not contain a recognized partition table
使用磁盘标识符 0xe5ceabad 创建新的 DOS 磁盘标签。
 
命令(输入 m 获取帮助):m #输入m
命令操作
   a   toggle a bootable flag 
   b   edit bsd disklabel
   c   toggle the dos compatibility flag
   d   delete a partition
   g   create a new empty GPT partition table
   G   create an IRIX (SGI) partition table
   l   list known partition types
   m   print this menu
   n   add a new partition
   o   create a new empty DOS partition table
   p   print the partition table
   q   quit without saving changes
   s   create a new empty Sun disklabel
   t   change a partition's system id
   u   change display/entry units
   v   verify the partition table
   w   write table to disk and exit
 
 
命令(输入 m 获取帮助):p  #出入p打印硬盘已有分区表信息
 
磁盘 /dev/sdb:21.5 GB, 21474836480 字节,41943040 个扇区
Units = 扇区 of 1 * 512 = 512 bytes
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0xe5ceabad
 
   设备 Boot      Start         End      Blocks   Id  System
 
 
命令(输入 m 获取帮助):n # 新建分区
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): p #创建主分区
分区号 (1-4,默认 1):1
起始 扇区 (2048-41943039,默认为 2048):#此处默认即可,直接回车
将使用默认值 2048
Last 扇区, +扇区 or +size{K,M,G} (2048-41943039,默认为 41943039):+2G #创建2G分区
分区 1 已设置为 Linux 类型,大小设为 2 GiB
 
命令(输入 m 获取帮助):p #查看分区信息
 
磁盘 /dev/sdb:21.5 GB, 21474836480 字节,41943040 个扇区
Units = 扇区 of 1 * 512 = 512 bytes
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0xe5ceabad
 
   设备 Boot      Start         End      Blocks   Id  System
/dev/sdb1            2048     4196351     2097152   83  Linux
 
命令(输入 m 获取帮助):w #保存并退出
The partition table has been altered!
Calling ioctl() to re-read partition table.
正在同步磁盘。

步骤4:使用file /dev/sdb1查看文件类型;

步骤5:使用mkfs对分区进行格式化;在shell终端中输入mkfs后 敲击两次“Tab”键,可获得mkfs前缀文件,任意选择其中的一个文件进行格式化,此处选择.ext4的文件进行格式化,命令: mkfs.ext4 /dev/sdb1

步骤6:挂载 mount /dev/sda1 /backup

永久挂载 vim /etc/fstab :: /dev/sda1 /backup ext4 defaults 0 0

如果想每次系统重启都能自动挂载该分区可修改vim /etc/fstab文件,在最后加入:/dev/sdb1 /mnt ext3 defaults 1 2 (格式说明:/dev/sdb1 代表哪个分区, /mnt是挂载目录, ext3是该分区的格式,defaults 是挂载时所要设定的参数(只读,读写,启用quota等),输入defaults包括的参数有(rw、dev、exec、auto、nouser、async) ,1是使用dump是否要记录,0是不要。 2是开机时检查的顺序,是boot系统文件就为1,其他文件系统都为2,

备注 lvresize -r -L +7G /dev/mapper/ubuntu–vg-ubuntu–lv /dev/sda3

Linux生成指定大小文件的方法

dd命令是Linux系统自带的一个工具,可以用来复制文件、转换文件格式、计算文件哈希值等功能。我们可以使用dd命令来生成指定大小的文件。# 生成1GB大小的文件

dd if=/dev/zero of=testfile bs=1G count=1

上面的命令中,if参数指定生成文件的内容为/dev/zero,即全0文件;of参数指定生成的文件名为testfile;bs参数指定每次读写的块大小,count参数指定读写多少块。

创建 dd if=/dev/zero bs=4M count=2500 of=/media/disk-hot/testfile

格式化 mkfs.xfs /media/disk-hot/testfile

创建挂载路径 mkdir /media/disk-wxy

挂载 mount /media/disk-hot/testfile /media/disk-wxy