shell 判断文件夹或文件是否存在

文件夹不存在则创建

if [ ! -d "/data/" ];then
  mkdir /data
  else
  echo "文件夹已经存在"
fi

文件存在则删除

if [ ! -f "/data/filename" ];then
  echo "文件不存在"
  else
  rm -f /data/filename
fi

判断文件夹是否存在

if [ -d "/data/" ];then
  echo "文件夹存在"
  else
  echo "文件夹不存在"
fi

判断文件是否存在

if [ -f "/data/filename" ];then
  echo "文件存在"
  else
  echo "文件不存在"
fi

文件比较符

-e 判断对象是否存在
-d 判断对象是否存在,并且为目录
-f 判断对象是否存在,并且为常规文件
-L 判断对象是否存在,并且为符号链接
-h 判断对象是否存在,并且为软链接
-s 判断对象是否存在,并且长度不为0
-r 判断对象是否存在,并且可读
-w 判断对象是否存在,并且可写
-x 判断对象是否存在,并且可执行
-O 判断对象是否存在,并且属于当前用户
-G 判断对象是否存在,并且属于当前用户组
-nt 判断file1是否比file2新  [ "/data/file1" -nt "/data/file2" ]
-ot 判断file1是否比file2旧  [ "/data/file1" -ot "/data/file2" ]

一个简单的shell判断

echo "hello world" > /tmp/helloworld.txt
if [ $? -ne 0 ]; then
echo " failed"
exit 1
else
echo "successed"
fi

作用:

判断上一句执行的结果,如果为0,返回“successed”,如果不为0,返回“failed”

一个简单的shell循环

#!/bin/env bash
CODEPATH=/opt/code/
JARPATH=/opt/jar
set -xe
find  ${CODEPATH} -type f -name "*.jar" | tee jar.cache.txt
for line in $(cat jar.cache.txt)
do
        cp ${line} ${JARPATH}
done
rm jar.cache.txt


作用:

循环查找/opt/code下的jar包,推送到/opt/jar目录下

for line一句,逐行读取jar.cache.txt,并执行

linux awk sed grep的用法

正则表达式基础知识

正则表达式:

是一套规则与方法,以行为基础工作单位

BRE(基本正则表达式)集合

元字符:^[].*$

作用:匹配字符,匹配位置,锚定位置

^:用于模式的最左侧,^start,表示以start开头的行
$:用于模式的最右行,end$,表示以end结尾的行
^$:用于表示空行
.:匹配任意一个且只有一个字符
*:匹配前一个字符,包含零次,可以理解为匹配所有内容
.*:匹配所有内容,除了空行
\:转义符,特殊符号需要保持字符串格式,需要转义
^.*:匹配任何字符开头(包括数量任意,内容任意,非空行)
.*$:匹配以任何字符结尾(包括数量任意,内容任意,非空行)
[]:匹配方括号内的内容,如[abc]表示匹配a或者b或者c,等价表达式[a-c],注:字母表中连续的字母序列或者连续的数字
[^]:取反,[^abc]匹配除了a、b、c之外的字符

ERD(扩展正则表达式)集合
使用grep -E生效
+:表示匹配前一个字符一次或者多次
[]+:表示匹配中括号中的内容一次或者多次
?:匹配前一个字符0次或者1次
|:“或”,表示同时匹配管道符前后的内容
():分组过滤,表示将()中的内容作为一个整体
a{n,m}:表示匹配a最少n次,最大m次
a{n,}:表示匹配a最少n次
a{n}:表示匹配a正好n次
a{,m}:表示匹配a最大m次

简述三剑客的作用

awk擅长取列;

sed擅长取行和替换;

grep擅长查找功能,比如可以根据关键字查询对应的日志。

三剑客使用介绍

grep是从文本文件或者数据流匹配文本行或者数据

grep [选项] 查找内容 [源文件]
观察其组成结构,由四部分组成:指令名(grep)、选项、查找内容、源文件,其中需要注意的有两个位置,下面让我们徐徐道来。

