shell脚本基础
执行脚本的几种方式 :
假如已经写好一个脚本hello.sh
1.在编写好的脚本目录下执行./hello.sh
2.直接执行bash hello.sh,可以不用添加执行权限
3.把脚本放入环境变量$PATH的路径中去
4.执行cat hello.sh |bash
5.以绝对路径方式去运行
远程主机的脚本在本机执行
远程主机:
1.启动httpd服务
2.cp hello.sh /var/www/html/
3.主机地址172.20.109.152
本地机:
[root@centos7 ~]#curl http://172.20.109.152/hello.sh | bash
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 356 100 356 0 0 58437 0 –:–:– –:–:– –:–:– 115k
hello world!
shell脚本错误检查
1.bash -n /path/to/hello.sh
这个只能检查语法错误,但不能检查命令错误
2.bash -x /path/to/hello.sh 调试执行,能查看脚本执行的过程
变量
定义变量:
1.如name=”wang zhe”,变量中含有空格,需要加“”号,否则,它会被当作一个命令去执行
例:
[root@centos7 data]#name=wang zhe
bash: zhe: command not found.
2.变量调用命令,name=`hostname` name=`cat /etc/issue `里面定义的是整篇文件内容。
查看该变量echo “$name”,此时该变量需要加上“”号,这样能保留文件的换行格式,否则会变成一行显示。
例:定义name1=a,name3=$name1 查看name3变量echo $name3,然后重新定义name1=b,再查看变量name3的结果
[root@centos7 data]#name1=a
[root@centos7 data]#name3=$name1
[root@centos7 data]#echo $name3
a
[root@centos7 data]#name1=b
[root@centos7 data]#echo $name3
a
结果,name3的结果并未随着name1变量的改变而改变,其原理是,开始name1和name3同样指向同一个变量a,name1重新指向了b,而name3还是指向a。
“`
bash变量的种类
局部变量:生效范围只在当前shell进程;对当前shell之外的其它shell进程,包括当前shell下的子shell均无效.
环境(全局)变量:生效范围为当前shell进程及其子进程
系统登陆时,系统运行了bash进程,在当前bash下再运行bash,他们的关系为父子进程
查看当前bash进程执行echo $$ ,查看父进程执行echo $ppid,查看父子进程执行pstree -p
[root@centos7 data]#echo $$
8192
[root@centos7 data]#bash
[root@centos7 data]#echo $$
8846
[root@centos7 data]#echo $PPID
8192
[root@centos7 data]#pstree -p
├─sshd(1041)─┬─sshd(1960)───bash(1972)
│ ├─sshd(4019)───bash(4023)───man(6373)───less(6386)
│ └─sshd(8188)───bash(8192)───bash(8846)───pstree(8905)
在局部变量下,父进程和子进程定义的变量,只能对各自当前shell有效。
例:在父进程定义一个变量name=a,然后进入子进程,执行echo $name
[root@centos7 data]#name=a
[root@centos7 data]#echo $name
a
[root@centos7 data]#bash
[root@centos7 data]#echo $name
说明父进程变量不能继承给子进程。同理,子进程定义的变量也不能继承给父进程,
而在全局变量,首先定义全局变量,export name=a 或者declare -x name=a ,全局变量父进程能把变量一直继承给子进程,子子进程,定义的全局变量也能传递给脚本,脚本也是一个子进程,一直继承下去。而子进程则不能继承变量给父进程。
例:
[root@centos7 data]#export name=a
[root@centos7 data]#echo $name
a
[root@centos7 data]#bash
[root@centos7 data]#echo $name
a
查看全局变量:export或者declare -x 或者env或者printenv
删除变量:unset=name
“`
$SHELVL和$_和$-变量
$SHELVL代表子进程嵌入的深度
例:
[root@centos7 data]#echo $SHLVL
1
[root@centos7 data]#bash
[root@centos7 data]#echo $SHLVL
2
$_代表引用最后一个参数
例:
[root@centos7 data]#echo a b c
a b c
[root@centos7 data]#echo $_
c
$-变量
h:hashall,打开这个选项后,Shell 会将命令所在的路径hash下来,避免每次都要查询。通过set +h将h选项关闭
i:interactive-comments,包含这个选项说明当前的 shell 是一个交互式的 shell。所谓的交互式shell,在脚本中,i选项是关闭的。
m:monitor,打开监控模式,就可以通过Job control来控制进程的停止、继续,后台或者前台执行等。
B:braceexpand,大括号扩展
H:history,H选项打开,可以展开历史列表中的命令,可以通过!感叹号来完成,例如“!!”返回上最近的一个历史命令,“!n”返回第 n 个历史命令
“`
只读变量(常量)
只读变量只能声明,不能修改和删除
设置:readonly name=a 或者declare -r name=a
[root@centos7 data]#set |grep name 查看自定义变量
_=name
name=a
要想删除常量,需要退出当前进程。
显示系统自带的常量:declare -r或者readonly -p
“`
()的意义
()不影响当前shell环境,相当于开启了一个临时子进程,而子进程对父进程不产生影响
[root@centos7 data]#(umask 666;touch /data/f1)
[root@centos7 data]#ll /data/f1
———-. 1 root root 0 Apr 10 05:55 /data/f1
[root@centos7 data]#umask
0022
()对于变量
[root@centos7 data]#(name=wang;echo $name)
wang
[root@centos7 data]#echo $name
在子shell能看到变量,而在当前shell下变量为空
{}则对当前环境变量有影响,它和()的相同点是都是以一个整体去运行
[root@centos7 data]#{ name=wang;echo $name; }
wang
[root@centos7 data]#echo $name
wang
“`
“`
例:
[root@centos7 data]#x=1;echo “pid=$$”;(echo “subpid=$$”;echo “subx=$x”;x=2;echo “subx2=$x”);echo x=$x
pid=1972
subpid=1972
subx=1
subx2=2
x=
上述实验说明()里的subx还是继承了外面的x=1.说明括号生成的子shell和之前执行bash生成的子shell有点区别。
“`
位置参数
$1调取命令中的第一个参数
${10}第10个参数,不能写成$10,它会被识别成$1和0
$* 传递给脚本的所有参数,全部参数合为一个字符串
$@ 传递给脚本的所有参数,每个参数为独立字符串
$# 参数的个数
$0显示命令本身
set –清空位置的所有参数
shift 逐个处理参数,shift 2 同时处理两个参数
例:编辑脚本scp.sh
#!/bin/bash
#
#********************************************************************
#Author: wqf
#QQ: 88888888
#Date: 2018-04-10
#FileName: scp.sh
#URL: http://www.magedu.com
#Description: The test script
#Copyright (C): 2018 All rights reserved
#********************************************************************
echo -e “\e[1;32mstart copy…\e[0m”
scp $* root@192.168.67.129:
echo -e “\e[1;32mcopy ended..\e[0m”
[root@centos6 data]#./scp.sh scp.sh
start copy…
root@192.168.67.129’s password:
scp.sh 100% 434 0.4KB/s 00:00
copy ended..
“`
$*和$@的区别
[root@centos6 data]#vim file1.sh
#!/bin/bash
#
#********************************************************************
#Author: wqf
#QQ: 88888888
#Date: 2018-04-10
#FileName: file.sh
#URL: http://www.magedu.com
#Description: The test script
#Copyright (C): 2018 All rights reserved
#********************************************************************
echo “all arg are $*”
file2.sh “$*”
[root@centos6 data]#vim file2.sh
#!/bin/bash
#
#********************************************************************
#Author: wqf
#QQ: 88888888
#Date: 2018-04-10
#FileName: file2.sh
#URL: http://www.magedu.com
#Description: The test script
#Copyright (C): 2018 All rights reserved
#********************************************************************
echo “file2.sh:the first arg is $1”
[root@centos6 data]#./file.sh a b c
all arg are a b c
file2.sh:the first arg is a b c
结果$* 把a,b,c单个单独的字符串当作一个整体,传递个脚本二
假若把脚本中的$*换成$@
#!/bin/bash
#
#********************************************************************
#Author: wqf
#QQ: 88888888
#Date: 2018-04-10
#FileName: file.sh
#URL: http://www.magedu.com
#Description: The test script
#Copyright (C): 2018 All rights reserved
#********************************************************************
echo “all arg are $*”
./file2.sh “$@”
[root@centos6 data]#./file.sh a b c
all arg are a b c
file2.sh:the first arg is a
$@则把a ,b,c当作一个单独字符串,注意$@要加上“”号,
“`
$0 显示命令本身
给脚本创建不同的软链接,
#!/bin/bash
#
#********************************************************************
#Author: wqf
#QQ: 88888888
#Date: 2018-04-10
#FileName: file.sh
#URL: http://www.magedu.com
#Description: The test script
#Copyright (C): 2018 All rights reserved
#********************************************************************
echo “the scripts name is $0”
[root@centos6 data]#./file.sh
the scripts name is ./file.sh
[root@centos6 data]#ln -s /data/file.sh link2.sh
[root@centos6 data]#ln -s /data/file.sh link1.sh
[root@centos6 data]#ll
total 52
lrwxrwxrwx. 1 root root 13 Apr 10 09:39 link1.sh -> /data/file.sh
lrwxrwxrwx. 1 root root 13 Apr 10 09:39 link2.sh -> /data/file.sh
[root@centos6 data]#./link1.sh
the scripts name is ./link1.sh
[root@centos6 data]#./link2.sh
the scripts name is ./link2.sh
以后可以根据软链接的不同实现不同功能
“`
进程使退出状态来报告成功或者失败
- 0代表成功,1-255表示失败
- $?变量保存最近的命令退出状态,
例:
[root@centos6 data]#grep -q root /etc/passwd
[root@centos6 data]#echo $?
0
例:
[root@centos6 data]#ping -c2 192.168.67.129 &>/dev/null
[root@centos6 data]#echo $?
0
选项-c表示ping的次数
“`
退出状态码
bash自定义退出状态码
exit n :自定义退出状态码
注意:脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit命令后面的数字
注意:如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码
bash中的算术运算
let var=算术表达式
var=$[算术表达式]
var=$((算术表达式))
var=$(expr arg1 arg2 arg3)
declare -i 算术表达式
例:三种表达式
[root@centos6 data]#a=1
[root@centos6 data]#b=1
[root@centos6 data]#let c=a+b
[root@centos6 data]#echo $c
2
[root@centos6 data]#x=2
[root@centos6 data]#let x++
[root@centos6 data]#echo $x
3
[root@centos6 data]#let result=100%3
[root@centos6 data]#echo $result
1
[root@centos6 data]#c=$[a+b]
[root@centos6 data]#echo $c
2
[root@centos6 data]#c=$((a+b))
[root@centos6 data]#echo $c
2
“`
expr
[root@centos6 data]#expr 1 + 2
3
[root@centos6 data]#expr 1 \* 3
3
let 命令:
XOR 异或
0^1=1
1^0=1
0^0=0
1^1=0 ###即相同为假,不同为真
例:
[root@centos6 data]#a=2
[root@centos6 data]#b=3
[root@centos6 data]#let c=a^b
[root@centos6 data]#echo $c
1
分别把a和b转换成二进制
a:10
b:11 对位异或结果为01
c: 01
变量值互换
[root@centos6 data]#a=4
[root@centos6 data]#b=5
[root@centos6 data]#echo $a $b
4 5
[root@centos6 data]#a=$[a^b];b=$[a^b];a=$[a^b];echo $a $b
5 4
a异或b得到一个中间值a,中间值a异或b得到的是a赋值给b,中间值a异或被a赋值的b得到b,并且赋值给a,从而实现了对换
方法二
[root@centos6 data]#a=4
[root@centos6 data]#b=5
[root@centos6 data]#echo $a $b
4 5
[root@centos6 data]#tmp=$a
[root@centos6 data]#a=$b
[root@centos6 data]#b=$tmp
[root@centos6 data]#echo $a $b
5 4
“`
给字体生成随机颜色
“`
COLOR=$[RANDOM%7+31]
[root@centos6 data]#COLOR=$[RANDOM%7+31];echo -e “\e[1;${COLOR}mhello\e[0m”
hello
[root@centos6 data]#COLOR=$[RANDOM%7+31];echo -e “\e[1;${COLOR}mhello\e[0m”
hello
“`
练习:
1、编写脚本/root/bin/sumid.sh,计算/etc/passwd文件中的第10个用户和第20用户的ID之和
2、编写脚本/root/bin/sumspace.sh,传递两个文件路径作为参数给脚本,计算这两个文件中所有空白行之和
3、编写脚本/root/bin/sumfile.sh,统计/etc, /var, /usr目录中共有多少个一级子目录和文件
脚本1:
#!/bin/bash
#
#********************************************************************
#Author: wqf
#QQ: 88888888
#Date: 2018-04-10
#FileName: sumid.sh
#URL: http://www.magedu.com
#Description: The test script
#Copyright (C): 2018 All rights reserved
#********************************************************************
uid1=`cat /etc/passwd |head -n$1 |tail -n1 |cut -d: -f3`
uid2=`cat /etc/passwd |head -n$2 |tail -n1 |cut -d: -f3`
sumid=$[uid1+uid2]
echo “$sumid”
脚本2
#!/bin/bash
#
#********************************************************************
#Author: wqf
#QQ: 88888888
#Date: 2018-04-10
#FileName: sumfile.sh
#URL: http://www.magedu.com
#Description: The test script
#Copyright (C): 2018 All rights reserved
#**************************************************
file1=`grep -c “^$” $1`
file2=`grep -c “^$” $2`
sumspace=$[file1+file2]
echo “the sumspace is $sumspace”
脚本3
filenum1=`ls -1 $1 | wc -l`
filenum2=`ls -1 $2 | wc -l`
filenum3=`ls -1 $3 | wc -l`
sumfile=$[filenum1+filenum2+filenum3]
echo “the sumfile is $sumfile”
[root@centos6 data]#./sumfile2.sh /etc /var /usr
the sumfile is 282
“`
条件测试
test
字符串比较 [ str1 = str2 ]
root@centos6 data]#str1=a
[root@centos6 data]#str2=b
[root@centos6 data]#test $str1 = $str2
[root@centos6 data]#echo $?
1
[root@centos6 data]#str1=b
[root@centos6 data]#test $str1 = $str2
[root@centos6 data]#echo $?
0
等价的写法:#[ $str1 = $str2 ]
-n STRING
the length of STRING is nonzero
例:-n
[root@centos6 data]#var=b
[root@centos6 data]#[ $var ]
[root@centos6 data]#echo $?
0
-n 可以省略
[root@centos6 data]#[ “aa” ]
[root@centos6 data]#echo $?
0
[root@centos6 data]#[ “” ]
[root@centos6 data]#echo $?
1
注:判断字符串是否为空还可以写成[ x”$var” = “x” ]
数字大小比较eq、ne、 ge、 gt、 le、 lt
“`
“`
例:分区利用率报警
#!/bin/bash
#
#********************************************************************
#Author: wqf
#QQ: 88888888
#Date: 2018-04-10
#FileName: diskcheck.sh
#URL: http://www.magedu.com
#Description: The test script
#Copyright (C): 2018 All rights reserved
#********************************************************************
sd=`df |grep sd | tr -s ” ” % |cut -d% -f5 |sort -nr |head -n1`
[ “$sd” -ge 80 ] && echo “the disk will full” || echo “the disk is not full”
“`
判断用户输入参数的个数
[ “$#” -ne 2 ] && echo “please input 2 arg” && exit
判断用户输入的是否是数字
[[ ! “$1” =~ ^[0-9]+$ ]] && echo “$1 is not digit,please input digit” && exit
扩展正则表达式必须用[[ ]]
例:
#!/bin/bash
[ “$#” -ne 2 ] && echo “please input 2 arg” && exit
[[ ! “$1” =~ ^[0-9]+$ ]] && echo “$1 is not digit,please input digit” && exit
[[ ! “$2” =~ ^[0-9]+$ ]] && echo “$2 is not digit,please input digit” && exit
uid1=`cat /etc/passwd |head -n$1 |tail -n1 |cut -d: -f3`
uid2=`cat /etc/passwd |head -n$2 |tail -n1 |cut -d: -f3`
sum=$[uid1+uid2]
echo $sum
“`
在[ ]内变量用“”
[root@centos6 data]#[ $disk -ge 80 ] && echo warning
-bash: [: -ge: unary operator expected ###当变量值为空,变量没加“”号,相当于[ -ge 80 ] 则是报语法错误
[root@centos6 data]#[ “$disk” -ge 80 ] && echo warning
-bash: [: : integer expression expected ###加上“”则报的是前面的变量必须是数字
创建用户
#!/bin/bash
#
#********************************************************************
#Author: wqf
#QQ: 88888888
#Date: 2018-04-10
#FileName: createuser.sh
#URL: http://www.magedu.com
#Description: The test script
#Copyright (C): 2018 All rights reserved
#********************************************************************
id $1 &>/dev/null
[ “$?” -eq 0 ] && echo “$1 is exist” && exit
useradd “$1” && echo magedu |passwd –stdin “$1” &>/dev/null && echo “the user created successe”
“`
()与{}应用比较
语法:false || (echo cmd1; exit) 与false || { echo cmd1; exit; }
[root@centos6 data]#false || (echo cmd1;exit)
cmd1
[root@centos6 data]#false || { echo cmd1;exit; }
cmd1
logout
()执行命令是开启了一个子进程,exit 是退出子进程
{}则是在当前进程执行命令,exit则是退出当前进程,从而退出当前终端
在脚本中想要退出来则使用{},
“`
判断是否为文件夹和软链接
-d判断是否为文件夹
[root@centos7 ~]#[ -d /bin ] && echo true
true
[root@centos7 ~]#ll -d /bin
lrwxrwxrwx. 1 root root 7 Apr 8 20:53 /bin -> usr/bin
此时判断的是软链接指向的文件夹本身
-L判断是否为软链接
[root@centos7 ~]#[ -L /bin ] && echo true
true
[root@centos7 ~]#[ -L /bin/ ] && echo true
此时/bin目录后面不需要加/
判断文件可读可写
-a 表示与,两个条件都满足为真
-o 表示或,满足一个条件即为真
[wang@centos7 ~]$[ -r /etc/issue -a -w /etc/passwd ] && echo “read and write”
[wang@centos7 ~]$[ -r /etc/issue -o -w /etc/passwd ] && echo “read and write”
read and write
“`
“`
-v判断变量是否设置
[wang@centos7 ~]$[ -v var ] && echo set || echo no set
no set
[wang@centos7 ~]$var=””
[wang@centos7 ~]$[ -v var ] && echo set || echo no set
set
注:var=””设置的变量为空,也算设置了变量
判断变量是否为空字符串的几种写法
-z或者-n
[root@centos7 ~]#[ x”$var” = “x” ] && echo empty || echo “not empty”
not empty
[root@centos7 ~]#[ “$var” = “” ] && echo empty || echo “not empty”
not empty
[root@centos7 ~]#[ -z “var” ] && echo empty || echo “not empty”
not empty
[root@centos7 ~]#[ -n “var” ] && echo “not empty” || echo empty
not empty
“`
练习:
测试主机是否联通,如果能联通,则提示“主机可访问” 否则提示“主机不可访问”
#!/bin/bash
#
#********************************************************************
#Author: wqf
#QQ: 88888888
#Date: 2018-04-11
#FileName: hostping.sh
#URL: http://www.magedu.com
#Description: The test script
#Copyright (C): 2018 All rights reserved
#********************************************************************
[[ ! “$1” =~ ^(([1-9]?[0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$ ]] && echo “please input the right ip” && exit
ping -c2 $1 &>/dev/null
[ $? -eq 0 ] && echo “the host is aviliable” || echo “the host is unreachable”
“`
“`
1、编写脚本/bin/per.sh,判断当前用户对指定参数文件,是否不可读并且不可写
2、编写脚本/root/bin/excute.sh ,判断参数文件是否为sh后缀的普通文件,如果是,添加所有人可执行权限,否则提示用户非脚本文件
3、编写脚本/root/bin/nologin.sh和login.sh,实现禁止和充许普通用户登录系统
“`
“`
脚本一
#!/bin/bash
#
#********************************************************************
#Author: wqf
#QQ: 88888888
#Date: 2018-04-11
#FileName: per.sh
#URL: http://www.magedu.com
#Description: The test script
#Copyright (C): 2018 All rights reserved
#********************************************************************
[ ! -e $1 ] && echo “the file is not exist” && exit
[ -r “$1” -a -w “$1” ] && echo “r and w” || echo “not r and w”
“`
脚本二
“`
#!/bin/bash
#
#********************************************************************
#Author: wqf
#QQ: 88888888
#Date: 2018-04-11
#FileName: excute.sh
#URL: http://www.magedu.com
#Description: The test script
#Copyright (C): 2018 All rights reserved
#********************************************************************
[ ! -e $1 ] && echo “the file is not exist” && exit
[[ “$1” =~ .+\.sh$ ]] && chmod +x $1 || echo “the file is not the scripts”
“`
命令read
使用read命令来接受输入
使用read来把输入值分配给一个或多个shell变量
-p 指定要显示的提示
-s 静默输入,一般用于密码
-n N 指定输入的字符长度N
-d ‘字符’ 输入结束符
-t N TIMEOUT为N秒
read 从标准输入中读取值,给每个单词分配一个变量
所有剩余单词都被分配给最后一个变量
read -p “Enter a filename: “ FILE
例:read 批量赋值
[root@centos6 data]#read a b c
1 2 3
[root@centos6 data]#echo $a $b $c
1 2 3
[root@centos6 data]#cat >file
1 2 3
[root@centos6 data]#cat file
1 2 3
[root@centos6 data]#read a b c <file
[root@centos6 data]#echo $a $b $c
1 2 3
[root@centos6 data]#cat >file
22
33
44[root@centos6 data]#cat file
22
33
44[root@centos6 data]#read a b c <file
[root@centos6 data]#echo $a
22
[root@centos6 data]#echo $b
[root@centos6 data]#echo $c
批量赋值时,需要值用空格隔开,还可以read a b c <<<“1 2 3”
[root@centos6 data]#read a b c <<<“1 2 3”
[root@centos6 data]#echo $a $b $c
1 2 3
“`
系统中变量的特性
[root@centos6 data]#CMD=”hostname”
[root@centos6 data]#echo $CMD
hostname
[root@centos6 data]#$CMD
centos6.9
echo 打印时把hostname当作一个字符串
“`
[ ] 和[[ =~ ]]和[[ == ]]
“`
[ ]用于一般的字符串匹配
[[ =~ ]] 用扩展正则表达式
[[ == ]] 用类似于通配符
“`
判断用户输入的变量$ANS,“yes”是否合适。合适的输入方式为yes或者y ,且大小写可以随意组合
“`
[root@centos6 data]#ANS=Yes
[root@centos6 data]#[[ $ANS =~ ^([Yy]([Ee][Ss])?)$ ]]
[root@centos6 data]#echo $?
0
“`
bash的配置文件
按生效范围划分,存在两类:
全局配置:
/etc/profile
/etc/profile.d/*.sh
/etc/bashrc
个人配置:
~/.bash_profile
~/.bashrc
“`
shell登录两种方式
交互式登录:
(1)直接通过终端输入账号密码登录
(2)使用“su – UserName” 切换的用户
执行顺序:/etc/profile –> /etc/profile.d/*.sh –> ~/.bash_profile –> ~/.bashrc –> /etc/bashrc
非交互式登录:
(1)su UserName
(2)图形界面下打开的终端
(3)执行脚本
(4)任何其它的bash实例
执行顺序: ~/.bashrc –> /etc/bashrc –> /etc/profile.d/*.sh
“`
. 和source 与脚本执行./的区别
.和source 调用的是当前进程的变量,改变的是当前的环境。source+配置文件执行就是为了改变当前用户的环境
./或者别的方式执行脚本都是调用子进程的变量,改变的是子进程的环境
“`
Bash 退出任务
保存在~/.bash_logout文件中(用户)
在退出登录shell时运行
用于
- 创建自动备份
- 清除临时文件
文件查找和压缩
locate命令
locate KEYWORD,locate 是基于索引搜索数据库,搜索速度快,但不是实时搜索,及时更新数据库执行updatedb
有用的选项
-i 不区分大小写的搜索
-n N 只列举前N个匹配项目
-r 使用正则表达式
示例
搜索名称或路径中带有“conf”的文件
locate conf
使用Regex来搜索以“.conf”结尾的文件
locate -r ‘\.conf$’
“`
例:查找/etc目录下以.conf结尾的文件
[root@centos7 data]#locate -r “^/etc/.*\.conf$”
/etc/GeoIP.conf
/etc/asound.conf
/etc/autofs.conf
/etc/autofs_ldap_auth.conf
/etc/brltty.conf
/etc/cgconfig.conf
/etc/cgrules.conf
/etc/cgsnapshot_blacklist.conf
“`
命令find
选项:
一、指定搜索层级
-maxdepth level最大搜索目录深度,指定目录等级为1
-mindepth level最小搜索目录深度
-name “文件名称”:支持使用glob
*, ?, [], [^]
-iname “文件名称”:不区分字母大小写
-inum n 按inode号查找
-samefile name 相同inode号的文件
-links n 链接数为n的文件
-regex “PATTERN”:以PATTERN匹配整个文件路径字符串,而不仅仅是文件名称
例:只查找第三层目录下的文件
[root@centos6 ~]#find /etc -maxdepth 3 -mindepth 3 -name ifcfg-eth0
/etc/sysconfig/network-scripts/ifcfg-eth0
“
例:文件通配符匹配,但注意需要加上””
[root@centos6 data]#find -maxdepth 1 -name “*f*”
./sumfile.sh
./lost+found
./file
./sumfile2.sh
“`
“`
例:-inum
[root@centos6 data]#ls -i
1569793 aa 18 createuser.sh 16 diskcheck.sh 12 file 11 lost+found 13 sumfile2.sh 15 sumfile.sh
[root@centos6 data]#find /data -inum 13
/data/sumfile2.sh
“`
“`
例:-samefile
[root@centos6 data]#ln file file_link
[root@centos6 data]#find /data -samefile file
/data/file_link
/data/file
“`
“`
例:-links
[root@centos6 data]#find /bin -links 2
/bin
/bin/ed
/bin/red
“`
“`
例:-regex
[root@centos6 data]#find /etc/ -regex “.*\.conf$”
/etc/gconf/2/evoldap.conf
/etc/asound.conf
/etc/security/pam_winbind.conf
/etc/security/namespace.conf
/etc/security/limits.d/90-nproc.conf
“““
二、根据所有者,所属主查找
-user USERNAME:查找属主为指定用户(UID)的文件
-group GRPNAME: 查找属组为指定组(GID)的文件
-uid UserID:查找属主为指定的UID号的文件
-gid GroupID:查找属组为指定的GID号的文件
-nouser:查找没有属主的文件
-nogroup:查找没有属组的文件
例:-user
[root@centos6 data]#find /home -user wang -name “*.sh” -ls
2097204 0 -rw-rw-r– 1 wang wang 0 Apr 12 08:48 /home/wang/file.sh
“`
例:-nouser
[root@centos6 data]#userdel zz
[root@centos6 data]#find /home -nouser -ls
2097196 4 drwx—— 4 505 507 4096 Apr 10 16:12 /home/zz
2097197 4 -rw-r–r– 1 505 507 176 Mar 23 2017 /home/zz/.bash_profile
2097198 4 -rw-r–r– 1 505 507 124 Mar 23 2017
“`
例:-nouser 或者 -nogroup -o表示或,-a表示并且
[root@centos6 data]#find /home -nouser -o -nogroup -ls
2097205 4 drwx—— 4 hh 507 4096 Apr 12 08:57 /home/hh
2097206 4 -rw-r–r– 1 hh 507 176 Mar 23 2017 /home/hh/.bash_profile
2097207 4 -rw-r–r– 1 hh 507 124 Mar 23 2017 /home/hh/.bashrc
“`
三、根据文件类型查找:
-type TYPE:
- f: 普通文件
- d: 目录文件
- l: 符号链接文件
- s:套接字文件
- b: 块设备文件
- c: 字符设备文件
- p: 管道文件
例:
[root@centos6 data]#find /dev -type b -ls
11084 0 brw-rw—- 1 root disk Apr 12 07:57 /dev/ram9
11073 0 brw-rw—- 1 root disk Apr 12 07:57 /dev/ram8
11062 0 brw-rw—- 1 root disk Apr 12 07:57 /dev/ram7
11051 0 brw-rw—- 1 root disk Apr 12 07:57 /dev/ram6
“`
“`
四、空文件或目录
-empty
find /app -type d -empty
“`
“`
五、组合条件:
与:-a
或:-o
非:-not, !
“`
例:!或者not 查找目录下非空的文件
[root@centos6 data]#find /data ! -empty -type f
/data/sumfile.sh
/data/file_link
/data/scp.sh
/data/diskcheck.sh
/data/file
“`
六、德·摩根定律:
(非 A) 或 (非 B) = 非(A 且 B)
(非 A) 且 (非 B) = 非(A 或 B)
示例:
!A -a !B = !(A -o B)
!A -o !B = !(A -a B)
“`
例:查找非空且非文件
[root@centos6 data]#find /data ! \( -empty -o -type f \)
/data
/data/a
/data/a/b
/data/a/b/c
“`
例:查找用户名不是root,且文件名不以f开头的文件
[root@centos6 data]#find /tmp ! -user root -a ! -name ‘f*’ -ls
1966179 0 -rw-rw-r– 1 wang wang 0 Apr 12 09:29 /tmp/aa
1966095 4 drwx—— 2 gdm gdm 4096 Apr 8 13:15 /tmp/gconfd-gdm
1966105 4 drwx—— 2 gdm gdm 4096 Apr 8 13:15 /tmp/pulse-Cw8Rk5C5uXxZ
“`
七、排除目录
示例:
查找/etc/下,除/etc/sane.d目录的其它所有.conf后缀的文件
find /etc -path ‘/etc/sane.d’ -a –prune -o -name “*.conf”
查找/etc/下,除/etc/sane.d和/etc/fonts两个目录的所有.conf后缀的文件
find /etc \(–path ‘/etc/sane.d’ –o –path ’/etc/fonts’ \)
-a -prune –o -name “*.conf”
“`
八、根据文件大小来查找:
-size [+|-]#UNIT
常用单位:k, M, G,c(byte)
#UNIT: (#-1, #]
如:6k 表示(5k,6k]
-#UNIT:[0,#-1]
如:-6k 表示[0,5k]
+#UNIT:(#,∞)
如:+6k 表示(6k,∞)
“`
例:size
[root@centos6 data]#dd if=/dev/zero of=/data/f1 bs=1 count=1024
[root@centos6 data]#dd if=/dev/zero of=/data/f2 bs=1 count=1023
[root@centos6 data]#ll
total 12
-rw-r–r–. 1 root root 1024 Apr 12 09:49 f1
-rw-r–r–. 1 root root 1023 Apr 12 09:50 f2
-rw-r–r–. 1 root root 0 Apr 12 09:49 file1
-rw-r–r–. 1 root root 0 Apr 12 09:49 file2
-rw-r–r–. 1 root root 18 Apr 12 09:51 file3
[root@centos6 data]#find /data -size 1k
/data/f1
/data/file3
/data/f2
[root@centos6 data]#find /data -size 1024c
/data/f1
1k查找的范围为(1k-1,1k]即(0,1k]
1024字节查找的范围为(1024-1,1024c]即(1023,1024c]
“`
例:-size
[root@centos6 data]#find /data -size -1024c
[root@centos6 data]#find -size -1024c -ls
15 4 -rwxr-xr-x 1 root root 346 Apr 13 19:50 ./hehe.sh
19 4 -rwxr-xr-x 1 root root 610 Apr 14 11:11 ./ping.sh
11 0 ———- 2 root root 0 Apr 14 15:01 ./link
1569794 0 -rw-r–r– 1 root root 0 Apr 14 14:57 ./aa/file
17 4 -rwxr-xr-x 1 root root 511 Apr 14 08:48 ./disk.sh
14 4 -rwxr-xr-x 1 root root 454 Apr 13 19:04 ./cp.sh
16 4 -rwxr-xr-x 1 root root 480 Apr 13 20:33 ./sumid.sh
18 0 -rw-r–r– 1 root root 0 Apr 14 14:34 ./.sh
11 0 ———- 2 root root 0 Apr 14 15:01 ./file
13 0 -rw-r–r– 1 root root 0 Apr 14 14:30 ./ABC
20 4 -rwxr-xr-x 1 root root 485 Apr 14 11:47 ./read.sh
22 4 -rw-r–r– 1 root root 1023 Apr 14 15:13 ./f2
-1024c查找的范围[0,1024c-1]即[0,1023c]
例:
[root@centos6 data]#find /data -size +1023c
/data
/data/f1
查找范围(1023,∞)
“`
九、根据时间戳:
以“天”为单位;
-atime [+|-]#,
#: [#,#+1)
+#: [#+1,∞]
-#: [0,#)
-mtime
-ctime
以“分钟”为单位:
-amin
-mmin
-cmin
“`
例:查找一分钟修改的文件
[root@centos7 data]#useradd feng
[root@centos7 data]#find /etc -mmin -1
/etc
/etc/resolv.conf
/etc/group
/etc/gshadow
/etc/passwd
/etc/shadow
/etc/tuned/active_profile
/etc/cups
“`
十、MODE: 精确权限匹配
/MODE:任何一类(u,g,o)对象的权限中只要能一位匹配即可,或关系,+ 从centos7开始淘汰
-MODE:每一类对象都必须同时拥有指定权限,与关系
0 表示不关注
- find -perm 755 会匹配权限模式恰好是755的文件
- 只要当任意人有写权限时,find -perm +222就会匹配
- 只有当每个人都有写权限时,find -perm -222才会匹配
- 只有当其它人(other)有写权限时,find -perm -002才会匹配
“`
例:-MODE表示模糊匹配,只要包含指定的权限就可以匹配
[root@centos6 data]#chmod 777 file1
[root@centos6 data]#find -perm -666
./file1
666转换成二进制为110110110 其中1表示关心,需要检查,则该位需要有权限才能匹配,0则表示不关心
“`
十一、处理动作
-print:默认的处理动作,显示至屏幕
-ls:类似于对查找到的文件执行“ls -l”命令
-delete:删除查找到的文件
-fls file:查找到的所有文件的长格式信息保存至指定文件中
-ok COMMAND {} \; 对查找到的每个文件执行由COMMAND指定的命令,对于每个文件执行命令之前,都会交互式要求用户确认
-exec COMMAND {} \; 对查找到的每个文件执行由COMMAND指定的命令
{}: 用于引用查找到的文件名称自身
find传递查找到的文件至后面指定的命令时,查找到所有符合条件的文件一次性传递给后面的命令
[root@centos6 data]#find -perm -222 -fls find.log1
等价于find -perm -222 ls > find.log
例:-ok
[root@centos6 data]#find -name “f*” -ok rm {} \;
< rm … ./file2 > ?
< rm … ./file4 > ?
< rm … ./f1 > ? y
{}代表匹配到的所有文件
find -name “f*” -exec rm {} \; -exec表示批量执行
例:查找文件并批量改名
[root@centos6 data]#touch file{1..10}
[root@centos6 data]#ls
file1 file10 file2 file3 file4 file5 file6 file7 file8 file9
[root@centos6 data]#find /data -name “file*” -exec mv {} {}.bak \;
[root@centos6 data]#ls
file10.bak file2.bak file4.bak file6.bak file8.bak
file1.bak file3.bak file5.bak file7.bak file9.bak
“`
参数替换xargs
1.由于很多命令不支持管道|来传递参数,而日常工作中有这个必要,所以就有了xargs命令
2.xargs用于产生某个命令的参数,xargs 可以读入 stdin 的数据,并且以空格符或回车符将 stdin 的数据分隔成为arguments
3.注意:文件名或者是其他意义的名词内含有空格符的情况
有些命令不能接受过多参数,命令执行可能会失败,xargs可以解决
示例:
ls f* |xargs rm
find /sbin -perm +700 |ls -l 这个命令是错误的
find /sbin -perm +7000 | xargs ls –l
find和xargs格式:find | xargs COMMAND
echo file{1..6666666} |xargs -n10 touch -n10表示每次处理10个
“`
find示例
1.备份配置文件,添加.orig这个扩展名
find -name “*.conf” -exec cp {} {}.orig \;
2.提示删除存在时间超过3天以上的joe的临时文件
find /tmp -ctime +3 -user joe -ok rm {} \;
3.在主目录中寻找可被其它用户写入的文件
find ~ -perm -002 -exec chmod o-w {} \;
4.查找/data下的权限为644,后缀为sh的普通文件,增加执行权限
find /data –type f -perm 644 -name “*.sh” –exec chmod 755 {} \;
5.查看/home的目录
find /home –type d -ls
“`
练习
1、查找/var目录下属主为root,且属组为mail的所有文件
[root@centos6 mail]#find /var -user root -a -group mail -ls
787624 4 drwxrwxr-x 2 root mail 4096 Apr 12 08:57 /var/spool/mail
2、查找/var目录下不属于root、lp、gdm的所有文件
[root@centos6 mail]#find /var ! \( -user root -o -user lp -o -user gdm \) -type f -ls
927032 4 -rw——- 1 rpc rpc 164 Apr 12 07:56 /var/cache/rpcbind/portmap.xdr
3、查找/var目录下最近一周内其内容修改过,同时属主不为root,也不是postfix的文件
[root@centos6 mail]#find /var -mtime -7 ! \( -user root -o -user postfix \) -type f -ls
/var/spool/mail/hehe
786814 0 -rw-rw—- 1 bb mail 0 Apr 10 15:53 /var/spool/mail/bb
786810 0 -rw-rw—- 1 hh mail 0 Apr 12 08:57 /var/spool/mail/hh
4、查找当前系统上没有属主或属组,且最近一个周内曾被访问过的文件
[root@centos6 mail]#find -nouser -o -nogroup -atime -7
./hh
./zz
5、查找/etc目录下大于1M且类型为普通文件的所有文件
[root@centos6 data]#find /etc -size +1M -type f -ls
1706172 2176 -rw-r–r– 1 root root 2225495 Apr 8 12:37 /etc/gconf/gconf.xml.defaults/%gconf-tree.xml
1705869 8280 -rw-r–r– 1 root root 8477071 Apr 8 12:36
6、查找/etc目录下所有用户都没有写权限的文件
[root@centos6 ~]#find /etc ! -perm /222
/etc/gshadow
/etc/ld.so.conf.d/kernel-2.6.32-696.el6.x86_64.conf
/etc/rc.d/init.d/lvm2-lvmetad
/etc/rc.d/init.d/blk-availability
/etc/rc.d/init.d/lvm2-monitor
/etc/shadow-
7、查找/etc目录下至少有一类用户没有执行权限的文件
[root@centos6 ~]#find /etc ! -perm -111 -ls
8、查找/etc/init.d目录下,所有用户都有执行权限,且其它用户有写权限的文件
[root@centos6 ~]#find /etc/init.d/ -perm -111 -perm -002 -ls
1707849 0 -r-x–x-wx 1 root root 0 Apr 12 12:40 /etc/init.d/aa
“`
文本处理工具sed
用法:
sed [option]… ‘script’ inputfile…
常用选项:
-n:不输出模式空间内容到屏幕,即不自动打印
-e: 多点编辑
-f:/PATH/SCRIPT_FILE: 从指定文件中读取编辑脚本
-r: 支持使用扩展正则表达式
-i.bak: 备份文件并原处编辑
“`
地址定界:
(1) 不给地址:对全文进行处理
(2) 单地址:
#: 指定的行,$:最后一行
/pattern/:被此处模式所能够匹配到的每一行
(3) 地址范围:
#,#
#,+#
/pat1/,/pat2/
#,/pat1/
(4) ~:步进
1~2 奇数行
2~2 偶数行
“`
编辑命令:
d: 删除模式空间匹配的行,并立即启用下一轮循环
p:打印当前模式空间内容,追加到默认输出之后
a [\]text:在指定行后面追加文本
支持使用\n实现多行追加
i [\]text:在行前面插入文本
c [\]text:替换行为单行或多行文本
w /path/somefile: 保存模式匹配的行至指定文件
r /path/somefile:读取指定文件的文本至模式空间中
匹配到的行后
=: 为模式空间中的行打印行号
!:模式空间中匹配行取反处理
“`
例:只显示第二行
[root@centos7 data]#ifconfig ens33 |sed -n ‘2p’
inet 192.168.67.129 netmask 255.255.255.0 broadcast 192.168.67.255
“`
例:显示以root开头的行
[root@centos7 data]#sed -n ‘/^root/p’ /etc/passwd
root:x:0:0:root:/root:/bin/bash
“`
例:显示以w字母开头行到以s开头的结尾行
[root@centos7 data]#sed -n ‘/^w/,/^s/p’ /etc/passwd
wang:x:1000:1000:wang:/home/wang:/bin/bash
bash:x:1001:1001::/home/bash:/sbin/nologin
testbash:x:1002:1002::/home/testbash:/sbin/nologin
basher:x:1003:1003::/home/basher:/sbin/nologin
sh:x:1004:1004::/home/sh:/sbin/nologin
“`
例:打印奇数行
[root@centos7 data]#seq 10 >f1
[root@centos7 data]#sed -n ‘1~2p’ f1
1
3
5
7
9
“`
例:多点编辑-e
[root@centos7 data]#seq 10 >f1
[root@centos7 data]#sed -n -e ‘3p’ -e ‘6p’ f1
3
6
“`
例:-f
[root@centos7 data]#cat >sedscripts.txt
1~2p
[root@centos7 data]#sed -n -f sedscripts.txt f1
1
3
5
7
9
“`
例:编辑命令d删除
[root@centos7 data]#sed ‘2d’ f1 ###删除第二行
1
3
4
5
6
7
8
9
10
[root@centos7 data]#sed ‘2!d’ f1 ###删除除了第二行以外的行
2
“`
例:= 打印行号
[root@centos7 data]#sed -n ‘/root/=’ /etc/passwd
1
10
“`
例:编辑命令a追加 -i.bak编辑并且备份
[root@centos7 ~]#[root@centos7 ~]# sed -i.bak ‘/functions/aalias rm=”mv -t”‘
“`
例:a 追加的内容中含有空格 -i在前面插入内容
[root@centos6 data]#sed ‘2,5a\ ===’ file
1
2
===
3
===
4
===
5
===
6
7
8
9
10
“`
例:c
[root@centos6 data]#sed ‘2,5c\ ===’ file
1
===
6
7
8
9
10
“`
例:w保存内容到file文件中
[root@centos7 ~]#sed ‘2,6w file’ /etc/passwd
[root@centos7 ~]#cat file
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
“`
例:-r
[root@centos7 ~]#cat >f1
alias ll=”ls -l”
alias p=”pwd”
[root@centos7 ~]#sed ‘/Source/r f1′ .bashrc
# .bashrc
# User specific aliases and functions
alias rm=”mv -t /data”
alias cp=’cp -i’
mv=”mv -i”
# Source global definitions
alias ll=”ls -l”
alias p=”pwd”
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
“`
例:取ip地址
[root@centos6 ~]#ifconfig eth0 |sed -n ‘2p’ | sed -r ‘s@.*inet addr:(.*) Bcast.*@\1@’
192.168.67.128
[root@centos6 ~]#ifconfig eth0 |sed -n ‘2p’ |sed -r ‘s/(.*addr:)(.*) (Bcast.*)/\2/’
192.168.67.128
[root@centos7 ~]#ifconfig ens33 | sed -r ‘2!d;s/(.*inet )(.*)( netmask.*)/\2/’
192.168.67.130
[root@centos7 ~]#ifconfig ens33 | sed -n ‘2p’ | sed -r -e ‘s/.*inet //’ -e ‘s/ netmask.*//’
192.168.67.130
“`
例:取dirname
[root@centos6 ~]#echo “/etc/sysconfig/network” |sed -r ‘s/(.*\/)([^/]+\/?)/\1/’
/etc/sysconfig/
本文来自投稿,不代表Linux运维部落立场,如若转载,请注明出处:http://www.178linux.com/96099