kk Blog —— 通用基础


date [-d @int|str] [+%s|"+%F %T"]
netstat -ltunp
sar -n DEV 1

linux rsync 备份静态文件脚本

mysqlbak.sh

1
2
3
php rsync.php u8 2023-01-01

php rsync.php aps 2023-01-01

rsync.php

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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
<?php

function sDir(&$fpa, &$dones, $logs, $ptime, $dir, $pre = 0)
{
	if (!is_dir($dir))
		return;

	// 类型 大小 时间 是否gzip 文件名或目录名
	$path = $dir;
	if (!isset($dones[$path])) {

		$tp = is_link($path) ? 'dir_link' : 'dir';
		$s = filesize($path);
		$t = filectime($path);
		$gz = 'no';

		echo "同步 {$tp}: {$path}\n";
		exec("echo 同步 {$tp}: {$path} >> {$logs}");

		exec("rsync -avd --max-size 0 {$path}/. root@192.168.1.2:/home/bak/rsync_178/{$path} >> {$logs} 2>&1");
		fputcsv($fpa, array(date('Y-m-d_H:i:s'), $tp, $s, $t, $gz, $path), "\t");
		$dones[$path] = array('', $tp, $s, $t, $gz, $path);
	}
	if (is_link($path))
		return;

	$handle = opendir($dir);
	while ($file = readdir($handle)) {
		if ($file == '.' || $file == '..')
			continue;

		$path = $dir . '/' . $file;

		$tp = '';
		$s = filesize($path);
		$t = filemtime($path);
		$gz = 'no';

		if (is_dir($path)) {

			sDir($fpa, $dones, $logs, $ptime, $path, $pre + 8);

		} elseif (isset($dones[$path])) {

			if ($s >= 100 and $t < $ptime and $dones[$path][1] == 'file') {
				$suf = substr($path, -3);
				$retval1 = $retval2 = '';
				if ($suf != '.gz') {

					$spath = str_replace(' ', '\\ ', str_replace(')', '\\)', str_replace('(', '\\(', $path)));

					exec("gzip {$spath}", $output, $retval1);
					$tp = 'gz';
					$gz = 'yes' . $retval1 . $retval2;
					fputcsv($fpa, array(date('Y-m-d_H:i:s'), $tp, $s, $t, $gz, $path), "\t");

					echo "{$dones[$path][0]} 已经同步, gzip压缩: {$path}\n";
				}
			}

		//    if ($tp == '')
		//        echo "{$dones[$path][0]} 已经同步: {$path}\n";

		} elseif (is_link($path)) {

			$tp = 'link';
			echo "同步 {$tp}: {$path}\n";
			exec("echo 同步 {$tp}: {$path} >> {$logs}");

			exec("rsync -akv {$path} root@192.168.1.2:/home/bak/rsync_178/{$path} >> {$logs} 2>&1");
			fputcsv($fpa, array(date('Y-m-d_H:i:s'), $tp, $s, $t, $gz, $path), "\t");
			$dones[$path] = array('', $tp, $s, $t, $gz, $path);
		} else {

			$spath = str_replace(' ', '\\ ', str_replace(')', '\\)', str_replace('(', '\\(', $path)));

			$tp = 'file';
			echo "同步 {$tp}: {$path}\n";
			exec("echo 同步 {$tp}: {$spath} >> {$logs}");

			$suf = substr($path, -3);
			$addsuf = ($suf != '.gz') ? '.gz' : '';
			$retval1 = $retval2 = '';

			if ($s < 100) {
				exec("rsync -av {$spath} root@192.168.1.2:'/home/bak/rsync_178/{$spath}' >> {$logs} 2>&1");
			} elseif ($t < $ptime) {
				$gz = 'yes';
				if ($suf != '.gz')
					exec("gzip {$spath}", $output, $retval1);
				exec("rsync -av {$spath}{$addsuf} root@192.168.1.2:'/home/bak/rsync_178/{$spath}{$addsuf}' >> {$logs} 2>&1");
			} else {
				$gz = 'yes';
				if ($suf != '.gz')
					exec("gzip {$spath}", $output, $retval1);
				exec("rsync -av {$spath}{$addsuf} root@192.168.1.2:'/home/bak/rsync_178/{$spath}{$addsuf}' >> {$logs} 2>&1");
				if ($suf != '.gz')
					exec("gunzip {$spath}{$addsuf}", $output, $retval2);
			}
			$gz .= $retval1 . $retval2;
			fputcsv($fpa, array(date('Y-m-d_H:i:s'), $tp, $s, $t, $gz, $path), "\t");
			$dones[$path] = array('', $tp, $s, $t, $gz, $path);
		}
	}
	closedir($handle);
}

