0%

原文 https://zhuanlan.zhihu.com/p/441161884

0.前言

rsync 命令的过滤规则功能非常强大,但网上几乎没有详解此主题的资料,让人学习和理解有一定的难度。官网文档 和man rsync手册是英文的,没有什么示例说明,不好理解。即使有人翻译了手册,理解起来也是有一定的难度。

故而有了此教程,结合实际命令对过滤规则的相关概念、逻辑和使用技巧做一个比较透彻的讲解。希望有兴趣学习的朋友,可以快速的入门,节省时间。为什么说是入门呢?因为 rsync 的过滤规则相关内容里,还包含了一些高级技巧,个人感觉实际项目中用到的机会比较少,并未包含在此教程里。

本教程主要分为以下三部分:

  • 1.概述:讲解 rsync 过滤规则的相关概念和内部运行逻辑
  • 2.操作和修饰符:讲解过滤规则中的操作和修饰符
  • 3.匹配模式:讲解过滤规则中的匹配模式
  • 4.使用场景举例:使用具体命令举例讲解过滤规则的使用技巧

1.概述

1.1 什么是 rsync 的过滤规则?

rsync 过滤规则是用于定义哪些文件要传输(包含某些文件)哪些文件不要传输(排除某些文件)的一些规则。这些规则可以直接写在命令参数里,也可以写在规则文件里,然后由命令引用。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 命令1.1-1:规则直接写在命令参数里
# --include="*.php" --exclude="*" 这两个参数配置了两条过滤规则
# 此命令将会只同步src_dir目录下的php文件(不包含子目录的)
rsync -av --include="*.php" --exclude="*" src_dir/ dst_dir/

# 命令1.1-2:通过规则文件配置规则
# rsync.rules 为规则文件,可以使用相对路径或绝对路径
rsync -av -f ". ./rsync.rules" src_dir/ dst_dir/
rsync -av -f ". /www/rsync.rules" src_dir/ dst_dir/
rsync.rules 规则文件的内容如下(具体语法后文说明):

# 只同步php文件
+ *.php
- *

1.2 配置过滤规则的方式有哪些?

与过滤规则有关的选项包括主要有:

1
2
3
4
5
--include=PATTERN :设定一条包含规则,如:--include="*.php"
--exclude=PATTERN :设定一条排除规则,如:--exclude="*"
--include-from=FILE :指定一个文件,文件中一行一条包含规则,以; 或#开头的行为注释,空行被忽略
--exclude-from=FILE :指定一个文件,文件中一行一条排除规则,以; 或#开头的行为注释,空行被忽略
--filter=RULE, -f :设定一条过滤规则,可能是排除或包含规则(如:-f "- *.php" ),也可能其它类型的规则(如包含一个规则文件 -f ". ./rsync.rules")

这些选项配置的规则,其本质是一样,只是描述方式有些差异。其中 –filter=RULE, -f 选项支持完整的规则表达语法,其它的选项都可以转化为此选项的表达。举例如下:

1
2
3
4
5
6
# 以下的都是命令是完全等价的,-f 方式更简单,后文将会更多的选用 -f 的方式表达
# --include="xxx" 等价于 -f "+ xxx"
# --exclude="xxx" 等价于 -f "- xxx"
rsync -av --include="*.php" --exclude="*" src_dir/ dst_dir/
rsync -av -filter "+ *.php" -filter "- *" src_dir/ dst_dir/
rsync -av -f "+ *.php" -f "- *" src_dir/ dst_dir/

由 –include-from 或 –exclude-from 选项引入的规则文件,相当于每个规则前面自动加了 + 或-。其规则文件类内举例如下:

1
2
3
# --include-from 或 --exclude-from 引用的规则文件,开头没有 + 或 -
*.php
*

1.3 过滤规则的工作方式

所有的过滤规则配置最终在 rsync 内部会形成一个有序的规则列表,在命令行中靠前选项,其规则的排序也靠前。随着要传输的(文件/目录路径)列表的构建,针对每个路径,rsync 会依次读取有序规则列表中的规则进行检查。当第一个规则匹配成功后,立即进行操作(包含或排除),并停止后面规则的检查;若所有规则都不不匹配,此路径默认为包含。若有递归选项时(如-r -a),如果子目录被规则排除,那么 rsync 不会递归检查此目录的内容了,也就是此目录下的文件和目录不会进行规则过滤也不会传输,相当于整个子目录都排除了。简单总结如下:

规则有顺序,同命令中参数配置顺序(从左到右)
扫描文件系统,读取(目录或文件的)路径后马上进行规则检查,确定包含还是排除
规则检查按序进行,若有命中立即包含或排除,并停止后续规则检查;若无规则命中,默认为包含
目录被排除时,其下所有子目录和文件都被排除
举例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 此命令会同步src_dir目录下的所有php文件(不包含子目录的)
# 因为src_dir目录下每个文件和目录路径都会先由 -f "+ *.php" 规则检查,php文件符合此规则就被包含了,后面的 -f "- *" 规则不会检查了
# 其余类型的文件和子目录,不符合第一个规则,继续检查第二个规则时,都被排除了
# 子目录被排除后,其中即使有php文件,也不会被检查,所以此命令不会同步src_dir目录下子目录中的php文件
rsync -av -f "+ *.php" -f "- *" src_dir/ dst_dir/

# 调换两个参数的顺序,则完全不一样了
# 此命令将不会同步任何文件和目录
# 因为第一条规则把所有文件和目录到排除了,第二条规则没有机会生效
rsync -av -f "- *" -f "+ *.php" src_dir/ dst_dir/

# 此命令会同步src_dir目录下的所有php文件(包含子目录的)
# 规则 -f "+ */" 会匹配并包含所有子目录路径,所以 rsync 会检查所有的子目录,然后其中的php文件被包含了
rsync -av -f "+ *.php" -f "+ */" -f "- *" src_dir/ dst_dir/

