日志切割,日志轮转

日志切割,日志轮转

>shell输出重定向到目标文件,修改文件名后不会将信息继续写入文件的解决办法


问题:

如果某个脚本将输出信息重定向到文件A,无论是mv A B 还是rm -f A,脚本后续的输出都不会自动创建一个A脚本并且将输出输入其中。


可以使用linux自带的logrotate , 或者下面的方法

举例:

* test.sh文件内容

#!/bin/sh
while :
do
  sleep 1
  echo $(date +%Y-%m-%d %H:%M:%S)
done

* 执行下面代码

./test.sh > a.txt &
#并不会重新生成一个a.txt,而是将结果继续输出到b.txt中
mv a.txt b.txt
#不执行上面的mv,直接删除文件也不会重新生成一个a.txt
rm -f a.txt


* 正确的操作应该是

#将./test.sh > a.txt & 改为 ./test.sh >> a.txt & 
#将a.txt的内容追加到b.txt中
cat a.txt >> b.txt
#清空a.txt
#注意这种方式清空,脚本日志重定向的时候要>> 不要> ,>不会重置文件大小 例如nohup ./a.sh > b & 改成 nohup ./a.sh >> b &
cat /dev/null > a.txt


___ 

下面举一个例子,将程序输出的日志按分钟和按天分割

#!/bin/sh
#脚本主要是将日志分割成天和分钟
LOG_ROOT=$GOPATH/src/github.com/Terry-Mao/goim/logs
TARGET_ROOT=$GOPATH/src/github.com/Terry-Mao/goim/target
#存放文件的路径
log_path_all=(
$LOG_ROOT/logic_log
$LOG_ROOT/logic_log/day
$LOG_ROOT/comet_log
$LOG_ROOT/comet_log/day
$LOG_ROOT/job_log
$LOG_ROOT/job_log/day
)
#创建目录
# shellcheck disable=SC2068
for log_path in ${log_path_all[@]};do
  if [ ! -d $log_path ] ; \
  then \
    mkdir -p $log_path ; \
  fi;
done
server_all=(
comet
logic
job
)
while :
do
  #这里必须一分钟执行一次,否则天数据里面的内容会重复
  sleep 60
  # shellcheck disable=SC2068
  for server in ${server_all[@]};do
    #这里用追加的形式,是因为集群可能多个docker容器对应同一个日志目录,防止日志丢失
    cat $TARGET_ROOT/${server}.log >> $LOG_ROOT/${server}_log/${server}_$(date +%Y%m%d%H%M).log
    #清空旧日志,这里不能用删除,删除或者mv后,不会产生新文件
    cat /dev/null > $TARGET_ROOT/${server}.log
    #将每分钟的日志汇入每日日志
    cat $LOG_ROOT/${server}_log/${server}_$(date -d "-1 minute" +"%Y%m%d%H%M").log >> $LOG_ROOT/${server}_log/day/${server}_$(date +%Y%m%d).log
    #删除10分钟以前的分钟日志
    rm -f $LOG_ROOT/${server}_log/${server}_$(date -d "-10 minute" +"%Y%m%d%H%M").log
  done
done