linux实战技能100讲笔记,⭐《Linux实战技能100讲》个人笔记 - 7. 其他工具

[TOC]

Logrotate 日志管理工具

logrotate 是一个Linux系统默认安装了的日志文件管理工具,用来把旧文件轮转、压缩、删除,并且创建新的日志文件。我们可以根据日志文件的大小、天数等来转储,便于对日志文件管理。

默认 logrotate 是在每天凌晨 3 点多被 anacron 调用执行.

日志管理工具

logrotate [选项]

选项

# 常用

-d, --debug # 调试模式,仅输出操作步骤,并不实际执行。隐式包含 -v 参数

-f, --force # 强制执行转储(logrotate 会根据状态文件, 自动判定是否有必要执行), 若配置文件刚修改完要马上执行建议使用该参数.

-s, --state=statefile # 使用指定的状态文件(而非默认的),对于运行在不同用户情况下有用

-v, --verbose # 显示转储过程的详细信息

# 不常用

-m, --mail=command # 发送邮件命令而不是用‘/bin/mail'发

文件

/etc/logrotate.conf # 默认配置文件

/var/lib/logrotate.status # 默认状态文件

默认配置文件 /etc/logrotate.conf 中一般会有一句 include /etc/logrotate.d 用于加载该目录下的所有配置文件.

可在

/etc/logrotate.d/ 下放置自定义的配置文件来自动调用.

默认的状态文件(记录每个处理的日志的最后时间?) /var/lib/logrotate.status

参考:

配置选项

默认读取的配置 /etc/logrotate.conf

# 触发方式 - 时间间隔

hourly

daily

weekly

monthly

# 触发方式 - 文件大小

size # 当日志文件到达指定的大小时才转储(例如 10(字节), 100k,4M, 1G

maxsize # 与时间间隔一同配置, 当日志文件超过该 maxsize 时, 即使未到指定时间间隔也会轮转

minsize # 与时间间隔一同配置, 若日志文件未超过该 minsize 时, 即使到达指定时间间隔也不会轮转.

# 对旧日志操作方式(默认策略应该是重命名原日志文件)

默认方式 # 修改日志文件名(实际是修改所属目录inode中的信息), 若该文件已被进程打开, 通常需要配置 postrotate 发送信号给该进程以重新打开日志文件.

copytruncate # 用于还在打开中的日志文件,把当前日志备份并截断,是先拷贝再清空的方式,拷贝和清空之间有一个时间差,可能会丢失部分日志数据

nocopytruncate # 备份日志文件但是不截断

# 压缩

compress # 压缩(gzip)日志文件的所有非当前版本

nocompress # (默认)不压缩

delaycompress # 本次转储的日志在下一次转储时才压缩.

nodelaycompress # (默认)不延迟压缩

# 邮件

mail # 转储的日志发送到指定邮箱

nomail # (默认)不发送转储的日志文件到邮箱

# 错误处理

errors # 转储时的错误信息发送到指定邮箱

missingok # 如果日志文件丢失,不要显示错误

# 空文件处理

notifempty # 如果日志文件为空,则不轮换日志文件(即忽略空文件).

ifempty # (默认)即使空文件也转储

# 存放目录

olddir # 转储后的日志放在指定目录下

noolddir # (默认)转储后的日志放在和当前日志文件同一个目录下

# 转储日志命名

dateext # 指定转储后的日志文件以当前日期为格式结尾,如 access.log-20200426.gz.

# 默认是以自增序号, 比如 messages -> messages.1 -> messages.2

dateformat # 配合dateext使用,紧跟在下一行出现,定义日期格式,只支持 %Y %m %d %H %s 这5个参数(%s 是时间戳)

# hourly 默认使用时间格式: -%Y%m%d%H

# daily,weekly,monthly 默认使用时间格式: -%Y%m%d

# 示例: dateformat -%Y%m%d%s

# 保留转储文件数量

rotate # 保留转储后的日志文件数量, 0指没有备份(轮转后马上删除旧日志), n指保留n个备份

# 创建新日志

create # 轮换原始文件并创建具有指定权限、用户和组的新文件, 示例: create 700 root root

nocreate # (默认)不主动创建新的日志文件

# 脚本

sharedscripts # 对于整个日志组只运行一次脚本

prerotate # 引入一个在日志被轮换前执行的脚本, 需要和 endscript 严格配置. 关键字必须单独一行.

postrotate # 引入一个在日志被轮换后执行的脚本, 需要和 endscript 严格配置. 关键字必须单独一行.