1.4 配置过滤规则的语法

过滤规则的语法如下:

操作 [匹配模式]
操作,修饰符 [匹配模式]
操作:是诸如+(包含)和-(排除)。还有之前引用规则文件(-f “. ./rsync.rules”)的.号,其意义是包含规则文件的操作。还有其它的一些后文详细说明。

修饰符:可用于改变规则的一些行为方式,后文详细说明。

匹配模式:用于匹配字符串的模式,类似正则表达式,可用于检查字符串是否符合某种模式。若符合就说是匹配的,或说命中了。中括号表示匹配模式是可选的,因为某些特殊的操作,没有匹配模式。

操作和匹配模式之间的空格必须是一个英文空格,也可以使用_字符代替,这在命令行中直接写规则时,可以省略引号。例如:

1
2
3
4
5
# 以下两条命令完全等价
# 省略引号的写法应注意其中的*号被意外扩展为路径了
# 建议使用空格加引号的写法,更清晰和安全
rsync -av -f "+ *.php" -f "+ */" -f "- *" src_dir/ dst_dir/
rsync -av -f +_*.php -f +_*/ -f -_* src_dir/ dst_dir/

1.5 测试方法

若需要反复修改命令进行测试,按照实际同步的方式,可能需要不断的删除目标目录的文件,这多少有点不方便。有一个解决办法就是,稍微改变一下 rsync 命令,去掉目标目录不写,则表示不实际同步数据,只列出需要同步的文件/目录列表。例如:

1
2
3
4
5
6
# 原命令
rsync -av -f "+ *.php" -f "+ */" -f "- *" src_dir/ dst_dir/

# 修改后
# 此命令并不会实际同步数据,只会输出要同步的文件/目录列表
rsync -av -f "+ *.php" -f "+ */" -f "- *" src_dir/

2 操作和修饰符

2.1操作

规则类型是由操作决定的,操作不同可以看作是规则类型不同。操作一共有以下9种,每种操作都有对应的标识,分为长标识和短标识,一般配置时都是使用短标识

| 序号 | 长标识 | 短标识 | 操作说明 | 说明 | | —- | ——— | —— | —————————— | ———————- | | 1 | exclude | - | 排除操作 | 排除符合匹配模式的路径 | | 2 | include | + | 包含操作 | 包含符合匹配模式的路径 | | 3 | merge | . | 引入规则文件 | 参考:命令1.1-2 | | 4 | dir-merge | : | 指定每个目录里要合并的规则文件 | 针对传输目录,不常用 | | 5 | hide | H | 指定从传输中隐藏文件的模式 | | | 6 | show | S | 指定某些文件不会被隐藏 | | | 7 | protect | P | 指定某些文件受保护不被删除 | | | 8 | risk | R | 指定某些文件不受保护 | | | 9 | clear | ! | 清除当前包含/排除列表 | 无匹配模式 |

最基本也是最常用的操作就是前3个,比较好理解,之前的示例里已经有说明,这里不再重复。

2.2 修饰符

修饰符只可用于包含/排除操作(+/-),一共有以下7种。当操作使用短标识是,中间的逗号是可以省略的。

1.修饰符/

包含/排除操作后面的匹配模式,本来是针对传输目录的相对路径进行匹配。加了此修饰符后,会把相对路径转换为绝对路径后进行匹配,匹配的方式和规则保持不变。例如:

1
2
3
4
5
6
7
8
9
# 假设 src_dir 的绝对路径未为:/www/src_dir

# 命令2.2-1:此命令将同步src_dir下的所有php文件,但不包括admin.php
# 当扫描到admin.php文件时,其相对路径是 'admin.php'。转化为绝对路径为 '/www/src_dir/admin.php'
# 使用 '-f "-/ src_dir/admin.php"' 规则检查时,匹配(为什么匹配请看后文匹配模式),然后排除。
rsync -av -f "-/ src_dir/admin.php" -f "+ *.php" -f "- *" src_dir/

# 同理此命令效果相同
rsync -av -f "-/ /www/src_dir/admin.php" -f "+ *.php" -f "- *" src_dir/

2.修饰符!

表示否定,对匹配结果进行取反,把匹配成功当做匹配失败,把匹配失败当做匹配成功。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 此命令只同步src_dir下的php文件
# 扫描src_dir目录下的文件和目录时,php文件以外的目录和文件都匹配失败,取反变成匹配成功,排除
# 而php文件最终变成匹配失败,算未命中任何规则,默认保留
rsync -av -f "-! *.php" src_dir/

# 经测试,/和!两个修饰符可以同时使用
# 修改命令2.2-1
# 此命令将只同步admin.php文件
rsync -av -f "-/! src_dir/admin.php" -f "+ *.php" -f "- *" src_dir/

# 但以下命令报错了
rsync -av -f "-!/ src_dir/admin.php" -f "+ *.php" -f "- *" src_dir/

# 但改为单引号后正常了,可能是双引号中的某些字符被意外解析了
# 也就是多个修饰符时,顺序不影响
# 这又是一条经验,如非必要,参数请用单引号
rsync -av -f '-!/ src_dir/admin.php' -f "+ *.php" -f "- *" src_dir/

3.修饰符C

未仔细研究,略过

4.修饰符s

未仔细研究,略过

5.修饰符r

未仔细研究,略过

6.修饰符p

未仔细研究,略过

7.修饰符x

未仔细研究,略过

3 匹配模式
包含和排除规则,都有一个匹配模式,如 过滤规则- .php中的字符串.php就是此规则的匹配模式。用于检查匹配传输路径(要同步的原目录中文件或目录的相对路径,有修饰符/时为绝对路径)。匹配模式就是描述路径特征的一个字符串,如 *.php描述的就是路径末尾的名称()必须是.php结尾。功能和用法类似正则表达式,但比正则表达式简单。