源文件
源文件部分是可有可无的,若不指定任何文件名称或是所给予的文件名为-,则grep指令会从标准输入设备读取数据,其使用如下所示:

// 文件路径为/test

// 接收cat的输入
cat ./test |grep 'hello'

// 存在路径部分参数
grep 'hello' ./test
选项部分
选项部分比较多,可以通过grep --help指令来看一下有哪些选项:

Regexp selection and interpretation: // 正则表达式选择和解释
-E, --extended-regexp PATTERN is an extended regular expression (ERE)
-F, --fixed-strings PATTERN is a set of newline-separated strings
-G, --basic-regexp PATTERN is a basic regular expression (BRE)
-P, --perl-regexp PATTERN is a Perl regular expression
-e, --regexp=PATTERN use PATTERN for matching
-f, --file=FILE obtain PATTERN from FILE
-i, --ignore-case ignore case distinctions
-w, --word-regexp force PATTERN to match only whole words
-x, --line-regexp force PATTERN to match only whole lines
-z, --null-data a data line ends in 0 byte, not newline

Miscellaneous: // 各种各样的
-s, --no-messages suppress error messages
-v, --invert-match select non-matching lines // 搜索不匹配的行
-V, --version display version information and exit
--help display this help text and exit

Output control: // 输出控制
-m, --max-count=NUM stop after NUM matches
-b, --byte-offset print the byte offset with output lines
-n, --line-number print line number with output lines
--line-buffered flush output on every line
-H, --with-filename print the file name for each match
-h, --no-filename suppress the file name prefix on output
--label=LABEL use LABEL as the standard input file name prefix
-o, --only-matching show only the part of a line matching PATTERN
-q, --quiet, --silent suppress all normal output
--binary-files=TYPE assume that binary files are TYPE;
TYPE is 'binary', 'text', or 'without-match'
-a, --text equivalent to --binary-files=text
-I equivalent to --binary-files=without-match
-d, --directories=ACTION how to handle directories;
ACTION is 'read', 'recurse', or 'skip'
-D, --devices=ACTION how to handle devices, FIFOs and sockets;
ACTION is 'read' or 'skip'
-r, --recursive like --directories=recurse
-R, --dereference-recursive likewise, but follow all symlinks
--include=FILE_PATTERN search only files that match FILE_PATTERN
--exclude=FILE_PATTERN skip files and directories matching FILE_PATTERN
--exclude-from=FILE skip files matching any file pattern from FILE
--exclude-dir=PATTERN directories that match PATTERN will be skipped.
-L, --files-without-match print only names of FILEs containing no match
-l, --files-with-matches print only names of FILEs containing matches
-c, --count print only a count of matching lines per FILE
-T, --initial-tab make tabs line up (if needed)
-Z, --null print 0 byte after FILE name

Context control: // 上下文控制
-B, --before-context=NUM print NUM lines of leading context
-A, --after-context=NUM print NUM lines of trailing context
-C, --context=NUM print NUM lines of output context
-NUM same as --context=NUM
--color[=WHEN],
--colour[=WHEN] use markers to highlight the matching strings;
WHEN is 'always', 'never', or 'auto'
-U, --binary do not strip CR characters at EOL (MSDOS/Windows)
-u, --unix-byte-offsets report offsets as if CRs were not there
看着选项内容真的很多,背起来着实不易,幸好文档中给我们做了分类,只需要记住这些分类是干什么的,然后在需要的时候从里面进行搜索即可快速搜寻到所需用法(感觉看其内容比看菜鸟教程上的内容容易很多)

(1)当需要通过正则的方式进行搜索内容时,去"Regexp selection and interpretation"区块找选项即可,常用的有:

-E:通过正则表达式进行搜索
(2)当需要对输出的内容进行控制时,去"Output control"区块找选项即可,常用的有如下几个:

-m 数量:表征匹配多少次就会停止
-n:显示匹配行及行号
-H:打印每一个匹配的文件名
-r:能够递归查询,即可以输入文件夹查询
-c:统计匹配到行的个数
(3)当需要获取输出内容的上下文进行操纵时,去"Context control"区块找选项即可,常用的有如下几个:

-B 数量、-A 数量、-C 数量:分别表征获取内容前、后、前后几行
--color:对输出的内容添加颜色
(4)除了一些划分比较理解的选项,还有一些选项我个人认为划分的并不是很合理,但是它们仍然很重要,让我们一起来看看有哪些:

-i:忽略字母大小写
-v:反向选择,也就是显示出没有搜索出字符串内容的那一行
二、经典用法
上面已经将其基本使用做了详细的阐述,俗话说的好:光说不练假把式,光练不说真把式,连说带练全把式。既然上面阐述了一通理论的东西,下面我们就来实战几个常用场景,将理论付诸于实践。在实战之前先创建一个文件,文件名是test,文件内容如下所示:

hello world!!!
dog
cat
pig
big pig
tiger
Elephant
从确定文件中过滤出包含pig的

$ grep 'pig' ./test
pig
big pig
从包含某一部分内容的文件中过滤包含pig的

$ grep 'pig' ./te*
pig
big pig
从某一文件夹下所有内容中过滤出包含pig的

$ grep -r 'pig' .
./test:pig
./test:big pig
从某一文件中过滤出不包含pig的

$ grep -v 'pig' ./test
hello world!!!
dog
cat
tiger
Elephant
在过滤文件时显示行数

$ grep -n 'pig' ./test
4:pig
5:big pig
匹配出以开头的内容(通过基本正则表达式匹配即可,基本正则表达式字符有^$.[]*)

$ grep ^p ./test
pig
匹配出包含pig或cat内容的行(用到了扩展正则表达式,其在基本正则表达式基础上增加了(){}?+|等)

$ grep -E 'pig|cat' ./test
cat
pig
big pig
匹配出包含hello和world内容的行

$ grep 'hello' ./test |grep 'world'
hello world!!!
获取到匹配内容‘big pig'的前一行内容

$ grep -B1 'big pig' ./test
pig
big pig
获取匹配到'pig'行的数量

$ grep -c 'pig' ./test
获取到的pig行的内容高亮显示

$ grep --color 'pig' ./test
pig
big pig

sed是一个流编辑器

一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有 改变,除非你使用重定向存储输出。Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等