if ($argc != 3) {
	echo "run: {$argv[0]} dir 2023-01-01\n";
	exit(-1);
}

$dir = $argv[1];
$ptime = strtotime($argv[2]);


$files = "rsync_{$dir}.files";
$logs = "rsync_{$dir}.log";


// 读取已经同步的列表
$dones = array();
if (file_exists($files)) {
	$fp = fopen($files, 'r');
	while ($line = fgetcsv($fp, 0, "\t")) {
		if ($line[1] == 'gz')
			continue;
		$file = $line[5];
		$dones[$file] = $line;
		$dones[$file . '.gz'] = $line;
	}
	fclose($fp);
}


$fpa = fopen($files, 'a');
sDir($fpa, $dones, $logs, $ptime, $dir);
fclose($fpa);

linux rsync命令

https://blog.csdn.net/Dontla/article/details/130371692

1. rsync 简介

rsync 就是远程同步的意思remote sync.

rsync 被用在UNIX / Linux执行备份操作操作.

rsync 工具包被用来从一个位置到另一个位置高效地同步文件和文件夹. rsync可以实现在同一台机器的不同文件直接备份,也可以跨服务器备份.

2. rsync的重要特性

速度快: 初次同步时, rsync会全量拷贝从源文件或目录到目标位置. 第二次往后同步时, rsync 仅仅会拷贝变化的数据块或字节到目标位置这将使得文件传输非常迅速.

安全: rsync 可以使用ssh协议加密传输.

占用带宽少: rsync 在发送时会压缩数据块, 接收后再解压缩数据块. 所以和其他文件传输协议比起来, rsync在跨主机传输文件时会占用较小的带宽.

不需要特殊权限: 安装和运行rsync 不需要特殊权限.

3. 用法

从语法结构我们可以看出, 源和目标即可以在本地也可以在远端. 如果是远端的话,需要指明登录用户名, 远端服务器名, 和远端文件或目录. 同时源可以是多个, 目标位置只能是一个.

3.1 Rsync参数解释

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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
一般同步传输目录都使用azv选项. 

-v, --verbose 详细模式输出 

-q, --quiet 精简输出模式 

-c, --checksum 打开校验开关,强制对文件传输进行校验 

-a, --archive 归档模式,表示以递归方式传输文件,并保持所有文件属性,等于-rlptgoD 

-r, --recursive 对子目录以递归模式处理 

-R, --relative 使用相对路径信息 

-b, --backup 创建备份,也就是对于目的已经存在有同样的文件名时,将老的文件重新命名为~filename。可以使用--suffix选项来指定不同的备份文件前缀。 

--backup-dir 将备份文件(如~filename)存放在在目录下。 

-suffix=SUFFIX 定义备份文件前缀 

-u, --update 仅仅进行更新,也就是跳过所有已经存在于DST,并且文件时间晚于要备份的文件。(不覆盖更新的文件) 

-l, --links 保留软链结 

-L, --copy-links 想对待常规文件一样处理软链结 

--copy-unsafe-links 仅仅拷贝指向SRC路径目录树以外的链结 

--safe-links 忽略指向SRC路径目录树以外的链结 

-H, --hard-links 保留硬链结 

-p, --perms 保持文件权限 

-o, --owner 保持文件属主信息 

-g, --group 保持文件属组信息 

-D, --devices 保持设备文件信息 

-t, --times 保持文件时间信息 

-S, --sparse 对稀疏文件进行特殊处理以节省DST的空间 

-n, --dry-run现实哪些文件将被传输 