传输路径:是指 src_dir 中文件或目录的相对路径,格式类似如下:

server.php
services.php
session.php
view.php
config/
config/services.php
config/session.php
config/view.php
routes/
routes/api.php
routes/channels.php
routes/console.php
routes/web.php
匹配模式将是和这些路径进行匹配。

关于匹配模式,我一共总结了10条模式规则:

模式以/开头时,表示模式必须匹配路径的开始;否则可以匹配路径中任意一层名称。如:/*.php
模式以/结尾时,表示模式只匹配目录,否则可以匹配目录或文件。如:config/
模式中间的/表示路径分隔符。如:subdir/view.php
匹配任意长度的任意字符,但不匹配/。如:.php
**结尾时匹配任意长度的任意字符(包括/)。如:app/**匹配路径”app/xx/xx/a.txt”
***结尾时匹配任意长度的任意字符(包括/),还包括目录本身。如:app/***匹配路径”app”和”xxx/app”
?匹配/以外的任意一个字符
[]匹配一个某一类字符,如:[a-z]匹配一个小写字母,[0-9]匹配一个数字
模式默认必须匹配到路径的末尾。如:foo匹配”foo”和”xx/foo”,但不匹配”xx/foo1”和”foo/xx”
路径被匹配的部分必须是包含完整的(目录或文件)名称,不可从名称中间切开。如:foo不匹配”xxx/afoo”,abc/foo不匹配”subdir/aabc/foo”
以下举例说明各条规则的使用:

4 使用场景举例

4.1 场景:排除某些目录或文件不同步

此需求比较简单,因为默认包含所有路径,只需设定排除规则,排除对应的目录或文件即可

1
2
3
4
5
6
7
8
9
10
11
12
13
# 排除app和vendor目录不同步
# 注意此命令会排除名称是app或vendor的目录或文件,因为模式规则1
rsync -av -f '- app' -f '- vendor' src_dir/

# 此命令则只排除 src_dir 一级子目录中的 app 和 vendor
rsync -av -f '- /app/' -f '- /vendor' src_dir/

# 排除更深层次的子目录
rsync -av -f '- /app/Admin' -f '- /vendor' src_dir/

# 排除隐藏文件/目录 和 php文件
# 因为模式规则9,10,4,模式`.*`相当于是要求路径最后的名称(文件或目录)必须是`.`开头
rsync -av -f '- .*' -f '- *.php' src_dir/

4.2 场景:只同步指定的子目录

因为传输路径若无规则命中默认是包含(同步),所以若要实现只同步指定目录,需主动写过滤规则排除不需要同步的路径。整体思路就是,先写规则包含要同步的路径,然后排除其余路径。先比较简单的只同步一级子目录开始

只同步一级子目录

以下所有命令均等价,只是实现思路不同。效果都是:只同步config目录(包括所有子目录和文件)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# 命令4.2-1:使用了模式规则1、4
# 因模式规则1,-f '- /*'规则排除了str_dir目录下出config外所有的文件和子目录
# 递归扫描config目录时,因不命中任何规则,所有子目录和文件都被默认包含
rsync -av -f '+ config' -f '- /*' src_dir/

# 命令4.2-2:使用了模式规则4、5、9
# -f '+ config'匹配config目录并包含
# -f '+ config/**' 匹配config目录下所有的子目录和文件的路径,包含。模式规则5
# 其余所有的路径被 -f '- *'匹配,排除。模式规则4、9
rsync -av -f '+ config/**' -f '+ config' -f '- *' src_dir/

#命令4.2-3:
# -f '+ config/***' 匹配config目录以及其所有子目录和文件。规则6
rsync -av -f '+ config/***' -f '- *' src_dir/

#命令4.2-4:
# 使用修饰符!取反,排除了config目录以及其所有子目录和文件路径以外的路径
# 相当于只同步config目录
rsync -av -f '-! config/***' src_dir/
扩展:只同步多个一级子目录

只同步config、app目录(包括所有子目录和文件)

# 注意两条命令的排除规则是不同的,可以参考体会一下模式规则1
rsync -av -f '+ config' -f '+ app' -f '- /*' src_dir/
rsync -av -f '+ config/***' -f '+ app/***' -f '- *' src_dir/
只同步更深层级的子目录

模仿只同步一级子目录的写法,可能会直接把命令写成rsync -av -f '+ app/Admin' -f '- /*' src_dir/。但此命令并不能按预期工作。原因是rsync扫描到app路径时,并不能命中-f '+ app/Admin'规则,然后就后面的规则排除掉了。然后就没然后了,此命令不会同步任何文件。

明白这个问题后,修正它,然后就可写出只同步app/Admin子目录(包含所有子目录和文件)的命令了,以下都是:

# 命令4.2-5:
# 扫描到一级子目录app时,其路径并不会和规则 -f '+ app/Admin/' 匹配,因为模式规则9
# app 路径是有规则 -f '+ app' 命中包含的。此规则若去掉,则此命令不会同步任何文件和目录
# -f '- /*' -f '- /*/*' 两条规则是排除所有未被前面规则包含的一级子目录/文件和二级子目录/文件
# app/Admin/ 下的子目录/文件将不会在命中规则,默认包含
rsync -av -f '+ app/Admin/' -f '+ app' -f '- /*' -f '- /*/*' src_dir/

# 命令4.2-6:效果同命令3-5
# 思路同命令4.2-4
rsync -av -f '+ app' -f '-! app/Admin/***' -f '- /*' src_dir/

#命令4.2-6:效果同命令3-6,思路则不同
# -av -f '+ app'规则包含app
# -av -f '+ app'规则包含app/Admin/目录及所有子目录和文件
# 其余路径由 -f "- *" 排除
rsync -av -f '+ app' -f '+ app/Admin/***' -f "- *" src_dir/

