403 lines
24 KiB
Markdown
403 lines
24 KiB
Markdown
---
|
||
layout : post
|
||
title : "定时任务和实时文件监听"
|
||
subtitle : "cron VS inotify"
|
||
date : 2023-02-21 10:07:18
|
||
author : "Manford Fan"
|
||
catalog : false
|
||
header-img : "img/post-bg-universe.jpg"
|
||
tags :
|
||
- Cron
|
||
- Inotify
|
||
- Monitor
|
||
---
|
||
|
||
|
||
Cron服务我是一直有在使用的,比如开机启动,比如定时任务,这在构建自己的平台的时候是非常常见的需求,而且大多数情况下Cron服务表现的非常出色,但并不是没有缺点和不适用的场景。Inotify tools是一个工具集,里面包含三个常用的命令,功能是实时监控指定的文件或者文件夹,每当发生变化,即使非常细微,inotify也能及时的识别并报告出来。可以看出这两者差别还是挺大的,这就意味着互补性挺强的。
|
||
|
||
## 一、Cron定时任务
|
||
|
||
`cron`服务是Linux系统元老级的服务进程了,很多系统服务也会依赖于该服务。它的功能是固定周期定时循环执行某个命令或者脚本,如果想要在未来某个时间执行一次动作,可以考虑`at`命令,这个命令用法比较简单,使用`man`看下手册就知道该怎么使用,在这里就不做记录了。主要使用到的命令是`crontab`,本身的用法也比较简单,只不过有些规则比较绕,很容易设置完不生效。
|
||
|
||
`crontab`命令是用来为不同用户安装,卸载以及列出使用`cron`服务的工具,每个用户可以单独设定自己的`crontab`文件各个用户的文件都被放在`/var/spool/cron/crontabs`文件夹中(Debian11系统), 一般情况下,十分不建议手动编辑。
|
||
|
||
### 1. 相关文件
|
||
|
||
- /etc/cron.allow: 记录**允许**使用`crontab`命令的用户,每行一个用户
|
||
- /etc/cron.deny: 记录**不允许**使用`crontab`命令的用户,每行一个用户
|
||
- 两个文件只存在其一,以存在的文件为准
|
||
- 两个文件都不存在,以系统设定为准,都不允许或者都允许,**root用户**始终被允许
|
||
- 两个文件都存在,则以`cron.allow`为准
|
||
|
||
### 2. 命令选项
|
||
|
||
|Option|Descrition|
|
||
|:-|:-|
|
||
|-e|edit,编辑对应用户的crontab文件|
|
||
|-r|remove,移除对应用户的crontab文件,**谨慎使用**|
|
||
|-i|interactive,配合-r使用,删除文件前确认|
|
||
|-l|list,列出对应用户的crontab文件内容|
|
||
|-u|user,指定用户设定或者列出crontab文件内容|
|
||
|
||
|
||
### 3. 文件内容
|
||
|
||
`/var/spool/cron/crontabs`文件夹下的crontab文件内容分为三部分,环境变量设定,cron命令以及注释,每一部分的内容都是以行为单位,不可交叉,环境变量一般放在文件开头部分。需要注意,虽然crontab文件本身定义了一些环境变量(详见命令的`man`手册),但是最好还是自行将使用到的环境变量写在文件中,以避免运行不生效;另外,该文件不会做通常的bash替换,所以不能识别当前环境下的变量值。
|
||
|
||
```bash
|
||
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/var/lib/snapd/snap/bin:/root/bin"
|
||
SHELL="/usr/bin/bash"
|
||
|
||
# * * * * *
|
||
# - - - - -
|
||
# | | | | |
|
||
# | | | | +----- 星期几 (0 - 7) (Sunday=0 or 7, Sunday on this platform)
|
||
# | | | +---------- 月份 (1 - 12)
|
||
# | | +--------------- 几号 (1 - 31)
|
||
# | +-------------------- 小时 (0 - 23)
|
||
# +------------------------- 分钟 (0 - 59)
|
||
|
||
# at the beginning of every hour, update blog content & backup mysql
|
||
50 * * * * /usr/bin/bash /opt/scripts/sql_backup.sh
|
||
|
||
# at 02:10 of every day, do rclone sync things
|
||
10 2 * * * /usr/bin/bash /opt/scripts/rclone/rclone_sync.sh
|
||
10 2 * * * /usr/bin/bash /opt/scripts/hosts_update.sh
|
||
|
||
# at 03:20 of every Sunday, do backup things
|
||
20 3 * * 7 /usr/bin/bash /opt/scripts/backups.sh >> /opt/logs/backups.log 2>&1
|
||
|
||
# every half day, at 00:00 or 12:00, will do the transfermation between dos and unix format of all .md file
|
||
0 */12 * * * /usr/bin/find /opt/ -regextype posix-extended -regex ".*\.log|.*\.conf|.*\.sh|.*\.md" -exec /usr/bin/dos2unix {} \; > /dev/null 2>&1
|
||
|
||
# 00:05 of every day, do force reload rclone & alist service to refresh contents
|
||
5 0 * * * /usr/bin/bash /opt/scripts/rclone/rclone_alist_automount.sh -c
|
||
# 5 0 * * * /usr/bin/bash /opt/scripts/rclone/rclone_cloudreve_automount.sh -c
|
||
5 0 * * * /usr/bin/bash /opt/scripts/rclone/rclone_onedrive_automount.sh -c
|
||
|
||
# every mimute, check if there is any file name or number change in /opt/media.koel
|
||
# * * * * * /usr/bin/bash /opt/scripts/koel_update.sh
|
||
|
||
# every 10 mimutes, check if rclone & alist service is normal or not
|
||
*/10 * * * * /usr/bin/bash /opt/scripts/rclone/rclone_alist_automount.sh
|
||
# */10 * * * * /usr/bin/bash /opt/scripts/rclone/rclone_cloudreve_automount.sh
|
||
*/10 * * * * /usr/bin/bash /opt/scripts/rclone/rclone_onedrive_automount.sh
|
||
|
||
# do repo update @ 01:30 everyday
|
||
30 1 * * * /usr/bin/bash /opt/scripts/github_update.sh >> /opt/logs/github_update.log 2>&1
|
||
|
||
# reboot every Thursday 00:00
|
||
# 0 0 * * 4 /usr/sbin/reboot
|
||
|
||
# when reboot
|
||
@reboot /usr/bin/aria2c --conf-path=/etc/aria2/aria2c.conf -D
|
||
@reboot /usr/local/bin/jupyter lab --allow-root
|
||
@reboot /usr/bin/python3 /opt/source-code/calibre-web/cps.py
|
||
@reboot /usr/bin/qbittorrent-nox
|
||
@reboot /usr/bin/mount -t ext4 -w /dev/sdb1 /opt/webdav/wd
|
||
@reboot /usr/bin/bash /opt/scripts/jekyll_update.sh >> /opt/logs/jekyll_update.log
|
||
# @reboot /opt/source-code/clash/clash
|
||
# NO, because rclone depends alist.service
|
||
# @reboot nohup /usr/bin/rclone mount ALIST:/ /opt/webdav --allow-other --vfs-cache-mode full --vfs-cache-max-size 10G --vfs-read-ahead 100M --vfs-cache-max-age 4h --cache-dir /tmp/vfs-cache --bwlimit-file 20M --bwlimit 100M --log-file /opt/logs/rclone.log --log-level NOTICE --vfs-read-chunk-size-limit 10m --buffer-size 50M --attr-timeout 5m --transfers=6 --multi-thread-streams=6 --allow-non-empty > /dev/null 2>&1 &
|
||
|
||
# # acme auto renew cert
|
||
43 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null
|
||
```
|
||
|
||
### 4. cron命令书写规则
|
||
|
||
如上述的文件实例内容,cron命令的格式为`时间周期 + 命令`,命令不需要多解释,可以是单行命令,也可以是一个脚本的执行;对于时间周期,`crontab`提供了丰富的格式,以应对不同的使用场景。
|
||
|
||
```text
|
||
# * * * * *
|
||
# - - - - -
|
||
# | | | | |
|
||
# | | | | +----- 星期几 (0 - 7) (Sunday=0 or 7, Sunday on this platform)
|
||
# | | | +---------- 月份 (1 - 12)
|
||
# | | +--------------- 几号 (1 - 31)
|
||
# | +-------------------- 小时 (0 - 23)
|
||
# +------------------------- 分钟 (0 - 59)
|
||
```
|
||
|
||
通常情况下,周期时间是用五个数字来表示的,不设定的情况下是五个星(* * * * *),代表的含义以及对应的可选范围如上。根据不同的系统发行版,有些系统还支持使用星期和月份的缩写,来替代数字,比如`Mar`表示三月,`Fri`表示星期五等等。另外对于需要跟随系统启动,或者每天,每周,每月,每年运行一次的任务,还可以使用如下:
|
||
|
||
- @hourly :每小时运行一次,相当于"0 * * * *"
|
||
- @midnight :同@daily
|
||
- @daily :一天运行一次,相当于"0 0 * * *"
|
||
- @weekly :一周运行一次,相当于"0 0 * * 0"
|
||
- @monthly :一个月运行一次,相当于"0 0 1 * *"
|
||
- @annually :一年运行一次,相当于"0 0 1 1 *"
|
||
- @yearly :同@annually
|
||
- @reboot :重启时运行一次
|
||
|
||
除了如上指定的形式,`crontab`还支持更加多样化的规则设定,有些系统发行版支持执行列表和范围同时存在,比如"1,5, 10-40 * * * *",但是有些不支持,需要根据使用的系统来判断。
|
||
|
||
```bash
|
||
# 每5min打印一次hello
|
||
*/5 * * * * COMMAND
|
||
|
||
# 每8h执行一次命令,00:00,08:00和16:00
|
||
0 */8 * * * COMMAND
|
||
|
||
# 仅在01:00,09:00和12:00执行命令
|
||
0 1,9,12 * * * COMMAND
|
||
|
||
# 在每年3-5月份的4号凌晨03:05 -- 03:30之间,每分钟执行一次命令
|
||
5-30 3 4 3-5 * COMMAND
|
||
|
||
# 每小时的第一分钟,第五分钟以及第10-40分钟,每分钟执行一次命令
|
||
1,5, 10-40 * * * * COMMAND
|
||
```
|
||
|
||
### 5. 日志记录
|
||
|
||
一般情况下可以通过`cron`命令来设定需要记录日志的级别,如下图所示,可以使用`-L loglevel`参数来指定该服务需要记录日志的内容,loglevel为设定的等级,可有想要设定的内容代表的数字累加而得到。默认是level 1,只记录开始的动作;设定为0,表示关闭服务的日志记录功能;设定为15,表示开启所有类型的日志记录,相应的,如果服务下有很多指令,还是建议不要开启全日志记录,会占用比较大的空间。
|
||
|
||