endscript # 标记 prerotate 或 postrotate 脚本的结束, 关键字必须单独一行.

示例

nginx 示例

/data/nginx/logs/*log {

daily

rotate 32

missingok

notifempty

compress

delaycomporess

dateext

sharedscripts

postrotate

/bin/kill -USR1 $(cat /var/run/nginx.pid 2>/dev/null) 2>/dev/null || :

endscript

}

轮转完后日志会从

/data/nginx/logs/access.log 变为

/data/nginx/logs/access.log-20200426.gz, 之类的日期是个示例.

可通过手动执行(指定配置文件)来调用:

logrotate /path/to/nginx_logrotate

日志轮转的机制

方案1:create

默认方案没有名字,姑且叫它create吧。因为这个方案会创建一个新的日志文件给程序输出日志,而且第二个方案名copytruncate是个配置项,与create配置项是互斥的。

这个方案的思路是重命名原日志文件,创建新的日志文件。详细步骤如下:

重命名程序当前正在输出日志的程序。因为重命名只会修改目录文件的内容,而进程操作文件靠的是inode编号,所以并不影响程序继续输出日志。

创建新的日志文件,文件名和原来日志文件一样。虽然新的日志文件和原来日志文件的名字一样,但是inode编号不一样,所以程序输出的日志还是往原日志文件输出。

通过某些方式通知程序,重新打开日志文件。程序重新打开日志文件,靠的是文件路径而不是inode编号,所以打开的是新的日志文件。

什么方式通知程序我重新打开日志呢,简单粗暴的方法是杀死进程重新打开。很多场景这种作法会影响在线的服务,于是有些程序提供了重新打开日志的接口,比如可以通过信号通知nginx。各种IPC方式都可以,前提是程序自身要支持这个功能。

有个地方值得一提,一个程序可能输出了多个需要滚动的日志文件。每滚动一个就通知程序重新打开所有日志文件不太划得来。有个sharedscripts的参数,让程序把所有日志都重命名了以后,只通知一次。

方案2:copytruncate

如果程序不支持重新打开日志的功能,又不能粗暴地重启程序,怎么滚动日志呢?copytruncate的方案出场了。

这个方案的思路是把正在输出的日志拷(copy)一份出来,再清空(trucate)原来的日志。详细步骤如下:

拷贝程序当前正在输出的日志文件,保存文件名为滚动结果文件名。这期间程序照常输出日志到原来的文件中,原来的文件名也没有变。

清空程序正在输出的日志文件。清空后程序输出的日志还是输出到这个日志文件中,因为清空文件只是把文件的内容删除了,文件的inode编号并没有发生变化,变化的是元信息中文件内容的信息。

结果上看,旧的日志内容存在滚动的文件里,新的日志输出到空的文件里。实现了日志的滚动。

这个方案有两个有趣的地方。

文件清空并不影响到输出日志的程序的文件表里的文件位置信息,因为各进程的文件表是独立的。那么文件清空后,程序输出的日志应该接着之前日志的偏移位置输出,这个位置之前会被\0填充才对。但实际上logroate清空日志文件后,程序输出的日志都是从文件开始处开始写的。这是怎么做到的?这个问题让我纠结了很久,直到某天灵光一闪,这不是logrotate做的,而是成熟的写日志的方式,都是用O_APPEND的方式写的。如果程序没有用O_APPEND方式打开日志文件,变会出现copytruncate后日志文件前面会被一堆\0填充的情况。

日志在拷贝完到清空文件这段时间内,程序输出的日志没有备份就清空了,这些日志不是丢了吗?是的,copytruncate有丢失部分日志内容的风险。所以能用create的方案就别用copytruncate。所以很多程序提供了通知我更新打开日志文件的功能来支持create方案,或者自己做了日志滚动,不依赖logrotate。

指定每日0点转储文件

方式1: 修改anacrontab调用 logrotate 的时机(极其不推荐, 会影响其他服务的调用时机)

方式2: crontab 手动定义配置文件(目前个人推荐)

创建配置文件 /etc/logrotate_daily0.confdateext

missingok

notifempty

include /etc/logrotate_daily0.d

创建目录 /etc/logrotate_daily0.d

主要不要使用默认目录, 否则会被正常的 logrotate 调度执行到

在上述目录下创建自己想要的配置文件

在 crontab 配置定时任务0 0 * * * /usr/sbin/logrotate /etc/logrotate_daily0.conf &> /dev/null

一键脚本

cat > /etc/logrotate_daily0.conf <> /var/spool/cron/root < /dev/null

EOF

crontab /var/spool/cron/root

cat > /etc/logrotate_daily0.d/nginx <

方式3: 手动指定每日 logrotate 的调用(不推荐, 会影响其他已配置的日志轮转)

移除默认定时配置mv /etc/cron.daily/logrotate /usr/local/bin/logrotate.sh

在 crontab 配置定时任务0 0 * * * /bin/bash /usr/local/bin/logrotate.sh

Ansi

这是一个用于生成 ANSI 转义序列的脚本, 可用于:

移动光标

文本加粗

添加颜色

...

下载并使用

wget https://raw.githubusercontent.com/fidian/ansi/master/ansi -O /usr/local/bin/ansi

chmod a+x /usr/local/bin/ansi

ansi -h

示例

# 红色字体, 加粗

ansi --bold --bg-red "请用 root 账户执行本脚本";

echo -n '['; ansi -n --bold --green "DONE"; echo ']';

echo -n '['; ansi --bold --red "ERROR"; echo ']';

8bcb418161b12fc4b749ab0c1bc3da4a.png

83bf3459d159f1cc231620dbe1e6f04c.png

expect

expect是一个自动化交互套件,主要应用于执行命令和程序时,系统以交互形式要求输入指定字符串,实现交互通信

相关链接:

安装

yum install -y expect

注意 expect 脚本开头一行是 #!/usr/bin/expect , 或者在执行时使用 expect 来执行脚本.

命令

set timeout

设置超时时间

# -1 表示不限制执行超时时间

set timeout -1

默认是 30s, 若执行会超过这个时间, 要注意设置"超时时间", 避免脚本被强行中断

set

定义变量

set 变量名 变量值

# set password "123456"

puts

输出变量

spanw

交互程序开始后面跟命令或者指定程序

spanw ssh xxx@x.x.x.x

expect "*password"

send "123456\n"

# 进入交互模式

interact

expect

语法

expect "文本匹配" 支持通配符匹配

expect eof 等待spawn的执行结束

expect "待匹配文本"

send "xxx\r"

expect "*支持通配符*"

send "xxx\r"

# 等价于上面两条, 更简洁

expect {

"待匹配的文本" { send "xxxx\r"; exp_continue }

"*支持通配符*" { send "xxx\r"}

}

# 等待 spawn 的脚本结束

expect eof

exp_continue

在expect中多次匹配就需要用到

expect {

"待匹配的文本" { send "xxxx\r"; exp_continue }

"*支持通配符*" { send "xxx\r"}

}

send

用于发送指定的字符串信息

expect "xxx"

send "xxx\r"

send_user

用来打印输出 相当于shell中的echo

send_user "echo something"

exit

interact

进入交互模式

关键字

if

流程控制

if { ... } {

# ...

}

lindex

获取数组的第N个参数

# 使用 lindex 关键字获取第N个参数

set 变量名 [lindex $argv 0]

set 变量名 [lindex $argv 1]

...

# 参数总数

if {$argc < 1} {

send_user "..."

exit

}

file

示例

示例: 一个 expect 脚本的模板

#!/usr/bin/expect

set PASSWORD "ssh密码"

if {$argc < 1} {

send_user "usage: $argv0 \n"

exit

}

set srcdir [lindex $argv 0]

if {[file isdirectory "$srcdir"] != 1} {

send_user "not exists dir: $srcdir\n"

exit

}

spawn bash deploy.sh $srcdir

# 这是一个自动输入 ssh 密码的应答

expect {

"yes/no" { send "yes\n"; exp_continue }

"password:" { send "${PASSWORD}\n" }

}

expect eof

上面是一个在不使用秘钥情况下完成 rsync 免手动输入密码的处理.

示例: 自动输入 mysql 密码

#!/usr/bin/expect

set password xxxx

set name root

spawn mysql -u $name -p

expect "*password:*"

send "$password\r"

interact

示例: 在 shell 中嵌套 expect

#!/bin/bash

for i in `cat /home/admin/timeout_login.txt`

do

/usr/bin/expect << EOF

spawn /usr/bin/ssh -t -p 22022 admin@$i "sudo su -"

expect {

"yes/no" { send "yes\r" }

}

expect {

"password:" { send "xxo1#qaz\r" }

}

expect {

"*password*:" { send "xx1#qaz\r" }

}

expect "*]#"

send "df -Th\r"

expect "*]#"

send "exit\r"

expect eof

EOF

done

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值