# 命令4.2-7
# -f '-! app/***'规则使用取反,只保留app子目录
# -f '+ app/Admin/' 包含app/Admin/目录,其余二级子目录由规则-f "- /*/*"排除
# app/Admin/目录下所有子目录和文件,无规则命中,保留
rsync -av -f '-! app/***' -f '+ app/Admin/' -f "- /*/*" src_dir/
扩展:只同步多个深层级的子目录

与只同步一个深层级子目录类似,也可以写出很多不同的命令。但问了减少出错,建议使用命令4.2-6的思路,比较简洁。给深层的子目录的所有父级目录都添加好包含规则,然后深层子目录添加***的包含规则,最后是一条排除规则。

rsync -av -f '+ /app' -f '+ /app/Admin/***' -f '+ /vendor' -f '+ /vendor/psy' -f "- *" src_dir/
#### 4.3 场景:快速复制目录结构
有时需要需要创建一个目录,其子目录层次结构与另一个目录结构一样,但不需要其中的文件,这可以用rsync命令快速完成

# 使用了修饰符!取反,排除了目录以外的路径。模式规则1
rsync -av -f '-! */' src_dir/ dst_dir/

5 总结

本文针对 rsync 过滤规则主要讲解了4大块内容:配置方法、内部运行方式、规则语法和使用技巧举例。其内容都是来自官方手册和实操测试,若有谬误,欢迎大家批评指正。也欢迎大家在评论区沟通交流 rsync 的各种经验和技巧。

另外还需强调的是,这个不是 rsync 过滤规则的全部内容,例如操作和修饰符的讲解并不完整,命令中的其它一些与过滤有关的选项(如:–prune-empty-dirs)也未涉及。若有更高级功能的需求,请大家查阅官方手册。

原文 https://k4yt3x.com/%E6%8C%82%E8%BD%BD-dd-%E9%95%9C%E5%83%8F%E4%B8%AD%E7%9A%84%E5%88%86%E5%8C%BA/

旧系统在重装之前备份到了 dd 镜像,而重装完了之后发现有些文件遗忘在了原先的 EFI 分区。我将在这篇 post 中简单讲述我是怎么将 dd 镜像里的分区挂载到系统并且取回文件的。

  1. 将 dd 镜像挂载为 loop 设备
    我的硬盘镜像文件名为 vagrant.dd,所以我可以使用以下命令将该 dd 镜像挂载为 loop 设备。losetup 命令会自动扫描 dd 镜像中的分区并将其挂载到 /dev/loopX。这里的回显显示所有分区都被挂载到了 /dev/loop0 下。
1
2
$ sudo losetup --partscan --find --show vagrant.dd
/dev/loop0

挂载完成后,我们可以用 lsblk 命令查看新的 loop 设备,加上 -f 开关则可以显示设备的文件系统信息。

1
2
3
4
5
6
$ sudo lsblk -fp /dev/loop0
NAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINT
/dev/loop0
├─/dev/loop0p1 vfat FAT32 1396-7EA5
├─/dev/loop0p2 ext2 1.0 c5da8f36-6698-4478-97a8-93101bf44bb8
└─/dev/loop0p3 crypto_LUKS 2 7a3d56b5-20f8-44f2-b1a7-8c858bba342c
  1. 挂载文件系统
    在挂载完环回设备后,接下来的挂载就和挂载普通文件系统无异了。只需要用 mount 命令将 loop 设备挂载到任意挂载点即可读取。
1
2
3
4
5
$ sudo mount -o ro /dev/loop0p1 ~/boot
$ k ~/boot
total 16
drwxr-xr-x 4 root root 4096 12 Aug 2020 EFI
drwxr-xr-x 2 root root 4096 12 Aug 2020 System Volume Information


全流程截图

  1. 解除挂载
    使用完毕之后,按顺序解除两个挂载即可。
1
2
sudo umount ~/boot
sudo losetup -d /dev/loop0

原文

Linux gzip命令介绍
gzip(GNU zip)是一种在Linux系统中常见的命令行压缩工具。它使用DEFLATE压缩算法来减小文件的大小,使文件更易于存储和传输。gzip主要用于压缩文本文件、Tar归档文件和网页。不建议使用gzip来压缩图像、音频、PDF文档和其他已经压缩的二进制文件。

Linux gzip命令适用的Linux版本
gzip命令在大多数Linux发行版中都可以使用,包括Debian、Ubuntu、Alpine、Arch Linux、Kali Linux、RedHat/CentOS、Fedora和Raspbian。如果在某些Linux发行版中无法使用gzip命令,通常可以通过包管理器(如apt、yum或dnf)来安装。

例如,在Debian或Ubuntu上,可以使用以下命令来安装gzip:

[linux@bashcommandnotfound.cn ~]$ sudo apt-get install gzip
1
在RedHat/CentOS 7上,可以使用以下命令来安装gzip:

[linux@bashcommandnotfound.cn ~]$ sudo yum install gzip
1
在RedHat/CentOS 8或Fedora上,可以使用以下命令来安装gzip:

[linux@bashcommandnotfound.cn ~]$ sudo dnf install gzip
1
Linux gzip命令的基本语法
gzip命令的基本语法如下:

gzip [OPTION]… [FILE]…
1
gzip只能压缩单个文件,并为每个给定的文件创建一个压缩文件。

Linux gzip命令的常用选项或参数说明
以下是gzip命令的一些常用选项:

选项 说明
-d 解压缩文件
-f 强制压缩文件,即使已经存在同名的压缩文件
-k 压缩文件并保留原始文件
-r 递归地压缩目录中的所有文件
-v 显示正在处理的文件的名称和压缩比
-1 最快的压缩速度,最小的压缩比
-9 最慢的压缩速度,最大的压缩比
Linux gzip命令实例详解
以下是一些gzip命令的使用实例:

实例1:压缩单个文件
要压缩单个文件,可以调用gzip命令,后面跟着文件名:

[linux@bashcommandnotfound.cn ~]$ gzip filename
1
gzip将创建一个名为filename.gz的文件,并删除原始文件。

实例2:保留原始文件
如果你想保留输入(原始)文件,可以使用-k选项:

[linux@bashcommandnotfound.cn ~]$ gzip -k filename
1
实例3:压缩多个文件
你也可以将多个文件作为参数传递给命令。例如,要压缩名为file1、file2、file3的文件,你可以运行以下命令:

[linux@bashcommandnotfound.cn ~]$ gzip file1 file2 file3
1
以上命令将创建三个压缩文件,file1.gz、file2.gz、file3.gz。

实例4:改变压缩级别
gzip允许你指定从1到9的压缩级别。-1或–fast表示最快的压缩速度和最小的压缩比,-9或–best表示最慢的压缩速度和最大的压缩比。例如,要获得最大的压缩,你可以运行:

[linux@bashcommandnotfound.cn ~]$ gzip -9 filename
1
实例5:解压缩文件
要解压缩一个gzip压缩的文件,你可以使用-d选项:

[linux@bashcommandnotfound.cn ~]$ gzip -d filename.gz
1
这将创建一个名为filename的文件,并删除原始的压缩文件filename.gz。

实例6:递归压缩目录
要递归地压缩一个目录中的所有文件,你可以使用-r选项:

[linux@bashcommandnotfound.cn ~]$ gzip -r directoryname
1
这将压缩directoryname目录中的所有文件,并将每个文件替换为一个.gz压缩文件。

实例7:查看压缩文件的内容
要查看gzip压缩文件的内容,而不解压缩文件,你可以使用zcat命令:

[linux@bashcommandnotfound.cn ~]$ zcat filename.gz
1
这将在终端中显示filename.gz文件的内容。

实例8:压缩文件并显示进度
如果你想在压缩文件时看到进度,你可以使用-v选项:

[linux@bashcommandnotfound.cn ~]$ gzip -v filename
1
这将显示正在处理的文件的名称和压缩比。

实例9:解压缩文件并保留原始文件
如果你想解压缩一个gzip压缩的文件,并保留原始的压缩文件,你可以使用-d和-k选项:

[linux@bashcommandnotfound.cn ~]$ gzip -dk filename.gz
1
这将创建一个名为filename的文件,并保留原始的压缩文件filename.gz。

实例10:解压缩多个文件
你也可以将多个压缩文件作为参数传递给命令。例如,要解压缩名为file1.gz、file2.gz、file3.gz的文件,你可以运行以下命令:

[linux@bashcommandnotfound.cn ~]$ gzip -d file1.gz file2.gz file3.gz
1
以上命令将创建三个解压缩的文件,file1、file2、file3,并删除原始的压缩文件。

实例11:查看压缩文件的内容并保留原始文件
要查看gzip压缩文件的内容,而不解压缩文件,你可以使用zcat命令,并使用-k选项来保留原始的压缩文件:

[linux@bashcommandnotfound.cn ~]$ zcat -k filename.gz
1
这将在终端中显示filename.gz文件的内容,并保留原始的压缩文件。

实例12:解压缩文件并显示进度
如果你想在解压缩文件时看到进度,你可以使用-d和-v选项:

[linux@bashcommandnotfound.cn ~]$ gzip -dv filename.gz
1
这将显示正在处理的文件的名称和解压缩进度。

Linux gzip命令的注意事项
gzip可以压缩的只是常规文件。符号链接会被忽略。
如果你在尝试使用gzip命令时遇到了bash: gzip: command not found的错误,你可以按照上面的指示来安装gzip。
Linux gzip相关命令
gzip命令:用于压缩或解压缩文件
gunzip命令:用于解压gzip压缩的文件
zcat命令:用于查看gzip压缩的文件内容
zip命令:用于压缩文件
unzip命令:用于解压.zip压缩的文件
bzip2命令:用于高效的文件压缩工具
bunzip2命令:用于解压缩bzip2压缩的文件
tar命令:用于归档文件
rar命令:用于压缩解压rar文件
7z命令:用于压缩和解压7z格式的文件

原文:http://www.linuxsir.org/bbs/thread334903.html

  1. 先查看第一个空闲loop设备
    Shell代码
    sudo losetup -f
    /dev/loop0

  2. 使用上一步得到的设备名,第一次创建loop设备
    Shell代码
    sudo losetup /dev/loop0 archlinux-2008.06-core-i686.img

  3. 查看信息
    Shell代码
    sudo fdisk -lu /dev/loop0

Disk /dev/loop0: 322 MB, 322469376 bytes
53 heads, 12 sectors/track, 990 cylinders, total 629823 sectors
Units = sectors of 1 * 512 = 512 bytes
Disk identifier: 0x00000000

  Device Boot      Start         End      Blocks   Id  System  

/dev/loop0p1 * 63 629822 314880 83 Linux
Partition 1 has different physical/logical beginnings (non-Linux?):
phys=(0, 1, 1) logical=(0, 5, 4)
Partition 1 has different physical/logical endings:
phys=(39, 52, 12) logical=(990, 15, 3)

我们可以看到,该镜像只有一个分区(loop0p1),从第63扇区开始(Start列),每扇区512字节(Units = sectors of 1 * 512 = 512 bytes),我们算出offset,下面mout命令会用到:
Shell代码
63*512=32256

  1. mout
    Shell代码
    sudo losetup -o 32256 /dev/loop1 archlinux-2008.06-core-i686.img
    sudo mount -o loop /dev/loop1 /mnt/
    ls /mnt/
    addons archlive.sqfs boot lost+found

