乐趣区

关于linux:⭐Linux实战技能100讲个人笔记-7-其他工具

[TOC]

Logrotate 日志管理工具

logrotate 是一个 Linux 零碎默认装置了的日志文件管理工具,用来把旧文件轮转、压缩、删除,并且创立新的日志文件。咱们能够依据日志文件的大小、天数等来转储,便于对日志文件治理。

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

具体调用流程剖析能够见 4. Shell 篇.md#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

参考:

  • https://www.linuxprobe.com/co…
  • https://www.cnblogs.com/wushu…

配置选项

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

# 触发形式 - 工夫距离
hourly
daily
weekly
monthly             

# 触发形式 - 文件大小
size <logsize>                   # 当日志文件达到指定的大小时才转储(例如 10(字节), 100k,4M, 1G
maxsize <size>                    # 与工夫距离一起配置, 当日志文件超过该 maxsize 时, 即便未到指定工夫距离也会轮转
minsize <size>                    # 与工夫距离一起配置, 若日志文件未超过该 minsize 时, 即便达到指定工夫距离也不会轮转.

# 对旧日志操作形式(默认策略应该是重命名原日志文件)
默认形式                         # 批改日志文件名(理论是批改所属目录 inode 中的信息), 若该文件已被过程关上, 通常须要配置 postrotate 发送信号给该过程以从新关上日志文件.
copytruncate                    # 用于还在关上中的日志文件,把以后日志备份并截断,是先拷贝再清空的形式,拷贝和清空之间有一个时间差,可能会失落局部日志数据
nocopytruncate                    # 备份日志文件然而不截断

# 压缩
compress                         # 压缩 (gzip) 日志文件的所有非以后版本
nocompress                        # (默认)不压缩
delaycompress                    # 本次转储的日志在下一次转储时才压缩.
nodelaycompress                    # (默认)不提早压缩

# 邮件
mail <mail>                           # 转储的日志发送到指定邮箱
nomail                            # (默认)不发送转储的日志文件到邮箱

# 错误处理
errors <mail>                      # 转储时的错误信息发送到指定邮箱
missingok                        # 如果日志文件失落,不要显示谬误

# 空文件解决
notifempty                       # 如果日志文件为空,则不轮换日志文件(即疏忽空文件).
ifempty                            # (默认)即便空文件也转储

# 寄存目录
olddir <dir>                     # 转储后的日志放在指定目录下
noolddir                        # (默认)转储后的日志放在和以后日志文件同一个目录下

# 转储日志命名
dateext                            # 指定转储后的日志文件以以后日期为格局结尾,如 access.log-20200426.gz. 
                                # 默认是以自增序号, 比方 messages -> messages.1 -> messages.2
dateformat <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 <n>                       # 保留转储后的日志文件数量, 0 指没有备份(轮转后马上删除旧日志), n 指保留 n 个备份

# 创立新日志
create <mode> <user> <group>    # 轮换原始文件并创立具备指定权限、用户和组的新文件, 示例: 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

日志轮转的机制

此处不探讨压缩等的后续操作.

该局部内容来自: https://www.lightxue.com/how-…

若 inode 局部不了解, 可查看原文链接或查看笔记 3. 系统管理篇.md# 文件、目录与 inode(i 节点))

计划 1:create

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

这个计划的思路是重命名原日志文件,创立新的日志文件。具体步骤如下:

  1. 重命名程序以后正在输入日志的程序。因为重命名只会批改目录文件的内容,而过程操作文件靠的是 inode 编号,所以并不影响程序持续输入日志。
  2. 创立新的日志文件,文件名和原来日志文件一样。尽管新的日志文件和原来日志文件的名字一样,然而 inode 编号不一样,所以程序输入的日志还是往原日志文件输入。
  3. 通过某些形式告诉程序,从新关上日志文件。程序从新关上日志文件,靠的是文件门路而不是 inode 编号,所以关上的是新的日志文件。

什么形式告诉程序我从新关上日志呢,简略粗犷的办法是杀死过程从新关上。很多场景这种作法会影响在线的服务,于是有些程序提供了从新关上日志的接口,比方能够通过信号告诉 nginx。各种 IPC 形式都能够,前提是程序本身要反对这个性能。