-W, --whole-file 拷贝文件,不进行增量检测 

-x, --one-file-system 不要跨越文件系统边界 

-B, --block-size=SIZE 检验算法使用的块尺寸,默认是700字节 

-e, --rsh=COMMAND 指定使用rsh、ssh方式进行数据同步 

--rsync-path=PATH 指定远程服务器上的rsync命令所在路径信息 

-C, --cvs-exclude 使用和CVS一样的方法自动忽略文件,用来排除那些不希望传输的文件 

--existing 仅仅更新那些已经存在于DST的文件,而不备份那些新创建的文件 

--delete 删除那些DST中SRC没有的文件 

--delete-excluded 同样删除接收端那些被该选项指定排除的文件 

--delete-after 传输结束以后再删除 

--ignore-errors 及时出现IO错误也进行删除 

--max-delete=NUM 最多删除NUM个文件 

--partial 保留那些因故没有完全传输的文件,以是加快随后的再次传输 

--force 强制删除目录,即使不为空 

--numeric-ids 不将数字的用户和组ID匹配为用户名和组名 

--timeout=TIME IP超时时间,单位为秒 

-I, --ignore-times 不跳过那些有同样的时间和长度的文件 

--size-only 当决定是否要备份文件时,仅仅察看文件大小而不考虑文件时间 

--modify-window=NUM 决定文件是否时间相同时使用的时间戳窗口,默认为0 

-T --temp-dir=DIR 在DIR中创建临时文件 

--compare-dest=DIR 同样比较DIR中的文件来决定是否需要备份 

-P 等同于 --partial 

--progress 显示备份过程 

-z, --compress 对备份的文件在传输时进行压缩处理 

--exclude=PATTERN 指定排除不需要传输的文件模式 

--include=PATTERN 指定不排除而需要传输的文件模式 

--exclude-from=FILE 排除FILE中指定模式的文件 

--include-from=FILE 不排除FILE指定模式匹配的文件 

--version 打印版本信息 

--address 绑定到特定的地址 

--config=FILE 指定其他的配置文件,不使用默认的rsyncd.conf文件 

--port=PORT 指定其他的rsync服务端口 

--blocking-io 对远程shell使用阻塞IO 

-stats 给出某些文件的传输状态 

--progress 在传输时现实传输过程 

--log-format=formAT 指定日志文件格式 

--password-file=FILE 从FILE中得到密码 

--bwlimit=KBPS 限制I/O带宽,KBytes per second 

-h, --help 显示帮助信息

4. 示例

4.1. 示例 1. 同步同一台机上的两个目录
1
rsync -zvr /var/opt/installation/inventory/ /root/temp

说明:

-z: –compress 使用压缩机制

-v: –verbose 打印详细信息

-r: –recursive 以递归模式同步子目录

注意: 同步完成后, 我们会发现文件的时间戳timestamps发生了改变.

4.2. 示例 2: 保留文件的时间戳

有时我们希望拷贝或同步时, 时间戳不要发生变化, 源文件是什么时间戳,目标文件就是什么时间戳, 这时我们需要使用 -a –archive 归档模式选项. -a 选项相当于7个选项的组合 -rlptgoD

1
2
3
4
5
6
7
-r, --recursive: 递归模式Recursive mode
-l, --links: 将符号链接当作符号链接文件拷贝, 不拷贝符合链接指向的文件内容.
-p, --perms: 保留文件权限
-t, --times: 保留修改时间戳
-g, --group: 保留用户组信息
-o, --owner: 保留用户信息(需要超级用户权限)
-D, 相当于 --devices --specials 的组合, 保留设备文件, 保留特殊文件.
1
rsync -azv /var/opt/installation/inventory/ /root/temp/

同步完成后, 我们再来看文件属性, 时间戳信息得到了保留, 不仅如此文件的所有者 和所在组也得到保留.

4.3. 示例 3: 拷贝单个文件
1
rsync -v /var/lib/rpm/Pubkeys /root/temp/Pubkeys

说明: Pubkeys 是一个普通文件

