一般情况下,系统通过安装软件包的方式安装的 incron 都带有 SystemD 的启动文件。
此时,只需要以下命令便可启动 incron 的守护进程:
sudo systemctl start incron.service
# 或者
sudo systemctl start incrond.service
查看启动状态:
systemctl status -l incron.service
或者:
systemctl status -l incrond.service
开机启动:
sudo systemctl enable incron.service
# 或者
sudo systemctl enable incrond.service
incron 表的两种类型
incron 的表根据创建者有两种类型,其中一个是系统创建的系统表,另一个是用户创建的用户表。
用户表包含 root 用户和其他用户。
系统表所指定运行的命令具有 root 用户的权限,而用户表具有其相应用户的权限。
并且,按照规定,用户表只能监控自身具有读权限的相应目录和文件。
用户表以用户名称为文件名,存放在 /var/spool/incron/ 目录路径下;而系统表存入于 /etc/incron.d/ 目录路径下。
要访问 /var/spool/incron/ 需要 root 用户或 sudo 权限。
incrontab
incrontab 是 Inotify cron(incron)的表操纵器。它创建、删除、修改和列出用户表。
每个用户具有自己的表,任何给定的表中的命令将作为拥有该表的用户执行。
当表被修改时,或者守护进程启动时,incron 都会读取 incrontab 表,表与 incrond 进行挂钩。
incrontab 命令参数
incrontab 是操纵和管理 incron 表的命令行工具。
它结合一些命令行参数选项管理着所有用户表。
它有以下的命令行参数:
-
-u 或 --user:(仅能 root 用户使用)以该参数指定的用户执行以下的一些操作,如 -l、-e 等。
该选项主要用于操作系统用户的表:
比如: nginx、www、postfix 等等。
-
-l 或 --list:列出当前用户的所有 incron 表规则。
如果指定 -u 参数,则表示列出其指定用户的所有表规则。
-
-r 或 --remove:执行此参数将没有任何警告的情况下永久删除当前用户表。
-
-e 或 --edit:指定该参数将会用设定或默认的文本编辑器打开用户表并编辑之。
它会用一个临时文件来编辑,保存文件后,更改后的文件内容会保存到 /var/spool/incron/username。
普通用户不用提权也可使用。
-
-t 或 --types:列出所有支持的事件类型,以英文逗号分隔。
-
-d 或 --reload:让守护进程重新加载当前表。
由于旧表在修改后保存时守护进程会自动重新加载。
所以该功能主要用于新建的表(可能是允许了新的用户),或者用于重置 IN_ONESHOT 事件。
-
-f <FILE> 或 --config=<FILE>:指定另一个位置的配置文件。此功能需要 root 权限。
更多关于 incrontab 的资料请阅读文档: man incrontab。
incrontab 授权用户
incron 有两个文件来进行对用户使用的授权,一个是 /etc/incron.allow,另一个是 /etc/incron.deny。
这两个文件不都是为“准入”而设计的,前者肯定是,但是后者是相反的,类似于黑名单,在它的列表中,如果出现了某个用户名,那么该用户将不能使用 incron。
然而在前者列表中出现的用户,将被允许使用 incron。
如果都删除了这两个文件,那么将允许所有的用户使用 incron。这是很不安全的做法!
这两个文件可被 root 用户,或者 sudo 的使用者编辑。
文件内容的格式是一行一个用户。
编辑 incrontab 表
使用 incrontab 命令的 -e 选项(incrontab -e)打开当前登录用户的 incron 表编辑器。
每行一个规则。
如果指定 -u 参数,那么编辑表命令就变成 incrontab -u username -e,不过这需要 root 用户。
incron 环境变量
在 incrond 的文档是这样写的:
对于系统表,使用默认(与 incrond 本身相同)环境变量集。这同样适用于 root 的表。
对于非 root 用户表,清除整个环境,然后只设置这些变量:LOGNAME、USER、USERNAME、SHELL、HOME 和 PATH。
变量(PATH 除外)从用户数据库(例如/etc/passwd)获取值。PATH 变量设置为 /usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin。
参考:https://linux.die.net/man/8/incrond
incron 表的规则
incron 表的规则离不开监视路径、文件事件和执行的命令。
incron 的文件事件
阅读本文到这里,相信大家都知道 incron 是靠文件系统事件驱动的了。
那么 incron 都有哪些事件呢?
incron 支持以下的事件(掩码符号):
-
IN_ACCESS:文件被访问(打开)。
-
IN_ATTRIB:文件元数据被更改(如权限、时间戳、扩展属性、用户 ID、用户组,等等)。
-
IN_CLOSE_WRITE:文件以写的方式打开并且关闭。
-
IN_CLOSE_NOWRITE:文件不以写的方式打开并且关闭。
-
IN_CLOSE:以上两个条目的合并。
-
IN_CREATE:在监视的目录中创建新的文件/目录。
-
IN_DELETE:在监视的目录中删除文件/目录。
-
IN_DELETE_SELF:监视的文件/目录自己被删除。
-
IN_MODIFY:文件被修改。
-
IN_MOVE_SELF:监视的文件/目录自己被移动。
-
IN_MOVED_FROM:从监视的目录中移出目录/文件。
当文件被重命名时,发生在包含老文件名称的目录上。
-
IN_MOVED_TO:移动文件进入监视的目录。
当文件被重命名时,发生在包含新文件名称的目录上。
-
IN_MOVE:以上两者的合并。或者这可以理解为对文件的重命名触发的文件事件。
-
IN_OPEN:文件被打开。
-
IN_ALL_EVENTS:此符号定义为上述所有事件的位掩码。
-
IN_DONT_FOLLOW:如果它是一个符号链接,不要取消引用路径名。
更明白地解释就是不要追踪此符号链接指向的目标。
-
IN_ONESHOT:仅能监视一次事件。
在一次事件发生后,并且在重启或重置 incrond 之前将不再监视设置有该掩码的表规则。
-
IN_ONLYDIR:如果它是一个目录,只监视路径名(不监视文件)。
-
IN_NO_LOOP:该符号禁用监视事件,直到当前事件被完全处理(直到其子进程退出)。
此掩码符号防止监视的事件发生无限循环。
如果此事件无效,或者当前 incrontab 不支持它,那么就用 loopable=true 代替它。
incrontab -t 列出所有当前系统中 incrond 支持的所有文件系统事件,如果 IN_NO_LOOP 不在其列表中,那么就表示不支持此事件。
incrond 文档中写有:
守护进程本身目前没有防止循环的保护。
如果执行的命令是由于 一个事件会导致相同的事件,它会导致无限循环,除非标志掩码包含 指定了 loopable=true。
-
IN_IGNORED:监控项被移除。
-
IN_ISDIR:触发事件的是一个目录。
-
IN_Q_OVERFLOW:事件队列溢出。
-
IN_UNMOUNT:监视的文件系统被卸载(unmount)。
incron 表的规则是怎样的
本文前面说了,所谓“表的规则”是 incron 表的一行。
表的一行规则包含要监视的目录或文件路径、incron 定义的事件掩码(符号或数字,多个以英文逗号分隔),以及处理事件触发后的处理程序。
简而言之,表的一行规则:
<路径> <掩码> <命令>
其中:
-
“<路径>”是要监视的文件系统中目录或文件的绝对路径;
-
“<掩码>”是在 Inotify 接口代码中定义的事件掩码;
也是本文前面所述的事件掩码,它可以是掩码符号或者掩码数字;
-
“<命令>”则是一个可执行文件的绝对路径或者在环境变量中指定的目录路径下的命令本身。
请不要试图在表定义的规则中将标准输出和错误输出到其他文件,因为这注定是徒劳的。
incron 的通配符
既然介绍了如何设置一条表规则,那么现在就举个使用通配符(其实就是特殊的 Shell 变量)的例子。
incron 有以下的变量可在表的规则中使用:
$$:美元符号;
$@:监视的文件系统路径;
$#:事件的相关文件名;
$%:事件掩码符号(是文本);
$&:事件掩码数字。
可将上面这些变量以参数形式传入到脚本中处理。
以下是示例:
表规则:
/code/php/htdocs IN_ALL_EVENTS /data/home/after-os-installation/rsync/test.sh $$ $@ $# $% $&
以下是脚本文件 /data/home/after-os-installation/rsync/test.sh 的内容(该文件要让当前用户可读):
echo "$1 $2 $3 $4 $5" >> ~/test.log
文件 ~/test.log 显示的结果:
$ /code/php/htdocs wp-load.php IN_OPEN 32
上面的示例中,/code/php/htdocs 是 <路径>,路径后面一般不带斜杠; IN_ALL_EVENTS 是 <掩码>;
/data/home/after-os-installation/rsync/test.sh 是 <命令>,后面紧接着的是要输入 <命令> 的参数。
查看日志
前面(章节《incron 表的规则是怎样的》)提到,不要尝试在表规则中进行标准输出错误输出,因为规则的运行效果通过系统日志输出。
在 Debian 系的 Linux 系统,是在 /var/log/syslog 这个文件中输出系统消息日志;红帽系(Fedora 等)在文件 /var/log/messages 输出日志。
若是想查看实时日志输出,可执行以下命令:
tail -f /var/log/syslog
举例:利用 incron 和 Rsync 进行实时文件备份
远程文件备份常见的工具
说到 Linux 下远程文件备份,大多数情况下会联想到 SCP、FTP、SFTP、Rsync 等众多的工具。前面这些工具中,有的可以增量备份,有的只能进行全量备份。
什么是全量备份
全量备份是每次备份都会把备份源的所有文件都复制到(远程)目标目录。
这样做的缺点是,如果要备份的文件太多,那么会导致整个备份过程耗时过久。
什么是增量备份
相对于全量备份,增量备份仅复制有变化的文件。
常见做法是,第一次备份进行全量备份,把源目录下(可能要经排除之后)的所有文件全部复制进(远程)目的目录;之后的备份就进行增量备份。
不一定所有的备份工具都有增量备份的功能。有的工具通过编写 Shell 脚本来“模拟”增量备份,而 Rsync 自身就有增量备份的功能(当使用 --delete 参数,再次执行同步时,源目录增删文件地在目标目录进行相同的操作)。
什么是 Rsync
Rsync,全称 remote sync,是一款远程和本地文件同步工具,同时,用它来进行本地与本地间备份也可。它使用一种算法通过仅移动已更改的文件部分来最小化复制的数据量,这也就是增量备份。
Rsync 通过 SSH 方式传输文件
Rsync 可通过 SSH 像 SCP 一样进行本地与远程的文件有加密地传输。
这种传输方式,优点是加密,缺点是不能指定上传到远程服务器的文件用户属主和属组,属主和属组默认为 SSH 上传的用户名。
举例:
rsync -av --delete /path/to/test/dir/ utest@test.com:/tmp
上述的 Rsync 命令把本地的路径为 test/dir/ 的目录通过 SSH 上传到域名为 test.com 的远程服务器上面的 /tmp 目录。
其中:
-a:表示目录递归上传,以及把路径为 test/dir/ 的目录下元数据有改动的文件都上传。
-v:表示显示文件传输的详细信息。若不指定该选项,则会进入静默模式,整个传输过程不会有任何的东西打印出来。
--delete:表示删除目标目录中有的而源目录没有的文件。
utest:这是 SSH 登录的用户名。
本章节的示例仅适合 SSH 端口为默认的 22,并且不需要密钥验证的场景下。
指定密钥文件
上一章节的示例简单完整地演示出如何利用 Rsync 通过 SSH 通道上传文件资料。
这一章节的示例设置了 SSH 的非默认端口,以及应用上 SSH 密钥传输。
举例:
rsync -av --delete -e "ssh -p 23123 -i ~/.ssh/id_rsa" /path/to/test/dir/ utest@test.com:/tmp
以上示例中:
-e:指定 SSH 的相关配置,其中包括: -p 指定 SSH 端口 23123,-i 指定 SSH 登录用的私钥(私有密钥,公钥在远程服务器上)。
同步备份接收方文件的属主问题
Rsync 通过 SSH 通道上传到服务器的文件属主和属组均为此次 SSH 方式登录的用户名。
如果需要文件上传到服务器后赋予指定的属主和属组呢?
以上的这种需求可通过配置 Rsync 服务器端,并且使用 Rsync 协议来解决问题。
关于如何配置 Rsync 服务器端请参阅:Linux 下 Rsync 文件同步与增量备份 。
结合 Rsync 和 incron 来实时同步文件
本章节讲解如何结合 Rsync 和 incron 远程实时同步文件数据。
首先要有个源目录/文件
这时里要同步到远程的是一个目录,其目录路径是: /path/to/test/dir/。
然后设置要监视的文件事件
IN_CREATE,IN_DELETE,IN_CLOSE_WRITE,IN_MOVE
它们分别触发的事件是:创建新的文件、删除文件、写入并关闭文件和重命名文件/目录。
创建文件事件触发后要执行的脚本
把下面的命令写入一个当前系统登录用户可读的地方,这里 Shell 脚本的路径是:/home/username/remote-utest.sh。
该脚本文件的内容是:
#!/bin/sh
# 这里要求 SSH 密钥不能有密码,否则就无法同步
# 密钥不能有密码,也就是生成密钥时设置为空密码。
rsync -av --delete -e "ssh -p 23123 -i ~/.ssh/id_rsa_no_passwd" /path/to/test/dir/ utest@test.com:/tmp
应用当前用户下的 incron 表来设置实时同步
执行 incrontab -e 打开 incrontab 表的配置文件,然后添加以下一行:
/path/to/test/dir IN_CREATE,IN_DELETE,IN_CLOSE_WRITE,IN_MOVE /home/username/remote-utest.sh
保存文件,然后退出。
就这样简单几个步骤就把 incron 结合 Rsync 进行实时文件同步配置好了。
在 /path/to/test/dir 目录下做一些操作,如添加文件、修改文件、删除文件、重命名文件等等,同时,远程都会有相应的文件变化。