|
||
|
||
> **日志存放路径:`/var/log/syslog`**
|
||
|
||
|
||
## 二、Inotify实时文件监控
|
||
|
||
也不是最近的需求了,其实这个博客系统也是使用[Jekyll](https://jekyllrb.com/)构建的,每次有新的博文增加或者修改都需要手动运行一下`jekyll b -s ...`,虽然提供了`--watch --incremental`参数可以实时监控博文的更新修改情况,一种情况是修改***_config.yml***时,不生效,需要停止进程重新运行;另一种情况是,运行一段时间之后还是会发现某些博文没有被及时更新上线。直到最近在学习使用[Just the Docs](https://github.com/just-the-docs/just-the-docs)构建知识体系,发现实时监控文件变化的诉求更加迫切。
|
||
|
||
### 1. 简介
|
||
|
||
*inotify tools*是Linux内核2.6.13 (June 18, 2005)版本新增的一个子系统(API),它提供了一种监控文件系统(基于inode的)事件的机制,可以监控文件系统的变化如文件修改、新增、删除等,并可以将相应的事件通知给应用程序。这个工具集包含如下三个命令,统计使用最多的是`initofywait`,因为在收集资料时发现,绝大部分现有的资料都是针对`inotifywait`,而且不能说完全相同吧,只能说绝大部分是*Copy & Paste*。
|
||
|
||
### 2. 命令使用
|
||
|
||
inotify-tools是一个C库和一组命令行组成的工具集,提供了Linux下inotify工作的简单接口。也是一种强大的、细粒度的、异步文件系统监控机制,它满足各种各样的文件监控需要,可以监控文件系统的访问属性、读写属性、权限属性、删除创建、移动等操作,因为调用的是内核的API,可以监控文件发生的一切变化。
|
||
|
||
#### a. inotifywait
|
||
|
||
该命令的作用就是使用`inotify`接口监控文件或者文件夹的变化,特别适合用在shell脚本中,它可以被设定成触发一次之后退出,也可以被设定成持续监控并输出触发的结果。
|
||
|
||
> **支持的选项**
|
||
|
||
|Options|Descriptions|
|
||
|:-|:-|
|
||
|@<file>|监控文件夹时,排除部分文件夹,绝对或相对路径取决于被监控文件夹的格式|
|
||
|--fromfile <file>|从文件中读取要监控的文件夹,以@开头的行表示排除在外|
|
||
|-m, --monitor|持续监控而不是触发一次就退出|
|
||
|-d, --daemon|同 -m,不过不会输出在stdout上,而是输出到文件,所以必须指定-o参数|
|
||
|-o, --output|输出触发的事件内容到文件|
|
||
|-s, --syslog|把错误信息输出到syslog而不是stderr|
|
||
|-r. --recursive|递归监控文件夹,没有深度限制,即使新创建的文件夹也会被监控,软链接除外|
|
||
|-q, --quiet|安静模式,-q只输出事件信息,-qq什么都不会输出|
|
||
|--exclude <pattern>|排除文件或者文件夹,可使用扩展正则表达式,**区分**大小写|
|
||
|--excludei <pattern>|排除文件或者文件夹,可使用扩展正则表达式,**不区分**大小写|
|
||
|−t <seconds>, −−timeout <seconds>|如果指定时间内没有触发,就会退出,不指定则无限等待|
|
||
|−e <event>, −−event <event>|指定要监听的事件,可指定多个,逗号分隔|
|
||
|−−timefmt <fmt>|指定输出时间的格式,必须要遵守strftime规则,同`date`|
|
||
|−−format <fmt>|类似于printf的语法,自定义输出触发事件的格式|
|
||
|
||
对于`--format <fmt>`参数,用户可以根据如下指定格式进行自定义输出,每行限制4000个字符:
|
||
- %w:监控文件时,输出为触发事件的文件
|
||
- %f:监控文件夹时,输出为触发事件的文件,否则为空字符串
|
||
- %e:输出为触发的事件名称,多个事件以逗号分隔
|
||
- %Xe:输出为触发的事件名称,多个事件用字符"X"分隔
|
||
- %T:输出为使用`−−timefmt <fmt>`参数指定的时间格式
|
||
|
||
**特别需要注意**:`--exclude(i)`参数在命令行中只能使用一次,使用多次的话,结果是只会执行最后一次的表达式指定的文件或者目录;`@`参数后面直接跟要排除的文件夹的路径,**且只能是文件夹路径**,两者之间没有空格;`--fromfile`后面跟一个文件,文件内容是要监控的**文件夹路径**或者要排除的**文件夹路径**。所以`@`和`--fromfile`这两个参数只能处理**文件夹路径**,不能排除文件,从加粗的频率看,博主大概率是在这方面吃过亏的QAQ!!
|
||
|
||
总结一下,关于排除文件和文件夹,`--exclude(i)`参数既可以排除文件,也可以排除文件夹,还可以使用扩展正则表达式,功能最全面;`@`和`--fromfile`这两个参数只能处理**文件夹路径**,不能排除文件;有一种情况`--fromfile`后面的文件内容可以是**文件路径**,那就是有很多零散的文件需要监控,这个时候就肯定没有也没必要有需要排除的文件或者文件夹了,因为指定的就是文件路径,不想监控,可以直接不写。
|
||
|
||
```bash
|
||
# 很明显watch.list里面放的是文件夹,因为使用了 -r 参数
|
||
# 如下inotify命令表示,监控 /root/TODO/ 文件夹,但是排除其下的exclude/,yes/ 和 nope/ 文件夹
|
||
# 也排除文件名是todo.txt的文件,而且排除的是所有todo.txt文件
|
||
$ cat /root/watch.list
|
||
/root/TODO
|
||
@/root/TODO/exclude
|
||
$ inotifywait -mrq --fromfile /root/watch.list --timefmt "%Y-%m-%d %H:%M:%S" --format "%T %w%f %e" -e delete,move,close_write --exclude '/root/TODO/nope/|^.*/todo.txt' @/root/TODO/yes
|
||
```
|
||
|
||
> **可被监控的事件类型**
|
||
|
||
|Event Name|Description|
|
||
|:-|:-|
|
||
|access|监控之下的文件被读取|
|
||
|modify|监控之下的文件被修改|
|
||
|attrib|监控之下的文件属性发生变化,权限,日期信息等|
|
||
|close_write|监控之下的文件被可写模式打开后关闭,**但这并不意味着文件有写入**|
|
||
|close_nowrite|监控之下的文件被只读模式打开后关闭|
|
||
|close|无特殊意义,不单独出现,一般跟在上述两种关闭事件之后,表示文件关闭|
|
||
|open|监控之下的文件被打开|
|
||
|move_to|文件或者文件夹**被移动到了被监控的目录下**,被监控路径下的移动都属于此类|
|
||
|move_from|文件或者文件夹被移动到了**被监控的目录之外**,被监控路径下的移动也都属于此类|
|
||
|move|表示包含上述两种移动事件,不会打印出现|
|
||
|move_self|-|
|
||
|create|监控之下,文件或者文件夹被创建|
|
||
|delete|监控之下,文件或者文件夹被删除|
|
||
|delete_self|-|
|
||
|unmount|被监控的文件或者文件夹所在的文件系统被unmount之后触发|
|
||
|
||
一般常用的事件类型是create/delete/modify/open/close_write/move,因为`inotifywait`监控的粒度非常的详细,所以每操作一个文件的时候,命令都会输出详细的步骤,体现在程序中就是一次文件修改/创建操作,导致循环被执行多次,造成一定程度的资源浪费,合理选择触发的事件类型可以一定程度上规避此问题。
|
||
|
||
> **输出格式**
|
||
|
||
`inotifywait`命令会将启动时的采集分析信息输出到stderr,把触发的事件信息输出到stdout,默认的输出格式是按照输出,每行的组成分别是"*watched_filename EVENT_NAMES event_filename*"
|
||
|
||
```text
|
||
watched_filename: 被监控的文件名,如果监控的是目录,则是触发事件的文件所在目录,最后一个字符一定是'/'
|
||
EVENT_NAMES : 触发的事件名称,可参考上述"事件类型"
|
||
event_filename : 该部分仅当监控目录的时候才会输出,是触发事件的文件名
|
||
```
|
||
|
||
|
||
#### b. inotifywatch
|
||
|
||
`inotifywatch`命令的主要功能是使用inotify接口对某个目录下的文件操作事件类型数量做统计分析,该命令也是监控文件的各种变化,但是并不执行命令,而只是将每个文件触发的事件类型次数做了一个统计,并且事件类型统计可以按照自定义格式排序。该命令可被监控的事件类型和`inotifywait`完全一致,命令支持的参数比`inotifywait`没有`-m/-d/-o/-s`,但是多两个`-a/-d`,仅作不同之处的记录。
|
||
|
||
|Options|Descriptions|
|
||
|:-|:-|
|
||
|-a <event>, --ascending <event>|按照某种事件类型**升序**统计|
|
||
|-d <event>, --descending <event>|按照某种事件类型**降序**统计|
|
||
|
||
|
||
```bash
|
||
# 监控/root/TODO文件夹,并按照access升序统计
|
||
[root@CrossChain] [~]
|
||
> inotifywatch -r -a access /root/TODO/ -e modify,open,create,access -t 60
|
||
Establishing watches...
|
||
Finished establishing watches, now collecting statistics.
|
||
total access modify open filename
|
||
383 7 4 372 /root/TODO/nope/
|
||
411 16 4 391 /root/TODO/just-the-docs-0.4.0.rc3/
|
||
1116 29 4 1083 /root/TODO/
|
||
|
||
# 监控/root/TODO文件夹,并按照access降序统计
|
||
[root@CrossChain] [~]
|
||
> inotifywatch -r -d access /root/TODO/ -e modify,open,create,access -t 60
|
||
Establishing watches...
|
||
Finished establishing watches, now collecting statistics.
|
||
total access modify open filename
|
||
1296 38 6 1252 /root/TODO/
|
||
582 20 5 557 /root/TODO/yes/
|
||
216 9 2 205 /root/TODO/just-the-docs-0.4.0.rc3/
|
||
```
|
||
|
||
|
||
#### c. inotify-hookable
|
||
|
||
该命令Man手册中解释的功能是:*inotify−hookable − blocking command−line interface to inotify*。我理解应该是该命令提供了一个阻塞命令行执行的接口,当文件被检测到有变化才会触发式执行。据命令的开发者描述,这个小工具是为了替代“*the functionality offered by Plack’s Filesys::Notify::Simple*”,简化了原来需要写脚本,①文件系统发生变化,②`inotify`检测到变化,③执行指定文件变化时需要运行的命令,而现在使用`inotify-hookable`就可以在一个命令中完成之前需要三步才能完成的事情。
|
||
|
||
而且相较于`inotifywait/inotifywatch`(使用的时notify7接口),该命令使用inotify2接口,Man Page中描述,该接口速度非常的快,以至于需要处理好该命令发送事件类型的速度,以保证其他程序可以正确收到信号并执行。
|
||
|
||
|
||
> **支持的选项**
|
||
|
||
|Event Name|Description|
|
||
|:-|:-|
|
||
|-w, --watch-directories|指定需要监控的文件夹,可使用多次来监控不同的文件夹|
|
||
|-f, --watch-files|指定需要监控的文件,可使用多次来监控不同的文件,与-w不冲突|
|
||
|-r, --[no-]recursive|对指定的文件夹执行递归操作,默认开启|
|
||
|-c, --on-modify-command|当文件改变时,命令会执行|
|
||
|-C, --on-modify-path-command|是一个键值对的形式,key代表一个扩展正则表达式,value表示对匹配改正则表达式的文件或者文件夹需要执行的命令|
|
||
|-t, --buffer-time|该命令执行的非常快,当某个命令的操作可能造成被检测为两个批次,所以添加了等待时间100ms,如果100ms内没有接收到其他的事件触发,则立即发送当前的事件|
|
||
|-i, --ignore-paths|使用正则表达式指定不需要监控的文件或者文件夹|
|
||
|-d, --debug|debug模式,输出的信息更加详细|
|
||
|-q, --[no-]quiet|安静模式,输出简洁的信息|
|
||
|
||
|
||
如下是两个示例程序,理论上`inotify-hookable`命令后面可以监控非常多的文件和文件夹,只要注意使用`--on-modify-path-command`和`--on-modify-command`这两个选项设定好命令执行范围即可。另外,同一个脚本中只能有一个`inotify-hookable`命令出现,不能出现多个。该命令大多数情况下可以替代多个`inotifywait`脚本,实现统一的管理。
|
||
|
||
|
||
```bash
|
||
# 示例程序-1
|
||
inotify-hookable \
|
||
--watch-directories /opt/source-code/blog \
|
||
--watch-directories /opt/source-code/document/python \
|
||
--watch-directories /root/TODO \
|
||
--ignore-paths /opt/source-code/blog/.git/ \
|
||
--ignore-paths /opt/source-code/blog/img/avatar.jpg \
|
||
--ignore-paths /root/TODO/nope \
|
||
--ignore-paths /root/TODO/.*\.txt \
|
||
--on-modify-path-command "(^/opt/source-code/blog/.*)=(echo blog)" \
|
||
--on-modify-path-command "(^/opt/source-code/document/python/.*)=(echo python)" \
|
||
--on-modify-path-command "(^/root/TODO/.*)=(echo TODO)"
|
||
|
||
# 示例程序-2
|
||
inotify-hookable \
|
||
--watch-files /root/TODO/nope/todo.txt \
|
||
--on-modify-path-command "(^/root/TODO/nope)=(echo todo)" \
|
||
--watch-files /root/TODO/yes/hook.log \
|
||
--on-modify-command "echo hook" \
|
||
```
|
||
|
||
虽然理论上`inotify-hookable`命令可以将多个`inotifywait`命令写的脚本整合成一个脚本,实际面临着一个问题,使用`inotifywait`命令写的脚本一般都会有一定的长度,因为涉及到业务逻辑处理,所以需要在**脚本-1**中定义好功能实现函数,根据传参确定执行的部分,然后在**脚本-2**的`inotify-hookable`命令中调用脚本-1,如下是一个真实的例子,实际执行的时候,会将对应的部分展开执行。最后,运行结果表明,`inotify-hookable`的执行速度**远远快于**`inotifywait`命令!!!
|
||
|
||
```bash
|
||
# 脚本-1
|
||
#!/bin/bash
|
||
# update Just the Docs -- Python
|
||
function python_update() {
|
||
echo ====================================================
|
||
echo `date`
|
||
echo $directory$filename $action
|
||
rm -rf /opt/websites/just-the-docs/python
|
||
jekyll b -s /opt/source-code/document/python -d /opt/websites/just-the-docs/python
|
||
echo -e '\n'
|
||
}
|
||
# update Jekyll blog
|
||
function blog_update() {
|
||
echo ====================================================
|
||
echo `date`
|
||
echo $directory$filename $action
|
||
rm -rf /opt/websites/blog
|
||
let numOfAvatar=`ls /opt/websites/nav/assets/images/logos/ | wc -l`
|
||
let randNumber=$RANDOM%$numOfAvatar
|
||
|
||
cp /opt/websites/nav/assets/images/logos/${randNumber}.jpg /opt/websites/homepage/assets/img/logo.jpg -rf
|
||
cp /opt/websites/nav/assets/images/logos/${randNumber}.jpg /opt/websites/nav/assets/images/logos/avatar.jpg -rf
|
||
cp /opt/websites/nav/assets/images/logos/${randNumber}.jpg /opt/source-code/blog/img/avatar.jpg -rf
|
||
jekyll b -s /opt/source-code/blog/ -d /opt/websites/blog/
|
||
echo -e '\n'
|
||
}
|
||
|
||
if [[ $1 == 'blog' ]]; then
|
||
blog_update
|
||
elif [[ $1 == 'python' ]]; then
|
||
python_update
|
||
else
|
||
echo Wrong
|
||
fi
|
||
|
||
# ===========================================================
|
||
# 脚本-2
|
||
#!/bin/bash
|
||
# 监控文件变化,自动生成内容
|
||
inotify-hookable \
|
||
--watch-directories /opt/source-code/blog \
|
||
--watch-directories /opt/source-code/document/python \
|
||
--ignore-paths /opt/source-code/blog/.git/ \
|
||
--ignore-paths /opt/source-code/blog/img/avatar.jpg \
|
||
--on-modify-path-command "(^/opt/source-code/blog/.*)=($(blog_update))" \
|
||
--on-modify-path-command "(^/opt/source-code/document/python/.*)=($(python_update))"
|
||
```
|
||
|
||
|
||
|
||
|
||
### 3. 参数配置
|
||
|
||
该特性在Linux内核2.6.13版本以后,才能支持inotify软件。在没有安装inotify软件之前,在"/proc/sys/fs/inotify"文件夹下应该有`max_queued_events/max_user_instances/max_user_watches`这三个文件,这三个文件中的默认值都是可以被修改的,以监听更大范围的文件,但在修改之前,要确保自己知道在做什么。
|
||
|
||
|文件|默认|描述|
|
||
|:-|:-|:-|
|
||
|max_queued_events|16384|设置inotify实例事件队列可容纳的事件数量|
|
||
|max_user_instances|128|设置每个用户可以运行的inotifywait或inotifywatch命令的进程数|
|
||
|max_user_watches|65536|设置inotifywait或inotifywatch命令可以监视的文件数量(单进程)|
|
||
|
||
> **默认是Debian11系统**
|
||
|
||
|
||
## 三、参考文档
|
||
|
||
- [Github inotify tools](https://github.com/inotify-tools/inotify-tools)
|
||
- [Inotifywait Mannal Page](https://linux.die.net/man/1/inotifywait)
|
||
- [Inotifywatch Mannal Page](https://linux.die.net/man/1/inotifywatch)
|
||
- [Inotify-hookable Mannal Page](https://manpages.debian.org/unstable/inotify-hookable/inotify-hookable.1p.en.html)
|