4.4. 示例 4. 从本地拷贝多个文件到远端
1
rsync -avz /root/temp/ thegeekstuff@192.168.200.10:/home/thegeekstuff/temp/

使用rsync, 也可以从本地拷贝多个文件或目录到远端, 以下即为示例:

注意:

与本地文件拷贝不同的地方在于, 当拷贝文件到远程服务器时, 我们指定远程主机上的用户名, 服务器地址, 路径等信息, 类是于使用scp命令拷贝, 如果没有设置ssh免密码登录我们还需要提供远程用户的密码等信息.有时你不想频繁输入密码, 或者rsync运行在一个无人执守的脚本里面, 这是需要预先设置ssh免密登录, 或者使用结合expect命令,自动输入密码, 但是出于安全考虑, 密码需要加密. 所以在条件许可的情况下, 还是推荐设置ssh免密登录.

4.5. 示例 5. 从远程服务器拷贝文件到本地
1
rsync -avz thegeekstuff@192.168.200.10:/var/lib/rpm /root/temp

与示例 4 稍有不同, 这时远端目录或文件作为源位置, 本地目录或文件作为目标位置, 示例如下:

4.6. 示例 6. Remote shell for Synchronization

rsync 允许指定远程主机上运行shell命令. 这时需要使用 -e 选项: -e, –rsh=COMMAND 指定远端使用的shell命令

1
rsync -avz -e ssh thegeekstuff@192.168.200.10:/var/lib/rpm /root/temp
4.7. 示例 7. 拷贝时不覆盖目标位置已修改过的文件

在一下特殊的使用场景中, 我们不希望拷贝文件时, 我们不希望拷贝过程覆盖掉目标位置中用户做出的修改. 这时我们需要使用 -u 选项明确的告诉rsync命令保留用户在目标文件中作出的修改. 在下面的例子中, 文件Basenames是用户基于上次的拷贝, 修改过的文件, 当我们使用了-u 选项后, 该文件中的修改将不会被覆盖掉.

1
rsync -avzu thegeekstuff@192.168.200.10:/var/lib/rpm /root/temp

4.8. 示例 8. 仅拷贝目录结构, 不拷贝文件

在某些特殊场景中, 我们只需要远程服务器上的目录结构, 而不希望花大量时间, 带宽拷贝文件内容, 这时我们可以使用 -d, –dirs选项来达到目的.

1
rsync -v -d thegeekstuff@192.168.200.10:/var/lib/ .
4.9. 示例 9. 文件传输时显示进度

有时我们希望拷贝文件时, 能实时的显示拷贝进度, 以及传输速率等信息. 尤其是拷贝大文件时, 程序不输出信息, 用户往往无法区分程序是在响应中, 还是已经挂起, 在这种情况下如果使用 –progress 就会非常有帮助. rsync –progress option displays detailed progress of rsync execution as shown below.

1
rsync -avz --progress thegeekstuff@192.168.200.10:/var/lib/rpm/ /root/temp/

你也可以使用rsnapshot工具 (rsnapshot会调用rsync)来备份本地linux服务器, 或者备份远程linux服务器.

4.10. 示例 10. 同步时删除目标位置多余的文件或目录

有时我们希望目标文件和源文件保持严格一致, 不要多文件也不要少文件, 这是我们可能需要使用 -delete 选项来达到目的. 如果使用 -delete 选项, rsync将删除目标位置多余的文件或文件夹. 此选项还可以结合–delete-excluded 选项一起使用, 添加一些例外的文件.

1
2
3
4
# 现在Source and target 文件是一致的. 现在让我们在目标位置创建一个新文件.
$ touch new-file.txt

$ rsync -avz --delete thegeekstuff@192.168.200.10:/var/lib/rpm/ .

上述示例中, new-file.txt 是源文件中没有的文件, 其将会在拷贝时被删除掉.

4.11. 示例 11. Do not Create New File at the Target

在某些特殊的场景下, 我们只想更新, 目标位置已经存在的文件或目录, 而不关心源位置的新文件, 这时我们可以使用-existing 选项仅仅更新已经存在的文件. 让我们来验证一下这个选项的功能, 首先在源端添加一个新文件 new-file.txt.