sed --help
Usage: sed [OPTION]... {script-only-if-no-other-script} [input-file]...

  -n, --quiet, --silent
                 suppress automatic printing of pattern space
      --debug
                 annotate program execution
  -e script, --expression=script
                 add the script to the commands to be executed
  -f script-file, --file=script-file
                 add the contents of script-file to the commands to be executed
  --follow-symlinks
                 follow symlinks when processing in place
  -i[SUFFIX], --in-place[=SUFFIX]
                 edit files in place (makes backup if SUFFIX supplied)
  -l N, --line-length=N
                 specify the desired line-wrap length for the `l' command
  --posix
                 disable all GNU extensions.
  -E, -r, --regexp-extended
                 use extended regular expressions in the script
                 (for portability use POSIX -E).
  -s, --separate
                 consider files as separate rather than as a single,
                 continuous long stream.
      --sandbox
                 operate in sandbox mode (disable e/r/w commands).
  -u, --unbuffered
                 load minimal amounts of data from the input files and flush
                 the output buffers more often
  -z, --null-data
                 separate lines by NUL characters
      --help     display this help and exit
      --version  output version information and exit

If no -e, --expression, -f, or --file option is given, then the first
non-option argument is taken as the sed script to interpret.  All
remaining arguments are names of input files; if no input files are
specified, then the standard input is read.

动作说明:
a :新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)~
c :取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行!
d :删除,因为是删除啊,所以 d 后面通常不接任何咚咚;
i :插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行);
p :列印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行~
s :取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正规表示法!

sed匹配范围:
空地址:全文匹配,即逐行操作
单地址:指定行匹配
/.../:被模式匹配的每一行
区间范围:10,20是第十行到第二十行;10,+5,表示第十行向下五行;/.../,/.../也可多个模式一起结合匹配。
步长:1~2,表示从1开始,步长为2

实现功能:
1.提取,打印:
sed -n '匹配模式p' 文件名,如sed -n '1,2p' passwd.txt,显示第一至第二行。
2.过滤
sed -n '匹配模式p' 文件名,如sed -n '/^system/p' passwd.txt,显示已system开头的行

awk是一个处理文本的编程语言工具

能用简短的程序处理标准输入、文件、数据排序、计算以及生成报表等。

也是按行处理,默认分隔符是“ ”

awk基本命令

 awk -h
Usage: awk [POSIX or GNU style options] -f progfile [--] file ...
Usage: awk [POSIX or GNU style options] [--] 'program' file ...
POSIX options:          GNU long options: (standard)
        -f progfile             --file=progfile
        -F fs                   --field-separator=fs
        -v var=val              --assign=var=val
Short options:          GNU long options: (extensions)
        -b                      --characters-as-bytes
        -c                      --traditional
        -C                      --copyright
        -d[file]                --dump-variables[=file]
        -D[file]                --debug[=file]
        -e 'program-text'       --source='program-text'
        -E file                 --exec=file
        -g                      --gen-pot
        -h                      --help
        -i includefile          --include=includefile
        -l library              --load=library
        -L[fatal|invalid]       --lint[=fatal|invalid]
        -M                      --bignum
        -N                      --use-lc-numeric
        -n                      --non-decimal-data
        -o[file]                --pretty-print[=file]
        -O                      --optimize
        -p[file]                --profile[=file]
        -P                      --posix
        -r                      --re-interval
        -S                      --sandbox
        -t                      --lint-old
        -V                      --version

To report bugs, see node `Bugs' in `gawk.info', which is
section `Reporting Problems and Bugs' in the printed version.

gawk is a pattern scanning and processing language.
By default it reads standard input and writes standard output.

Examples:
        gawk '{ sum += $1 }; END { print sum }' file
        gawk -F: '{ print $1 }' /etc/passwd
$0 代表一整行数据
$1代表第一列
$NF代表最后一列,$(NF-1)倒数第二列

linux tee的用法

tee命令用于将标准输入复制到每个指定文件,并显示到标准输出。tee指令会从标准输入设备读取数据,将其内容输出到标准输出设备,同时保存成文件。

  • 基本参数
tee --help

Usage: tee [OPTION]... [FILE]...
Copy standard input to each FILE, and also to standard output.

  -a, --append              append to the given FILEs, do not overwrite
  -i, --ignore-interrupts   ignore interrupt signals
  -p                        diagnose errors writing to non pipes
      --output-error[=MODE]   set behavior on write error.  See MODE below
      --help     display this help and exit
      --version  output version information and exit

MODE determines behavior with write errors on the outputs:
  'warn'         diagnose errors writing to any output
  'warn-nopipe'  diagnose errors writing to any output not a pipe
  'exit'         exit on error writing to any output
  'exit-nopipe'  exit on error writing to any output not a pipe
The default MODE for the -p option is 'warn-nopipe'.
The default operation when --output-error is not specified, is to
exit immediately on error writing to a pipe, and diagnose errors
writing to non pipe outputs.
  • 将屏幕输出同时输出到文件:
ping www.baidu.com | tee pingbaidu.log
PING www.wshifen.com (103.235.46.40) 56(84) bytes of data.
64 bytes from 103.235.46.40 (103.235.46.40): icmp_seq=1 ttl=55 time=3.79 ms
64 bytes from 103.235.46.40 (103.235.46.40): icmp_seq=2 ttl=55 time=3.87 ms
......
cat pingbaidu.com
PING www.wshifen.com (103.235.46.40) 56(84) bytes of data.
64 bytes from 103.235.46.40 (103.235.46.40): icmp_seq=1 ttl=55 time=3.79 ms
64 bytes from 103.235.46.40 (103.235.46.40): icmp_seq=2 ttl=55 time=3.87 ms
......
  • 追加到输出文件
ping www.sina.com | tee -a pingbaidu.log
PING ww1.sinaimg.cn.w.alikunlun.com (47.246.16.231) 56(84) bytes of data.
64 bytes from 47.246.16.231 (47.246.16.231): icmp_seq=1 ttl=57 time=2.15 ms
64 bytes from 47.246.16.231 (47.246.16.231): icmp_seq=2 ttl=57 time=5.42 ms
......
cat pingbaidu.log  
PING www.wshifen.com (103.235.46.40) 56(84) bytes of data.
64 bytes from 103.235.46.40 (103.235.46.40): icmp_seq=1 ttl=55 time=3.79 ms
64 bytes from 103.235.46.40 (103.235.46.40): icmp_seq=2 ttl=55 time=3.87 ms
64 bytes from 103.235.46.40 (103.235.46.40): icmp_seq=3 ttl=55 time=4.62 ms
64 bytes from 103.235.46.40 (103.235.46.40): icmp_seq=4 ttl=55 time=3.77 ms
PING ww1.sinaimg.cn.w.alikunlun.com (47.246.16.231) 56(84) bytes of data.
64 bytes from 47.246.16.231 (47.246.16.231): icmp_seq=1 ttl=57 time=2.15 ms
64 bytes from 47.246.16.231 (47.246.16.231): icmp_seq=2 ttl=57 time=5.42 ms
64 bytes from 47.246.16.231 (47.246.16.231): icmp_seq=3 ttl=57 time=2.16 ms
......
  • 将内容输出到多个文件,我们直接在tee命令后面直接添加对应的文件
ping www.baidu.com | tee pingbaidu.log ping.log
PING www.wshifen.com (183.232.231.172) 56(84) bytes of data.
64 bytes from 183.232.231.172: icmp_seq=1 ttl=46 time=21.2 ms
64 bytes from 183.232.231.172: icmp_seq=2 ttl=46 time=19.4 ms
64 bytes from 183.232.231.172: icmp_seq=3 ttl=46 time=19.4 ms
64 bytes from 183.232.231.172: icmp_seq=4 ttl=46 time=20.5 ms
......

cat pingbaidu.log 
PING www.wshifen.com (183.232.231.172) 56(84) bytes of data.
64 bytes from 183.232.231.172: icmp_seq=1 ttl=46 time=21.2 ms
64 bytes from 183.232.231.172: icmp_seq=2 ttl=46 time=19.4 ms
64 bytes from 183.232.231.172: icmp_seq=3 ttl=46 time=19.4 ms
64 bytes from 183.232.231.172: icmp_seq=4 ttl=46 time=20.5 ms
......

cat ping.log 
ING www.wshifen.com (183.232.231.172) 56(84) bytes of data.
64 bytes from 183.232.231.172: icmp_seq=1 ttl=46 time=21.2 ms
64 bytes from 183.232.231.172: icmp_seq=2 ttl=46 time=19.4 ms
64 bytes from 183.232.231.172: icmp_seq=3 ttl=46 time=19.4 ms
64 bytes from 183.232.231.172: icmp_seq=4 ttl=46 time=20.5 ms
  • 忽略中断事件,这个时候我们可以使用-i参数
$ ping www.baidu.com | tee -i pingbaidu.log ping.log
PING www.wshifen.com (183.232.231.172) 56(84) bytes of data.
64 bytes from 183.232.231.172: icmp_seq=1 ttl=46 time=20.4 ms
64 bytes from 183.232.231.172: icmp_seq=2 ttl=46 time=19.6 ms
64 bytes from 183.232.231.172: icmp_seq=3 ttl=46 time=19.9 ms
64 bytes from 183.232.231.172: icmp_seq=4 ttl=46 time=19.3 ms
^C
--- www.wshifen.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 19.311/19.842/20.465/0.450 ms

......

cat pingbaidu.log 
PING www.wshifen.com (183.232.231.172) 56(84) bytes of data.
64 bytes from 183.232.231.172: icmp_seq=1 ttl=46 time=20.4 ms
64 bytes from 183.232.231.172: icmp_seq=2 ttl=46 time=19.6 ms
64 bytes from 183.232.231.172: icmp_seq=3 ttl=46 time=19.9 ms
64 bytes from 183.232.231.172: icmp_seq=4 ttl=46 time=19.3 ms

--- www.wshifen.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 19.311/19.842/20.465/0.450 ms

删除文件

删除文件命令:

find 对应目录 -mtime +天数 -name "文件名" -exec rm -rf {} \;

实例命令:

find /opt/soft/log/ -mtime +30 -name "*.log" -exec rm -rf {} \;

说明:

将/opt/soft/log/目录下所有30天前带".log"的文件删除。具体参数说明如下:

find:linux的查找命令,用户查找指定条件的文件;

/opt/soft/log/:想要进行清理的任意目录;

-mtime:标准语句写法;

+30:查找30天前的文件,这里用数字代表天数;

"*.log":希望查找的数据类型,"*.jpg"表示查找扩展名为jpg的所有文件,"*"表示查找所有文件,这个可以灵活运用,举一反三;

-exec:固定写法;

rm -rf:强制删除文件,包括目录;

{} \; :固定写法,一对大括号+空格+\+; 

LINUX shell 获取日期并格式化

#!/bin/sh

# upload logs to hdfs

source /etc/profile

#获取昨天日期 yyyyMMdd 格式

yesterday=`date --date='1 days ago' +%Y%m%d`

#获取昨天日期 yyyy-MM-dd 格式

yesterday2=`date --date='1 days ago' +%Y-%m-%d`

#获取今天日期 yyyyMMdd 格式

today=`date --date='0 days ago' +%Y%m%d`

#获取今天日期 yyyy-MM-dd 格式

today2=`date --date='0 days ago' +%Y-%m-%d`

#获取明天日期 yyyyMMdd 格式

today=`date --date='1 days' +%Y%m%d`

#获取明天日期 yyyy-MM-dd 格式

today2=`date --date='1 days' +%Y-%m-%d`

#获取当前时间 yyyy-MM-dd HH:mm:ss 格式

nowtime=`date --date='0 days ago' "+%Y-%m-%d %H:%M:%S"`

#获取当前日间 HH:mm:ss 格式

nowtime2=`date --date='0 days ago' +%H:%M:%S`

#获取1小时前时间 yyyy-MM-dd HH:mm:ss 格式

onehourage=`date --date='1 hours ago' "+%Y-%m-%d %H:%M:%S"`

#获取1小时后时间 yyyy-MM-dd HH:mm:ss 格式

onehourage2=`date --date='1 hours' "+%Y-%m-%d %H:%M:%S"`

#获取2小时前时间 yyyy-MM-dd HH:mm:ss 格式

twohourage=`date --date='2 hours ago' "+%Y-%m-%d %H:%M:%S"`

#获取2小时后时间 yyyy-MM-dd HH:mm:ss 格式

twohourage2=`date --date='2 hours' "+%Y-%m-%d %H:%M:%S"`

#获取1个月前时间 yyyy-MM-dd HH:mm:ss 格式

date --date='1 month ago' "+%Y-%m-%d %H:%M:%S"

#获取1个月加1天前时间 yyyy-MM-dd HH:mm:ss 格式

date --date='1 month ago + 1 day ago' "+%Y-%m-%d %H:%M:%S"

#获取1个月减1天前时间 yyyy-MM-dd HH:mm:ss 格式

date --date='1 month ago - 1 day ago' "+%Y-%m-%d %H:%M:%S"

#获取1个月加1天加1小时加1分钟加1秒钟前时间 yyyy-MM-dd HH:mm:ss 格式

date --date='1 month ago + 1 day ago + 1 hour ago + 1 min ago + 1 sec ago' "+%Y-%m-%d %H:%M:%S"

#获取1个月加1天减1小时减1分钟减1秒钟前时间 yyyy-MM-dd HH:mm:ss 格式  可以 + - 滥用

date --date='1 month ago + 1 day ago - 1 hour ago - 1 min ago - 1 sec ago' "+%Y-%m-%d %H:%M:%S"

#获取1个月加1天加1小时加1分钟加1秒钟后时间 yyyy-MM-dd HH:mm:ss 格式

date --date='1 month + 1 day  + 1 hour  + 1 min  + 1 sec ' "+%Y-%m-%d %H:%M:%S"

#获取1个月加1天减1小时减1分钟减1秒钟后时间 yyyy-MM-dd HH:mm:ss 格式

date --date='1 month + 1 day  - 1 hour  - 1 min  - 1 sec ' "+%Y-%m-%d %H:%M:%S"

#获取1年后1个月加1天减1小时减1分钟减1秒钟后时间 yyyy-MM-dd HH:mm:ss 格式

date --date='1 year 1 month + 1 day  - 1 hour  - 1 min  - 1 sec ' "+%Y-%m-%d %H:%M:%S"

#获取1年前1个月加1天减1小时减1分钟减1秒钟后时间 yyyy-MM-dd HH:mm:ss 格式

date --date='1 year 1 month + 1 day  - 1 hour  - 1 min  - 1 sec ' "+%Y-%m-%d %H:%M:%S"

转载:mariadb/mysql定时备份脚本

在DOCKER下运行的要点

进入docker,使用:
bash /root/脚本名,否则会因为解释器报错

开启mariadb的binlog,修改my.cnf

server-id = 1
log_bin = /var/lib/mysql/mariadb-bin
log_bin_index = /var/lib/mysql/mariadb-bin.index

全量备份脚本

#!/bin/bash
# 全备方式,一般在从机上执行,适用于小中型mysql数据库:
source /etc/profile # 加载系统环境变量
source ~/.profile # 加载用户环境变量
# 定义全局变量
#登录数据库用户名
user="root"
#访问数据库密码
password="prQX4e4CmmPiBhGZ"
#访问地址
host="localhost"
#访问数据库端口
port="3306"
#备份数据库名称,多个数据库用空格进行间隔
# db=("mydb") 可选
db=$(mysql -uroot -p密码 -e "show databases" | grep -Ev "Database|sys|information_schema")

local="--single-transaction"
#数据库位置
mysql_path="/var/lib/mysql"
#备份地址
backup_path="/tmp/mysql-backup"
date=$(date +%Y%m%d_%H:%M:%S)
day=30
#日志路径
backup_log="/var/log/mysql/mysql-backlog.log"
# 判断是否存在目录,不存在则创建目录
if [ ! -e $backup_path ];then
mkdir -p $backup_path
fi

# 删除30天以前备份
#find $backup_path -type f -mtime +$day -exec rm -rf {} \; > /dev/null 2>&1

echo "开始备份数据库: ${db[*]}"

# 备份数据库后压缩
backup_sql(){
  dbname=$1
#保存的文件名称
  backup_name="${dbname}_${date}.sql"
  mysqldump -h $host -P $port -u $user -p$password $lock --default-character-set=utf8 --flush-logs -R $dbname > $backup_path/$backup_name
  if [[ $? == 0 ]];then
    cd $backup_path
    # tar --force-local参数压缩带有冒号的压缩包
    tar czvf $backup_name.tar.gz $backup_name --force-local
    size=$(du $backup_name.tar.gz -sh | awk '{print $1}')
    rm -rf $backup_name
    echo "$date 备份 $dbname($size) 成功"
  else
    cd $backup_path
    rm -rf $backup_name
    echo "$date 备份 $dbname 失败"
  fi
}

# 多个库循环备份
#length=${#db[@]}
#for ((i=0;i<$length;i++));do
for db in $db;do
  backup_sql ${db[i]} >> $backup_log 2>&1
done

echo "备份结束,结果查看 $backup_log"
du $backup_path/*$date* -sh | awk '{print "文件:" $2 ",大小:" $1}'

增量备份脚本

#!/bin/bash
# 增量备份方式,在从机上执行,适用于中大型mysql数据库
# 同时数据库配置文件必须开启binlog二进制文件


source /etc/profile # 加载系统环境变量
source ~/.profile # 加载用户环境变量
# 定义全局变量
#存放二进制备份文件的压缩包目录
backup_path="/tmp/mysql-bin-backup"
#二进制备份文件所在位置
mysqlbin_path="/var/lib/mysql/mariadb-bin"

backup_log="/var/log/mysql/mysql-binbacklog.log"
#二进制日志的索引文档
mysqlbinfile="/var/lib/mysql/mariadb-bin.index"
date=$(date +%Y%m%d_%H:%M:%S)
day=30

# 刷新新的mysql-bin.0000*文件
mysqladmin -uroot -pprQX4e4CmmPiBhGZ flush-logs

statistics=`cat $mysqlbinfile|wc -l`
num=0
# 判断是否存在目录,不存在则创建目录
if [ ! -e $backup_path ];then
  mkdir -p $backup_path
fi

# 删除30天以前备份
find $backup_path -type f -mtime +$day -exec rm -rf {} \; > /dev/null 2>&1

# for循环对比是否存在或是否为最新的文件
echo "开始备份数据库: ..."
for file in `cat $mysqlbinfile`
do
  # basename用于截取mysql-bin.0000*文件名,去掉./mysql-bin.0000*前面的./
  dbname=`basename $file`
  backup_name=`basename $file`_$date
  statistics=`expr $num + 1`
  cd $backup_path
  # 判断是否刷新二进制文件
  if [ $num != $statistics ];then
    dest=$backup_path/$dbname*
    # 判断二进制文件是否存在于要压缩的目录,不存在则备份至此目录
    if [ ! -e $dest ];then
      #拷贝二进制文件到存放压缩包的目录,为接下来压缩做准备
      cp $mysqlbin_path/$dbname $backup_path/
      # --force-local,压缩文件若带有冒号需要加上--force-local参数进行压缩解压操作
      tar czvf $backup_name.tar.gz $dbname --force-local
      size=$(du $backup_name.tar.gz -sh | awk '{print $1}')
      rm -rf $dbname
      echo "$dbname 备份 $dbname($size) 成功" >> $backup_log
      du $backup_path/* -sh | grep mysql-bin | awk '{print "文件:" $2 ",大小:" $1}'
    else
      echo "$dbname 备份 $dbname 已存在" >> $backup_log
      continue
    fi
  fi
  num+=1
done
 
echo "备份结束,结果查看 $backup_log"
du $backup_path/* -sh | grep mysql-bin | awk '{print "文件:" $2 ",大小:" $1}'

全量备份还原

[root@localhost mysql_back]#tar --force-local -zxvf LOGLEO.000015_20200708_09:17:27.tar.gz

[root@localhost mysql_back]# mysql -uroot -p你的mysql密码 要还原的数据库名 </home/mysql-back/LOGLEO.000015_20200708_09:17:27.log

增量备份还原

**查看自己的二进制目录**
[root@localhost ~]#cd /home/mysql-binback
[root@localhost mysql_binback]# ls
LOGLEO.000014_20200708_09:41:21.tar.gz
LOGLEO.000015_20200708_09:41:21.tar.gz
LOGLEO.000017_20200708_09:44:58.tar.gz
LOGLEO.000018_20200708_11:03:15.tar.gz
LOGLEO.000019_20200708_11:07:31.tar.gz
LOGLEO.000020_20200708_11:08:15.tar.gz
LOGLEO.000021_20200708_13:54:59.tar.gz
LOGLEO.000022_20200709_01:00:01.tar.gz
LOGLEO.000023_20200710_01:00:01.tar.gz

**解压文件操作**
[root@localhost mysql_binback]# tar --force-local -zxvf LOGLEO.000023_20200710_01:00:01.tar.gz 
LOGLEO.000023


[root@localhost mysql_binback]#mysqlbinlog  LOGLEO.000023 | mysql -uroot -p你的数据库密码