有个中央值得一提,一个程序可能输入了多个须要滚动的日志文件。每滚动一个就告诉程序从新关上所有日志文件不太划得来。有个 sharedscripts 的参数,让程序把所有日志都重命名了当前,只告诉一次。

计划 2:copytruncate

如果程序不反对从新关上日志的性能,又不能粗犷地重启程序,怎么滚动日志呢?copytruncate 的计划出场了。

这个计划的思路是把正在输入的日志拷 (copy) 一份进去,再清空 (trucate) 原来的日志。具体步骤如下:

  1. 拷贝程序以后正在输入的日志文件,保留文件名为滚动后果文件名。这期间程序照常输入日志到原来的文件中,原来的文件名也没有变。
  2. 清空程序正在输入的日志文件。清空后程序输入的日志还是输入到这个日志文件中,因为清空文件只是把文件的内容删除了,文件的 inode 编号并没有发生变化,变动的是元信息中文件内容的信息。

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

这个计划有两个乏味的中央。

  1. 文件清空并不影响到输入日志的程序的文件表里的文件地位信息,因为各过程的文件表是独立的。那么文件清空后,程序输入的日志应该接着之前日志的偏移地位输入,这个地位之前会被 \0 填充才对。但实际上 logroate 清空日志文件后,程序输入的日志都是从文件开始处开始写的。这是怎么做到的?这个问题让我纠结了很久,直到某天灵光一闪,这不是 logrotate 做的,而是成熟的写日志的形式,都是用 O_APPEND 的形式写的。如果程序没有用 O_APPEND 形式关上日志文件,变会呈现 copytruncate 后日志文件后面会被一堆 \0 填充的状况。
  2. 日志在拷贝完到清空文件这段时间内,程序输入的日志没有备份就清空了,这些日志不是丢了吗?是的,copytruncate 有失落局部日志内容的危险。所以能用 create 的计划就别用 copytruncate。所以很多程序提供了告诉我更新关上日志文件的性能来反对 create 计划,或者本人做了日志滚动,不依赖 logrotate。

指定每日 0 点转储文件

形式 1: 批改 anacrontab 调用 logrotate 的机会(极其不举荐, 会影响其余服务的调用机会)

形式 2: crontab 手动定义配置文件(目前集体举荐)

  1. 创立配置文件 /etc/logrotate_daily0.conf

    dateext
    missingok
    notifempty
    
    include /etc/logrotate_daily0.d
  2. 创立目录 /etc/logrotate_daily0.d

    次要不要应用默认目录, 否则会被失常的 logrotate 调度执行到

  3. 在上述目录下创立本人想要的配置文件
  4. 在 crontab 配置定时工作

    0 0 * * * /usr/sbin/logrotate /etc/logrotate_daily0.conf &> /dev/null

一键脚本

cat > /etc/logrotate_daily0.conf <<'EOF'
dateext
rotate 7
missingok
notifempty

include /etc/logrotate_daily0.d
EOF

mkdir /etc/logrotate_daily0.d

cat >> /var/spool/cron/root <<'EOF'

# 0 点执行日志轮转
0 0 * * * /usr/sbin/logrotate -f /etc/logrotate_daily0.conf &> /dev/null
EOF

crontab /var/spool/cron/root

cat > /etc/logrotate_daily0.d/nginx <<'EOF'
/data/nginx/logs/*.log {
   missingok
   notifempty
   daily
   compress
   dateext
   nocreate
   rotate 31
   sharedscripts
   postrotate
        /bin/kill -USR1 $(ps -ef|grep nginx|grep master|grep -v grep|awk '{print $2}') || true
   endscript
}
EOF

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

  1. 移除默认定时配置

    mv /etc/cron.daily/logrotate /usr/local/bin/logrotate.sh
  2. 在 crontab 配置定时工作

    0 0 * * * /bin/bash /usr/local/bin/logrotate.sh

Ansi

https://github.com/fidian/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 ']';

expect

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

https://wxnacy.com/2018/05/31…

示例

示例: 一个 expect 脚本的模板

#!/usr/bin/expect

set PASSWORD "ssh 明码"

if {$argc < 1} {
    send_user "usage: $argv0 <dir>\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
退出移动版