- 内置命令:
shift
:使位置参数向左移动,默认移动1位,例如:shift 1
。
#!/bin/env bash
sum=0
while [ $# -ne 0 ]
do
let sum=$sum+$1 # 始终加上第1个位置的参数
shift(将位置参数向左移动1位)
done
echo sum=$sum
---------------------------------------------------------------------
[root@localhost myshell]# vim shift.sh
[root@localhost myshell]# chmod +x shift.sh
[root@localhost myshell]# ./shift.sh
sum=0
[root@localhost myshell]# ./shift.sh 1 2 3
sum=6
[root@localhost myshell]# yum list | grep expect
expect.x86_64 5.45-14.el7_1 base
expect-devel.i686 5.45-14.el7_1 base
expect-devel.x86_64 5.45-14.el7_1 base
expectk.x86_64 5.45-14.el7_1 base
pexpect.noarch 2.3-11.el7 base
[root@localhost myshell]# yum -y install expect(安装 expect 程序)
[root@localhost myshell]# rpm -ql expect(列出expect安装包安装的文件)
-
expect
是一门tcl(Tool Command Language)
工具命令语言,其可以实现登录到远程服务器过程中自动应答。
-
exp_continue
附加于某个expect
判断项之后,可以使该项被匹配后,还能继续匹配该expect
判断语句内的其他项。
#!/usr/bin/env expect
# 定义变量:set key value
set ip 192.168.211.141
set password 123456
set timeout 5 # 定义超时时间
# 开启一个程序
spawn ssh root@$ip
# 捕获相关内容
expect {
"(yes/no)?" { send "yes\r";exp_continue } # \r表示回车执行该命令
"password:" { send "$password\r" }
}
# 让终端处于交互状态,即会保持在终端而不会退回到原终端
interact
------------------------------------------------------------------------
[root@localhost myshell]# vim expect1.sh
[root@localhost myshell]# ./expect1.sh 或者 expect -f expect1.sh
spawn ssh root@192.168.211.141
root@192.168.211.141's password:
Last login: Sun Oct 25 15:56:57 2020 from 192.168.211.146
[root@hadoop ~]# logout
Connection to 192.168.211.141 closed.
------------------------------------------------------------------------
#!/usr/bin/env expect
# 定义变量,set key value
set ip 192.168.211.141
set password 123456
set timeout 5
# 开启一个程序
spawn ssh root@$ip
# 捕获相关内容
expect {
"(yes/no)?" { send "yes\r";exp_continue }
"password:" { send "$password\r" }
}
expect "#"
send "rm -rf /tmp/*\r"
send "hostname\r"
send "date +%F\r"
send "touch /tmp/file{1..3}\r"
expect eof # 表示交互结束,退回到原用户
-------------------------------------------------------------------------
[root@localhost myshell]# ./expect1.sh
spawn ssh root@192.168.211.141
root@192.168.211.141's password:
Last login: Sun Oct 25 16:18:28 2020 from 192.168.211.146
[root@hadoop ~]# rm -rf /tmp/*
[root@hadoop ~]# hostname
hadoop
[root@hadoop ~]# date +%F
2020-10-25
[root@hadoop ~]# touch /tmp/file{1..3}
[root@hadoop ~]# [root@localhost myshell]# (自动退出连接远程会话的终端程序)
[root@hadoop tmp]# ll
总用量 0
-rw-r--r--. 1 root root 0 10月 25 16:18 file1
-rw-r--r--. 1 root root 0 10月 25 16:18 file2
-rw-r--r--. 1 root root 0 10月 25 16:18 file3
---------------------------------------------------------------------------
#!/bin/env expect
# 使用位置参数
set ip [ lindex $argv 0 ]
set password [ lindex $argv 1 ]
set timeout 5
# 开启一个程序
spawn ssh root@$ip
# 捕获相关内容
expect {
"(yes/no)?" { send "yes\r";exp_continue }
"password:" { send "$password\r" }
}
interact
---------------------------------------------------------------------------
[root@localhost myshell]# ./expect2.sh 192.168.211.141 123456
spawn ssh root@192.168.211.141
root@192.168.211.141's password:
Last login: Sun Oct 25 16:19:53 2020 from 192.168.211.146
[root@hadoop ~]# logout
Connection to 192.168.211.141 closed.
[root@localhost myshell]# cat 1.txt
10.1.1.1 stu1
[root@localhost myshell]# read ip password < 1.txt (将文件1.txt中的第一行内容按格式赋值给变量ip和password)
[root@localhost myshell]# echo $ip $password
10.1.1.1 stu1
[root@localhost myshell]# cat 1.txt
10.1.1.1 stu1
10.1.1.2 stu2
[root@localhost myshell]# while read ip password;do echo $ip $password;done < 1.txt
10.1.1.1 stu1
10.1.1.2 stu2
- 在多台服务器上各创建1个用户(shell和expect结合使用):
#!/bin/env bash
# 循环在指定服务器上创建用户和删除/tmp目录下的所有文件
while read ip password
do
/usr/bin/expect <<END &>/dev/null
spawn ssh root@$ip
expect {
"(yes/no)?" { send "yes\r";exp_continue }
"password:" { send "$password\r" }
}
expect "#" { send "useradd yy1;rm -rf /tmp/*;logout\r" }
expect eof
END # 注意 END 需要顶格写
echo "服务器:$ip 已完成创建用户!"
done < ip.txt
------------------------------------------------------------------------------
[root@localhost myshell]# vim expect3.sh
[root@localhost myshell]# chmod +x expect3.sh
[root@localhost myshell]# cat ip.txt
192.168.211.141 123456
192.168.211.156 123456
[root@localhost myshell]# ./expect3.sh
服务器:192.168.211.141 已完成创建用户yy1!
服务器:192.168.211.156 已完成创建用户yy1!
[root@hadoop tmp]# id yy1(第一个服务器)
uid=1002(yy1) gid=1002(yy1) 组=1002(yy1)
[root@openstack ~]# id yy1(第二个服务器)
uid=1871(yy1) gid=1871(yy1) groups=1871(yy1)
- 运维人员实现批量推送公钥到内网主机:①管理员
root
创建yunwei
用户和安装expect
软件包,编写脚本文件(normal.sh)
#!/bin/env bash
# 判断 jumper 上的 yunwei 账号是否存在
{
id yunwei
[ $? -ne 0 ] && useradd yunwei && echo 123 | passwd --stdin yunwei
} &>/dev/null
# 判断 expect 程序是否安装
rpm -q expect
[ $? -ne 0 ] && yum -y install expect && echo "expect软件包已安装成功!"
--------------------------------------------------------------------------------
[root@localhost myshell]# vim normal.sh
[root@localhost myshell]# chmod +x normal.sh
[root@localhost myshell]# userdel -r yunwei
[root@localhost myshell]# rpm -e expect(卸载 expect 软件包)
[root@localhost myshell]# ./normal.sh
未安装软件包 expect
已加载插件:fastestmirror, langpacks
......
完毕!
expect软件已成功安装!
[root@localhost myshell]# rpm -q expect
expect-5.45-14.el7_1.x86_64
- ②运维人员检查公钥是否存在,哪些内网主机可以ping通,并将公钥推送到能ping通的内网主机,编写脚本文件:(push_public_key.sh)
#!/bin/env bash
home_dir=/home/yunwei
# 判断 yunwei 用户的密钥对是否存在
[ ! -f $home_dir/.ssh/id_rsa.pub ] && ssh-keygen -P '' -f $home_dir/.ssh/id_rsa &>/dev/null
# 循环检查局域网内主机的网络并对连通的主机进行公钥推送
ip_txt=$home_dir/ip.txt
for i in `cat $ip_txt` # 读取文件中每一行内容
do
ip=`echo $i | cut -d : -f1`
password=`echo $i | cut -d: -f2`
ping -c1 $ip &>/dev/null
if [ $? -eq 0 ];then
echo $ip >> ~/ip_up.txt
/usr/bin/expect <<-END
set timeout 10
spawn ssh-copy-id root@$ip # 开启一个程序,将公钥推送到指定内网主机
expect "(yes/no)?" { send "yes\r";exp_continue }
expect "password:" { send "$password\r" }
expect eof
END # 注意 END 左边为一个 tab 制表符:\t
else
echo $ip >> $home_dir/ip_down.txt
fi
done
-----------------------------------------------------------------
[yunwei@localhost ~]$ cat ip.txt
192.168.211.156:123456
192.168.211.141:123456
[yunwei@localhost ~]$ chmod +x push_public_key.sh
[yunwei@localhost ~]$ bash -x push_public_key.sh
[yunwei@localhost ~]$ bash -x push_public_key.sh
+ home_dir=/home/yunwei
+ '[' '!' -f /home/yunwei/.ssh/id_rsa.pub ']'
+ ssh-keygen -P '' -f /home/yunwei/.ssh/id_rsa
......
Now try logging into the machine, with: "ssh 'root@192.168.211.141'"
and check to make sure that only the key(s) you wanted were added.
[yunwei@localhost ~]$ ll
总用量 12
-rw-rw-r--. 1 yunwei yunwei 46 10月 25 21:17 ip.txt
-rw-rw-r--. 1 yunwei yunwei 64 10月 25 22:05 ip_up.txt
-rwxrwxr-x. 1 yunwei yunwei 723 10月 25 22:05 push_public_key.sh
[yunwei@localhost ~]$ cat ip_up.txt
192.168.211.156
192.168.211.141
[yunwei@localhost ~]$ ll .ssh/
总用量 12
-rw-------. 1 yunwei yunwei 1675 10月 25 22:05 id_rsa
-rw-r--r--. 1 yunwei yunwei 410 10月 25 22:05 id_rsa.pub
-rw-r--r--. 1 yunwei yunwei 354 10月 25 22:05 known_hosts
[root@hadoop .ssh]# ll(服务器ip为:192.168.211.141)
总用量 4
-rw-------. 1 root root 410 10月 25 22:05 authorized_keys
[root@openstack .ssh]# ll(服务器ip为:192.168.211.156)
total 4
-rw------- 1 root root 410 Oct 25 22:05 authorized_keys
--------------------------------------------------------------------
#!/bin/env bash
# 测试验证公钥是否推送成功
remote_ip=`tail -1 ~/ip_up.txt`
ssh root@$remote_ip hostname &>/dev/null
test $? -eq 0 && echo "成功推送公钥完毕!"
--------------------------------------------------------------------
[yunwei@localhost ~]$ vim test_ssh.sh
[yunwei@localhost ~]$ chmod +x test_ssh.sh
[yunwei@localhost ~]$ ./test_ssh.sh
成功推送公钥完毕!
- 使用
visudo
打开sudo
配置文件来管理用户的sudo
权限:
## Allow root to run any commands anywhere
root ALL=(ALL) ALL
yunwei ALL=(root) NOPASSWD:ALL,!/sbin/shutdown,!/sbin/init,!/bin/rm -rf /
--------------------------------------------------------------------------------------------
1、第一个字段 yunwei 指定的是用户:用户名或别名。每个用户设置一行,多个用户设置多行,也可将多个用户设置成一个别名后再进行设置。
2、第二个字段 ALL 指定用户所在的主机:ip或主机名,表示该sudo设置只在该主机上生效,默认限制的是本机,ALL表示在所有主机上都生效!
3、第三个字段 (root) 括号里指定以什么用户身份使用 sudo,即使用sudo后可以享有root账号下所有权限。若要排除个别用户,则可在括号内设置,如 ALL=(ALL,!oracle,!pos)。
4、第四个字段 ALL 指定的是执行的命令:即使用 sudo 后可以执行所有命令。除了设置不能关机和删除根内容以外,也可设置别名。NOPASSWD:ALL 表示使用sudo后不需要输入密码。
5、也可以授权给一个用户组:%admin ALL=(ALL) ALL 表示 admin 组里的所有成员都可以在任何主机上以任何用户身份执行任何命令。
-
普通数组
:只能使用整数
作为数组索引。如:array[0]=v1
。
-
关联数组
:可以使用字符串
作为数组索引。
- 普通数组的定义,一次赋予多个值:
数组名=(值1 值2 值3 ...)
,如:将文件中按空格隔开的字符串内容赋值给array1数组:array1=($(cat /etc/passwd))
、array4=(1 2 3 4 "hello world" [10]=linux)
、array3=(harry amy jack "Miss Hou")
。
- 获取某个下标的数组元素:
${数组名[元素下标]}
。
- 查看所有普通数组:
declare -a
。
- 查看所有关联数组:
declare -A
。
- 获取数组中所有元素:
echo ${array[*]}
或echo ${array[@]}
。
- 获取数组中元素总个数:
echo ${#array[*]}
。
- 获取数组中元素的索引下标:
echo ${!array[@]}
。
- 访问指定的子数组:
echo ${array[@]:1:2}
(1代表从下标为1的元素开始获取;2代表获取后面几个元素)。
[root@localhost myshell]# names=(harry jack tom sarsh)
[root@localhost myshell]# echo ${names[*]}
harry jack tom sarsh
[root@localhost myshell]# echo ${names[@]}
harry jack tom sarsh
[root@localhost myshell]# echo ${names[@]:1:2}(获取子数组所有元素)
jack tom
[root@localhost myshell]# echo ${#names[*]}(获取数组中元素总个数)
4
[root@localhost myshell]# echo ${!names[*]}(获取每个元素对应的数组索引)
0 1 2 3
- 关联数组的定义:①首先要声明关联数组:
declare -A asso_array1
;②数组元素赋值:一次赋一个值:数组名[索引or下标]=变量值
,如:asso_array1[linux]=one
;一次赋多个值:asso_array2=([name1]=harry [name2]=jack [name3]=amy [name4]="Miss Hou")
。注意:关联数组下标是无序的。建议数组下标不要带空格!
[root@localhost myshell]# declare -A asso_array1
[root@localhost myshell]# asso_array1[linux]=one
[root@localhost myshell]# asso_array1[java]=two
[root@localhost myshell]# declare -A
declare -A BASH_ALIASES='()'
declare -A BASH_CMDS='()'
declare -A asso_array1='([java]="two" [linux]="one" )'
[root@localhost myshell]# echo ${asso_array1[*]}
two one
[root@localhost myshell]# echo ${!asso_array1[*]}
java linux # 从这里可以看出初始化顺序不一定是打印顺序,即元素下标存储是无序的
[root@localhost myshell]# echo ${#asso_array1[*]}
2
[root@localhost myshell]# declare -A asso_array2
[root@localhost myshell]# asso_array2=([name1]=harry [name2]=jack [name3]=amy [name4]="Miss Hou")
[root@localhost myshell]# declare -A
declare -A BASH_ALIASES='()'
declare -A BASH_CMDS='()'
declare -A asso_array1='([java]="two" [linux]="one" )'
declare -A asso_array2='([name3]="amy" [name2]="jack" [name1]="harry" [name4]="Miss Hou" )'
[root@localhost myshell]# echo ${asso_array2[*]}
amy jack harry Miss Hou
[root@localhost myshell]# echo ${!asso_array2[*]}
name3 name2 name1 name4
[root@localhost myshell]# echo ${#asso_array2[*]}
4
- 获取某个文件名:
basename 文件的绝对路径名
。
- 获取某个文件所在的目录名:
dirname 文件的绝对路径名
。
- 变量值的删除匹配模式:
1个"%"代表从右往左去掉一个/key/
2个"%"代表从右往左最大去掉/key/
1个"#"代表从左往右去掉一个/key/
2个"#"代表从左往右最大去掉/key/
-----------------------------------------------
[root@localhost myshell]# url=www.taobao.com
[root@localhost myshell]# echo ${#url} (获取变量的长度)
14
[root@localhost myshell]# echo ${url#*.}(从左往右去掉一个/*./)
taobao.com
[root@localhost myshell]# echo ${url##*.}(从左往右最大去掉/*./)
com
[root@localhost myshell]# echo ${url%.*}(从右往左去掉一个/.*/)
www.taobao
[root@localhost myshell]# echo ${url%%.*}(从右往左最大去掉/.*/)
www
[root@localhost myshell]# A=/root/myshell/web_server_check.sh
[root@localhost myshell]# echo $A
/root/myshell/web_server_check.sh
[root@localhost myshell]# dirname $A(获取文件名)
/root/myshell
[root@localhost myshell]# basename $A(获取文件所在的目录名)
web_server_check.sh
- 统计web服务的不同连接状态个数,编写脚本(count_web_state.sh):
#!/bin/env bash
# 统计每个连接状态的个数
declare -A array1
states=`ss -ant | grep 80 | cut -d' ' -f1`
for i in $states
do
let array1[$i]++
done
# 通过遍历数组中的所有索引,将索引和对应的值打印出来
for j in ${!array1[@]}
do
echo $j:${array1[$j]}
done
-----------------------------------------------------------------------
[root@localhost myshell]# vim count_web_state.sh
[root@localhost myshell]# chmod +x count_web_state.sh
[root@localhost myshell]# bash -x count_web_state.sh
+ declare -A array1
++ ss -ant
++ grep 80
++ cut '-d ' -f1
+ states=LISTEN
+ for i in '$states'
+ let 'array1[LISTEN]++'
+ for j in '${!array1[@]}'
+ echo LISTEN:1
LISTEN:1
[root@localhost myshell]# netstat -ntp
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 192.168.211.146:22 192.168.211.1:14311 ESTABLISHED 3509/sshd: root@pts
[root@localhost myshell]# netstat -nltp | grep 80
tcp6 0 0 :::80 :::* LISTEN 6845/httpd
[root@localhost myshell]# netstat -natp | grep 80
tcp6 0 0 :::80 :::* LISTEN 6845/httpd
[root@localhost myshell]# ss -natp | grep :80
LISTEN 0 128 [::]:80 [::]:* users:(("httpd",pid=6850,fd=4),("httpd",pid=6849,fd=4),("httpd",pid=6848,fd=4),("httpd",pid=6847,fd=4),("httpd",pid=6846,fd=4),("httpd",pid=6845,fd=4))
-
netstat
用于显示网络连接,路由表,接口状态,伪装连接,网络链路信息和组播成员组:netstat [选项] | grep 端口号
。
- 常用选项:
-a(--all):显示所有正在或不在侦听的套接字。加上 --interfaces 选项将显示没有标记的接口。
-t(--tcp):显示tcp相关选项。
-u(--udp):显示udp相关选项。
-n(--numeric):显示数字形式地址而不是去解析主机、端口或用户名。
-l( --listening):只显示正在侦听的套接字(这是默认的选项)。
-p(--program):显示套接字所属进程的PID和名称。
-
case
语句为多重匹配语句,pattern
表示需要匹配的模式。
case var in # 定义变量,var 代表是变量名
pattern 1) # 模式1:用 | 或 or 分割多个候选值
command1
;; # 两个分号代表该命令执行完后就结束
pattern 2)
command2
;;
pattern 3)
command3
;;
*) # default:不满足以上模式,默认执行 *) 下面的命令
command4
;;
esac # esac表示 case 语句结束
#!/bin/env bash
case $1 in
start|S)
echo "service is running..."
;;
stop|T)
echo "service is stopped..."
;;
reload|R)
echo "service is restart..."
;;
*)
echo "请输入你要执行的动作!"
;;
esac
---------------------------------------------------------------------
[root@localhost myshell]# vim case1.sh
[root@localhost myshell]# chmod +x case1.sh
[root@localhost myshell]# ./case1.sh S
service is running...
[root@localhost myshell]# ./case1.sh T
service is stopped...
[root@localhost myshell]# ./case1.sh
请输入你要执行的动作!
[root@localhost myshell]# ./case1.sh R
service is restart...
[root@localhost myshell]# cat
hello
hello
world
world(ctrl+d 结束输入)
[root@localhost myshell]# cat <<END
> hello
> world
> END(输入END结束输入)
hello
world
[root@localhost myshell]# su - yunwei <<END
> echo hello
> END
上一次登录:一 10月 26 16:01:32 CST 2020
hello
[root@localhost myshell]# (仍留在当前用户)
- 实战:模拟一个多任务维护界面,当执行程序时先显示总菜单,然后进行选择后做出相应的维护操作。
#!/bin/env bash
menu(){
cat <<-EOF
h 显示命令帮助
f 显示磁盘分区
d 显示磁盘挂载
m 查看内存使用
u 查看系统负载
q 退出程序
EOF
}
# 函数调用
menu
while true
do
# 用户选择需要操作的内容
read -p "请选择需要执行的动作(help h):" action
clear
# 函数调用
menu
case $action in
h|help)
menu
;;
f)
# fdisk -l
lsblk
;;
d)
df -h
;;
m)
free -m
;;
u)
uptime
;;
q)
exit
;;
esac
done
函数名() {
函数体(一堆命令的集合)
}
-----------------------------
function 函数名() {
函数体(一堆命令的集合)
}
-----------------------------------------------------------
[root@localhost myshell]# source fun1.sh (source 读取一下文件,函数的作用域只对当前终端有效)
[root@localhost myshell]# cat fun1.sh
#!/bin/env bash
hello() {
echo hello world
}
function work() {
rm -rf /tmp/*
touch /tmp/file{1..3}
}
[root@localhost myshell]# hello
hello world
[root@localhost myshell]# work
[root@localhost myshell]# ll /tmp/
总用量 0
-rw-r--r--. 1 root root 0 10月 26 16:42 file1
-rw-r--r--. 1 root root 0 10月 26 16:42 file2
-rw-r--r--. 1 root root 0 10月 26 16:42 file3
- 函数中
return
的作用:①return
可以结束一个函数;②return
默认返回函数中最后一个命令的状态值,也可以给定参数值,范围是0-256
之间;③若没有return
命令,函数则默认返回最后一个指令的退出状态值。
[root@localhost myshell]# vim fun1.sh
[root@localhost myshell]# source fun1.sh
[root@localhost myshell]# cat fun1.sh
#!/bin/env bash
hello() {
echo hello world
}
function work() {
rm -rf /tmp/*
touch /tmp/file{1..3}
return 10 # 自定义返回最后一个命令执行后的状态值
}
[root@localhost myshell]# work
[root@localhost myshell]# echo $?
10
[root@localhost myshell]# vim fun2.sh
[root@localhost myshell]# source fun2.sh
[root@localhost myshell]# cat fun2.sh
#!/bin/env bash
# 菜单打印
menu(){
cat <<-EOF
h 显示命令帮助
f 显示磁盘分区
d 显示磁盘挂载
m 查看内存使用
u 查看系统负载
q 退出程序
EOF
}
hha(){
echo $1
}
[root@localhost myshell]# hha 5555 444(执行某个函数时顺便传递位置参数)
5555
[root@localhost myshell]# su - stu1
[stu1@localhost ~]$ vim ~/.bashrc # 将函数定义到用户的环境变量中
[stu1@localhost ~]$ ls -a
. .. .bash_logout .bash_profile .bashrc .cache .config .mozilla .viminfo
[stu1@localhost ~]$ source ./.bashrc # 函数定义只在当前用户全局内有效:~/.bashrc,在任何用户全局内有效:/etc/bashrc)
[stu1@localhost ~]$ menu
h 显示命令帮助
f 显示磁盘分区
d 显示磁盘挂载
m 查看内存使用
u 查看系统负载
q 退出程序
- 实战:①只允许
yunwei
用户通过跳板机远程连接后台的应用服务器做一些维护操作;②公司运维人员远程通过yunwei
用户连接跳板机时,跳出以下菜单供选择;③当用户选择相应主机后,直接免密码登录成功;④若用户不输入则一直提示用户输入,直到用户选择退出为止。编写脚本文件(jumper-server.sh):
#!/bin/env bash
menu()
{
cat <<-EOF
欢迎使用Jumper-server,请选择你要操作的主机:
1. DB1-Master
2. DB2-Slave
3. Web1
4. Web2
h. help
q. exit
EOF
}
# 屏蔽以下信号,比如键入 ctrl+z 后不作反应
trap "" 1 2 3 19 20
# 调用函数来打印菜单
menu
#循环等待用户选择
while true
do
# 菜单选择,case...esac语句
read -p "请选择你要访问的主机:" host
case $host in
1)
ssh root@192.168.211.141
;;
2)
ssh root@192.168.211.156
;;
h)
clear;menu
;;
q)
exit
;;
esac
---------------------------------------------------------------------------
[yunwei@localhost ~]$ chmod +x jumper-server.sh
[yunwei@localhost ~]$ vim .bashrc
[root@localhost yunwei]# cat /home/yunwei/.bashrc
# .bashrc
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
# Uncomment the following line if you don't like systemctl's auto-paging feature:
# export SYSTEMD_PAGER=
# User specific aliases and functions
~/jumper-server.sh # 当登录到 yunwei 账号时直接进入自定义的菜单选择模式
exit
[root@localhost myshell]# su - yunwei(切换到 yunwei 账号时自动执行自定义的脚本)
上一次登录:二 10月 27 14:58:10 CST 2020pts/1 上
欢迎使用Jumper-server,请选择你要操作的主机:
1. DB1-Master
2. DB2-Slave
3. Web1
4. Web2
h. help
q. exit
请选择你要访问的主机:1
Last login: Tue Oct 27 15:18:27 2020 from 192.168.211.146
[root@hadoop ~]# pwd
/root
[root@hadoop ~]# logout
Connection to 192.168.211.141 closed.
请选择你要访问的主机:^Z^Z^Z^Z^Z^C^C(快捷键信号被屏蔽,键入后不作反应)
请选择你要访问的主机:q
[root@localhost myshell]#
- 运行
shell
脚本时,若键入快捷键Ctrl+c
或Ctrl+x
(x为其他字符),程序就会终止运行,但我们并不希望shell
脚本在运行时被信号中断,此时就可以使用屏蔽信号手段,让程序忽略用户输入的信号指令,从而继续运行shell
脚本程序:trap "commands" signal-list
(当脚本收到signal-list
清单内列出的信号时,trap
命令执行双引号中的命令)
-
trap "" signal-list
:指定一个空命令串,表示直接忽视给定的信号。
- 使用
kill -l
查看信号列表:
1、SIGHUP:重新加载配置
2、SIGINT:键盘中断^C
3、SIGQUIT:键盘退出
9、SIGKILL:强制终止
15、SIGTERM:终止(正常结束),缺省信号
18、SIGCONT:继续
19、SIGSTOP:停止
20、SIGTSTP:暂停^Z
- 正则表达式:①
元字符
:具有特殊意义的专用字符,如:点(.
) 星(*
) 问号(?
)等。②前导字符
:位于元字符前面的字符:abc*
,aooo.
。
- 正则表达式中常用的元字符:
元字符 |
功能 |
备注 |
. |
匹配除换行符以外的任意单个字符 |
|
* |
前导字符出现0次或连续多次 |
|
.* |
任意长度的字符 |
ab.* |
^ |
行首(以......开头) |
^root |
$ |
行尾(以......结尾) |
bash$ |
^$ |
空行 |
|
[] |
匹配括号里任意单个字符或一组单个字符 |
[abc] |
[^] |
匹配不包含括号里任一单个字符或一组单个字符 |
[^abc] |
^[] |
匹配以括号里任意单个字符或一组单个字符开头 |
^[abc] |
^[^] |
匹配不以括号里任意单个字符或一组单个字符开头 |
^[^abc] |
\< |
取单词的头 |
\<hel |
\> |
取单词的尾 |
rld\> |
\<\> |
精确匹配 |
\<world\> |
\{n\} |
匹配前导字符连续出现n次 |
go\{2\} |
\{n,\} |
匹配前导字符至少出现n次 |
go\{2,\} |
\{n,m\} |
匹配前导字符出现n次与m次之间 |
go\{2,4\} |
\(\) |
保存被匹配的字符 |
一般用于搜索替换 |
\d |
匹配数字(grep -P ) |
[0-9] |
\w |
匹配字母数字下划线(grep -P ) |
[a-zA-Z0-9_] |
\s |
匹配空格、制表符、换页符(grep -P ) |
[\t\r\n] |
vim替换ip地址字符串
- 扩展类正则表达式中常用的元字符:必须使用特定的命指令:
grep -E
或egrep
或sed -r
。
扩展元字符 |
功能 |
备注 |
+ |
匹配1个或多个前导字符 |
bo+ 匹配boo 、bo
|
? |
匹配0个或1个前导字符 |
bo? 匹配b 、bo
|
| |
或 |
匹配a或b |
() |
组字符(看成整体) |
(my|your)self :表示匹配myself 或yourself
|
{n} |
前导字符重复n次 |
go{2} |
{n,} |
前导字符重复至少n次 |
go{2,} |
{n,m} |
前导字符重复n到m次 |
go{2,4} |
[:lower:] |
小写字母 |
[[:lower:]]{4,} |
[:upper:] |
大写字母 |
[[:upper:]]+ |
[:digit:] |
数字 |
[[:digit:]]? |
[:alnum:] |
字母和数字字符 |
[[:alnum:]]+ |
[:alpha:] |
所有字母(包括大小写字母) |
[[:alpha:]]{4} |
[:blank:] |
空格与制表符 |
[[:blank:]]* |
[:punct:] |
标点符号 |
[[:punct:]] |
[:space:] |
包括换行符,回车等在内的所有空白 |
[[:space:]]+ |
1、查找不以大写字母开头的行:
grep '^[^A-Z]' re.sh
grep -v '^[A-Z]' re.sh
grep '^[^[:upper:]]' re.sh
2、查找有数字的行:
grep '[0-9]' re.sh
grep -P '\d' re.sh
3、查找数字相邻为字母的行:
grep -E '[0-9][a-zA-Z]|[a-zA-Z][0-9]' re.sh
4、查找不以字符r开头的行:
grep -v '^r' re.sh
grep '^[^r]' re.sh
5、查找以数字开头的行:
grep '^[0-9]' re.sh
6、查找以大写字母开头的行:
grep '^[A-Z]' re.sh
7、查找以小写字母开头的行:
grep '^[a-z]' re.sh
8、查找以点结束的行:
grep '\.$' re.sh
9、查找不包行空行的所有行:
grep -v '^$' re.sh
10、查找完全匹配abc的行:
grep '\<abc\>' re.sh
grep -w 'abc' re.sh
11、查找A后有三个数字的行:
grep -E 'A[0-9]{3}' re.sh
grep 'A[0-9]\{3\}' re.sh
12、统计root在/etc/passwd里出现了几次:
grep -o 'root' /etc/passwd | wc -l
13、找出主机网卡 ens32 的IP地址、广播地址、子网掩码:
ifconfig ens32 | grep -o -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
ifconfig ens32 | grep -o -E '([0-9]{1,3}\.){3}[0-9]{1,3}'
ifconfig ens32 | grep -o -P '(\d{1,3}\.){3}\d{1,3}'
14、找出一行中全部是数字的所有行:
grep -E '^[0-9]+$' re.sh
15、找出邮箱地址的行:
grep -E '^[0-9a-zA-Z]+@[a-z0-9]+\.[a-z]+$' re.sh
网友评论