事实上,fdisk可以直接查看img文件(虽然功能不全,下面会说到),mount可以自动创建loop设备,所以上面步骤可以简化为:
I. 查看信息
Shell代码
sudo fdisk -lu archlinux-2008.06-core-i686.img
You must set cylinders.
You can do this from the extra functions menu.

Disk archlinux-2008.06-core-i686.img: 0 MB, 0 bytes
53 heads, 12 sectors/track, 0 cylinders, total 0 sectors
Units = sectors of 1 * 512 = 512 bytes
Disk identifier: 0x00000000

                      Device Boot      Start         End      Blocks   Id  System  

archlinux-2008.06-core-i686.img1 * 63 629822 314880 83 Linux
Partition 1 has different physical/logical beginnings (non-Linux?):
phys=(0, 1, 1) logical=(0, 5, 4)
Partition 1 has different physical/logical endings:
phys=(39, 52, 12) logical=(990, 15, 3)

第一行抱怨不能得到cylinders,原因是普通文件上没有实现ioctl操作,我们可以看到0 cylinders,但这对我们不重要,关键是我们依然可以得到第一个分区(archlinux-2008.06-core-i686.img1)的偏移值

II. 直接mount
Shell代码
sudo mount -o loop,offset=32256 archlinux-2008.06-core-i686.img /mnt/
ls /mnt/
addons archlive.sqfs boot lost+found

参考Loop-mounting partitions from a disk image

原文 https://www.jianshu.com/p/ed9dbaabfee4

一、挂载iso格式镜像
1、将镜像文件拷贝到linux系统上。

2、执行命令:mount -t iso9660 -o loop /root/xxx.iso /mnt

1
2
3
4
[root@h07d07184.sqa.eu95 /root]#mount -t iso9660 -o loop alinux-test.iso /mnt

mount: /root/alinux-test.iso is already mounted

3、查看/mnt文件夹,即可查看到镜像的文件。

1
2
3
[root@h07d07184.sqa.eu95 /root]#ls /mnt

apptmp_run.over boot dev home lib64 media opt root run srv tmp varbin data etc lib lost+found mnt proc rr_moved sbin sys usr

4、卸载:umount /mnt

二、挂载qcow2格式镜像

  1. 首先检查当前系统的kernel对NBD模块的支持(NBD:network block device),加载nbd这个module
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
[root@jay-linux kvm_demo]# grep NBD /boot/config-3.5.0

CONFIG_BLK_DEV_NBD=m

[root@jay-linux kvm_demo]# modinfo nbd

filename: /lib/modules/3.5.0/kernel/drivers/block/nbd.ko

license: GPL

description: Network Block Device

srcversion: 56F31584CC2EB73E6F1DA69

depends:

intree: Y

vermagic: 3.5.0 SMP mod_unload modversions

parm: nbds_max:number of network block devices to initialize (default: 16) (int)

parm: max_part:number of partitions per device (default: 0) (int)

parm: debugflags:flags for controlling debug output (int)

[root@jay-linux kvm_demo]# modprobe nbd max_part=16

[root@jay-linux kvm_demo]# lsmod | grep nbd

nbd 7593 0
  1. 将qcow2镜像映射为网络块设备(nbd),命令如下:
1
2
3
4
5
6
7
[root@h07d07184.sqa.eu95 /mnt]#qemu-nbd -c /dev/nbd0 /root/Alinux-2.1.0-OUT-1220.qcow2

[root@h07d07184.sqa.eu95 /mnt]# ll /dev/nbd0*

brw-rw---- 1 root disk 43, 0 Jan 10 10:17 /dev/nbd0

brw-rw---- 1 root disk 43, 1 Jan 10 10:17 /dev/nbd0p1
  1. 像普通block设备那样使用刚才映射好的网络块设备的分区即可,命令行如下:
1
2
3
[root@h07d07184.sqa.eu95 /mnt]#mount /dev/nbd0p1 /mnt/[root@h07d07184.sqa.eu95 /mnt]#ls /mnt/ 

apptmp_run.over boot dev home lib64 media opt root sbin sys usrbin data etc lib lost+found mnt proc run srv tmp var
  1. 使用完这个qcow2镜像后,卸载已挂载的nbd设备,解除qcow2镜像与nbd设备的关联。
1
2
3
4
5
[root@jay-linux kvm_demo]# umount /mnt/

[root@jay-linux kvm_demo]# qemu-nbd -d /dev/nbd0

/dev/nbd0 disconnected

三、挂载vhd格式镜像(与qcow2方法相似)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@h07d07184.sqa.eu95 /root]#ll /dev/nbd0*

brw-rw---- 1 root disk 43, 0 Jan 10 10:31 /dev/nbd0

[root@h07d07184.sqa.eu95 /root]#qemu-nbd -c /dev/nbd0 aliyun-test.vhd[root@h07d07184.sqa.eu95 /root]#ll /dev/nbd0*

brw-rw---- 1 root disk 43, 0 Jan 10 10:32 /dev/nbd0

brw-rw---- 1 root disk 43, 1 Jan 10 10:32 /dev/nbd0p1

[root@h07d07184.sqa.eu95 /root]#mount /dev/nbd0p1 /mnt[root@h07d07184.sqa.eu95 /root]#ls /mnt/

bin boot dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var

[root@h07d07184.sqa.eu95 /root]#umount /mnt/

[root@h07d07184.sqa.eu95 /root]#qemu-nbd -d /dev/nbd0

/dev/nbd0 disconnected

[root@h07d07184.sqa.eu95 /root]#

转载 https://einverne.github.io/post/2013/01/tee-command.html

在执行 Linux 命令时,我们可以把输出重定向到文件中,比如 ls > a.txt,这时我们就不能看到输出了,如果我们既想把输出保存到文件中,又想在屏幕上看到输出内容,就可以使用 tee 命令了。tee 命令读取标准输入,把这些内容同时输出到标准输出和(多个)文件中(read from standard input and write to standard output and files. Copy standard input to each FILE, and also to standard output. If a FILE is -, copy again to standard output.)。