1
2
3
4
[/var/lib/rpm ]$ > new-file.txt
Next, execute the rsync from the target.

$ rsync -avz --existing root@192.168.1.2:/var/lib/rpm/ .

从上面的例子可以看到, 由于加了–existing选项新文件new-file.txt没有被拷贝到目标位置

4.12. 示例 12. 查看目标位置和源位置之间的差异

选项-i, –itemize-changes 非常有用, 当我们想了解目标位置和源位置的文件差异时.

在源端:

1
2
3
4
$ ls -l /var/lib/rpm
-rw-r--r-- 1 root root  5357568 2010-06-24 08:57 Basenames
-rw-r--r-- 1 root root    12288 2008-05-28 22:03 Conflictname
-rw-r--r-- 1 root root  1179648 2010-06-24 08:57 Dirnames

在目标端:

1
2
3
4
$ ls -l /root/temp
-rw-r--r-- 1 root root    12288 May 28  2008 Conflictname
-rw-r--r-- 1 bin  bin   1179648 Jun 24 05:27 Dirnames
-rw-r--r-- 1 root root        0 Sep  3 06:39 Basenames

注意: 在上面的例子中, 源位置和目标位置有两处差异. 第一, 源文件Basenames的所有者和组 与 目标文件不同, 第一Dirnames文件大小也不一样. 现在让我们来看看rsync会怎样显示这些差异

1
rsync -avzi thegeekstuff@192.168.200.10:/var/lib/rpm/ /root/temp/

输出信息只在相应文件前面显示了9个字母来标识改变, 这些字母具体是什么意思呢? 请参考以下详细说明

1
2
3
4
5
6
> 表示文件已经被拷贝到了本地
f 代表该项目是一个文件.
s 代表文件大小发生了变化.
t 代表时间戳有差异.
o 所有者有差异
g 所属组有差异.
4.13. 示例 13. 使用通配符过滤文件

rsync 可以使用–include 和 –exclude 选项结合通配符进行文件或文件夹过滤

1
$ rsync -avz --include 'P*' --exclude '*' thegeekstuff@192.168.200.10:/var/lib/rpm/ /root/temp/

在上面的示例中, 仅仅以P打头的文件和文件夹被包含了进来, 其他的文件都被过滤在拷贝的过程中被排除在外了.

4.14. 示例 14. 不拷贝大文件
1
$ rsync -avz --max-size='100K' thegeekstuff@192.168.200.10:/var/lib/rpm/ /root/temp/

可以使用–max-size 告诉rsync 不要拷贝大小超过某个值的文件, 可以使用K, M, G指定文件大小, M for megabytes and G for gigabytes.

4.15. 示例 15. 拷贝整个文件

rsync 有个重要优点就是, 可以做到在拷贝的过程中, 只拷贝发生变化了的部分, 而不是发送整个文件. 但是在某些场景中, 比如文件较少, 文件size较小时, 我们的带宽又足够大, cpu资源相对又贫乏, 我们不希望它这样做, 因为毕竟计算源端和目标端的checksum, 并做对比, 也需要额外cpu开销. 这时我们可以使用 -W, –whole-file 选项, 让rsync不用计算那么多, 一上来就直接开始传送文件. 我们可以像下面这么做.

1
rsync -avzW  thegeekstuff@192.168.200.10:/var/lib/rpm/ /root/temp

git pull 跳过压缩 remote compression

https://www.itguest.com/post/bbbdgg1a2.html

git pull

1
remote: Compressing objects: 24%

来自 git 文档:

1
2
3
4
5
6
7
8
9
10
11
12
13
core.bigFileThreshold   

    Files larger than this size are stored deflated, without 
    attempting delta compression.  Storing large files without 
    delta compression avoids excessive memory usage, at the 
    slight expense of increased disk usage. 

Default is 512 MiB on all platforms. 
This should be reasonable for most projects as source code and other  
text files can still be delta compressed,  
but larger binary media files won't be. 

Common unit suffixes of 'k', 'm', or 'g' are supported

可以使用

1
git config --add core.bigFileThreshold 1