在 tee 中说道:tee 命令可以重定向标准输出到多个文件(tee': Redirect output to multiple files. The tee’ command copies standard input to standard output and also to any files given as arguments. This is useful when you want not only to send some data down a pipe, but also to save a copy.)。要注意的是:在使用管道时,前一个命令的标准错误输出不会被 tee 读取。

实例

格式:

tee file

输出到标准输出的同时,保存到文件 file 中。如果文件不存在,则创建;如果已经存在,则覆盖之。当使用 -a 参数时不会覆盖,而是附加。

格式:

tee -a file

输出到标准输出的同时,追加到文件 file 中。如果文件不存在,则创建;如果已经存在,就在末尾追加内容,而不是覆盖。

格式:

tee -

输出到标准输出两次。(A FILE of -' causes tee’ to send another copy of input to standard output, but this is typically not that useful as the copies are interleaved.)

格式:

tee file1 file2 -

输出到标准输出两次,同时保存到 file1 和 file2 中。

使用 tee 命令重复输出字符串

echo 12345 | tee
12345

echo 12345 | tee -
12345
12345
echo 12345 | tee - -
12345
12345
12345

使用 tee 命令把标准错误输出也保存到文件,默认情况下 tee 是不会将标准错误内容也保存到文件的,这个时候需要使用 2>$1

ls "*" 2>&1 | tee ls.txt

文件中就是

ls: cannot access '*': No such file or directory

转载 https://www.cnblogs.com/grumpyhippo/p/11260161.html#:~:text=dd%E5%91%BD%E4%BB%A4%E6%98%BE%E7%A4%BA%E8%BF%9B%E5%BA%A6%201.%E7%AC%AC%E4%B8%80%E4%B8%AA%E7%AA%97%E5%8F%A3%E6%89%A7%E8%A1%8Cdd%E5%91%BD%E4%BB%A4%202.%E5%8F%A6%E5%BC%80%E4%B8%80%E4%B8%AA%E7%AA%97%E5%8F%A3%EF%BC%8C%E6%89%A7%E8%A1%8Cwatch%20-n%205,pkill%20-USR1%20-x%20dd%203.%E5%9C%A8%E7%AC%AC%E4%B8%80%E4%B8%AA%E6%89%A7%E8%A1%8Cdd%E5%91%BD%E4%BB%A4%E7%9A%84%E7%AA%97%E5%8F%A3%E5%8D%B3%E5%8F%AF%E6%98%BE%E7%A4%BAdd%E6%89%A7%E8%A1%8C%E8%BF%9B%E5%BA%A6%EF%BC%8C%E7%9B%B4%E5%88%B0%E4%BB%BB%E5%8A%A1%E5%AE%8C%E6%88%90

dd命令显示进度
1.第一个窗口执行dd命令
2.另开一个窗口,执行watch -n 5 pkill -USR1 -x dd
3.在第一个执行dd命令的窗口即可显示dd执行进度,直到任务完成

dd 网络磁盘克隆
dd if=/dev/sda |ssh xxx.xxx.xxx.xxx “dd of=/dev/sda bs=4M”

linux手动迁移方法
1.在目标机器挂起live CD,并配置可通IP地址,开启ssh服务器,设置root密码。2.在原机执行dd if=/dev/sda |ssh xxx.xxx.xxx.xxx “dd of=/dev/sda bs=4M”
3.第二步完成后再目标机live CD系统中将boot所在分区挂载起来,执行grub-install –root-directory=/mnt/boot /dev/sda
4.目标机reboot
5.启动时进入grub>
6.ls查看boot所在分区,例如查询可知在(hd0,msdos1)。执行:set root=(hd0,msdos1);set prefix=(hd0,msdos1)/grub2;insmod normal;normal
7.执行完以上即可进入系统
8.进入系统后执行grub2-install /dev/sda
9.reboot目标机完成迁移。

转载 https://www.cnblogs.com/potato-chip/p/12759103.html

sudo dd if=/dev/zero of=/tmp/zero.img status=progress
linux下显示dd命令的进度:
dd if=/dev/zero of=/tmp/zero.img bs=10M count=100000
想要查看上面的dd命令的执行进度,可以使用下面几种方法:
比如:每5秒输出dd的进度
方法一:
watch -n 5 pkill -USR1 ^dd$

方法二:
watch -n 5 killall -USR1 dd

方法三:
while killall -USR1 dd; do sleep 5; done

方法四:
while (ps auxww |grep “ dd “ |grep -v grep |awk ‘{print $2}’ |while read pid; do kill -USR1 $pid; done) ; do sleep 5; done
上述四种方法中使用三个命令:pkill、killall、kill向dd命令发送SIGUSR1信息,dd命令进程接收到信号之后就打印出自己当前的进度。

转载 https://einverne.github.io/post/2023/08/publish-obsidian-post-to-wordpress.html

如何快速分享 Obsidian 中的笔记是从我开始使用 Obsidian 之后一直在思考的问题,在之前,因为我所有的笔记都是通过 Markdown 来存放在本地的,如果我想要分享一个笔记,一般就是将笔记移动到 Blog/_post 目录下,因为我使用一个 Git 仓库来管理我所有的笔记(Vault)然后使用 git submodule 的方式来将我的 Jekyll 博客Hexo 博客 放到我的统一的笔记库里面。所以当我想要发布一篇笔记的时候,就是将笔记移动到对应的博客的目录,然后在使用 git commit 提交,push 来发布,之后的过程都是通过 CI 自动完成的。

虽然这样的方式我已经使用了很多年了,也没有什么大的问题,唯一的问题就是因为发布博客对 Markdown 的标题有一些限制,所以发布之前都得进行重命名。并且我没有办法做到一键发布,大部分的情况下我都必需打开终端,然后进行提交。直到我发现了一款叫做 [[obsidian-wordpress]] 的插件。

这个插件完美的解决了我想要快速分享一篇笔记,然后还不需要我做任何调整,当完成初次的配置之后,基本上只需要点击一下就可以完成发布。

U9pC

这个插件使用 WordPress 的接口(XML-RPC 或 REST)来发布文章。

obsidian wordpress

obsidian-wordpress 是一款 Obsidian 下的插件,可以一键将笔记发布到 WordPress 站点中。该插件使用 XML-RPC 或 REST 接口进行发布。

XML-RPC 是默认启用的,但有些站点可能由于安全问题而禁用它。 虽然有些共享主机可能默认禁用 XML-RPC,但是您无法启用它。 因此,如果禁用 XML-RPC,这个插件将不起作用。

在 WodrPress 4.7 之后,REST API 会在默认情况下启用。 一些 REST API 需要额外的操作来保护可写 API。 历史上 REST 接口是通过安装插件实现的。 在 WordPress 5.6 版本之后,引入了应用程序密码来完成类似的工作。 因此在 WordPress 5.6 之后 ,应用程序密码是首选的。

初次设置

在插件的设置中,找到 Profile,这里可以配置站点的信息,包括地址,API 类型,用户名,密码等。

UA2H

需要注意的是这里的密码,在最新版的 WordPress 中请使用应用程序密码,在用户管理下面生成。

当完成以上的设置之后,在任意的笔记中,都可以在侧边栏中找到 WordPress 的按钮,然后点击,选择分类,一键完成发布。最近我有在写我的 日本生活 ,其中所有的内容都是我在 Obsidian 中完成编写,然后发布的。我创建了一个单独的文件夹用来存放所有发布到该网站的内容,并且这些内容也可以很好的和我的其他笔记进行融合,并且在我修改了文章的内容之后,也可以快速进行一键发布。

在以前我使用 WordPress 的时候,非常不方面的一点就是对其中文章内容的修改非常不方便,我不喜欢在线的编辑器,而如今 Obsidian 就成为了我的 WordPress 的本地编辑器。

图片怎么办

文章中的图片我是我之前搭建的 [[Chevereto]] 图床,配合 macOS 下的 uPic,我设置了快捷键 Ctrl + Shift + U,就可以一键上传粘贴板中的内容。然后直接在 Obsidian 中使用即可。

转载 https://einverne.github.io/post/2023/09/subdomain-scanner.html

前段时间看到一篇文章说因为 Nginx 的一个「特性」,在直接访问 IP ,并且没有配置默认证书的情况下 Nginx 就会返回一个 SSL 证书从而倒置域名的泄露,进而泄露了网站的源 IP,使得一些扫描网站,比如 [[censys]] 可以直接查询到域名背后的网站 IP,从而导致网站即使用了 CDN 也会遭受到攻击。在这个契机下,我又开始了衍生,因为在 censys,[[fofa]],[[Shodan]] 等等网站上你只需要输入一个域名就可以获得所有这个站点相关的信息,那么有没有办法可以在只知道一个网站域名的情况下知道所有的二级域名呢。

于是抱着这个新想法,进行了一番调查,果然还是有办法可以知道的。我最最朴素的想法就是写一个遍历,直接通过随机的字符串,[a-z0-9\-] 等等字符的组合,然后进行这些域名检查,ping,dig 的结果,如果有返回,可以认为这个子域名被启用了。但是很显然这个想法的效率太低了,并且遍历这么多无效的域名前缀很显然没有办法最快的找到所有的。

然后我就找到了 [[MassDNS]],一款使用 C 语言编写的高性能子域名扫描工具。它通过使用自定义的 DNS 解析器和并发查询来加快子域名的发现速度。MassDNS 支持使用字典文件进行子域名爆破,并提供了丰富的配置选项来优化扫描过程。 MassDNS 还支持自定义的 DNS 服务器,并可以通过设置最大查询时间和最大重试次数等参数来控制扫描过程中的超时和重试行为。此外,它还提供了多种输出格式,包括文本、JSON 和 CSV,以便用户根据需要对扫描结果进行分析和处理。 使用 MassDNS 进行子域名扫描非常简单,只需指定目标域名和字典文件即可开始扫描。它还提供了多线程支持,可以根据系统资源情况调整并发线程数量,以实现更快的扫描速度。

然后我又循着脉络找到了 OneForAll 这样一个开源的工具,它是一个功能强大的子域名收集工具,集成了非常多的工具,从它的官方介绍上也可以看出来它收集子域名的思路和方法。

  • 利用成熟第三方的情报收集
    • 利用证书收集子域名情报,比如通过 censys_apicertspottercrtsh 等等
    • 常规检查收集子域
      • 域传送漏洞利用axfr
      • 检查跨域策略文件cdx
      • 检查 HTTPS 证书cert
      • 检查内容安全策略csp
      • 检查 robots 文件robots
      • 检查 sitemap 文件sitemap
      • 利用 NSEC 记录遍历 DNS 域dnssec
      • NSEC3 记录
    • 网络爬虫存档记录,archivecrawlcommoncrawl
    • 通过第三方 DNS 数据集收集子域
    • 直接通过 DNS 查询收集,SRV记录,MX,NS,SOA,TXT记录
    • 利用威胁情报平台数据收集子域
    • 搜索引擎发现子域
  • 通过字典,或者遍历来查询子域名
  • 通过 [[MassDNS]] 来多线程查询子域名

OneForAll 使用

首先获取 OneForAll 的代码

1
git clone git@github.com:shmilylty/OneForAll.git

通过 pyenv 或者其他熟悉的工具,安装 Python 依赖,然后执行

1
python3 oneforall.py --target douban.com run

很快就能获得一个 CSV 的结果。

Other

  • [[Findomain]]