301# 注释
2:<<EOF,冒号在shell中也是命令,表示什么都不做。
3echo "I am oldboy"
4echo "I am oldboy"
5echo "I am oldboy"
6EOF #必须顶格写
7
8# 井号作为注释
9在目前的Linux中用bash和sh都是一样的,因为sh是bash的软连接。
10
11shell脚本的执行
121. bash script-name
132. path/to/script-name或./script-name
143. source script-name或. script-name
154. sh<script-name或cat script-name|sh
16
17bash script_name # 新开启一个子shell
18.或者source # 不会新开一个子shell
19
20bash脚本的一些规范化建议:
211.开头加脚本解释器
222.附带作者及版权信息
233.脚本扩展名为*.sh
244.脚本存放在固定的目录下
255.脚本中不用中文
266.成对的符号一次书写完成
277.循环格式一次性输入完成
28
29登录shell:优先/etc/profile,然后加载~/.bash_profile ,再次加载~/.bashrc,最后加载/etc/bashrc
30非登录shell:/etc/bashrc,~/.bashrc在执行一个非登录shell时调用
登录shell:优先/etc/profile,然后加载~/.bash_profile ,再次加载~/.bashrc,最后加载/etc/bashrc
非登录shell:/etc/bashrc,~/.bashrc在执行一个非登录shell时调用
变量
xxxxxxxxxx
301定义环境变量
2export TEST=1
3TEST=1
4export TEST
5declare -x TEST=1
6
7shell变量的使用和命名规范建议:
8针对变量名:(一般驼峰法则或者是下划线分隔都行)
91)变量名的定义要有一定的命令规范,并且要见名知意
102)变量名仅能使用字母,数字,下划线中的任意多个字符,并且以字母开头
11针对变量内容:
123)在脚本汇总定义普通字符串变量,精良把变量的内容用双引号括起来
134)单独数字的变量内容可以不加引号
145)希望变量的内容原样输出要加单引号
156)希望变量的值应用命令并获取命令的结果就用反引号或${}
16针对赋值符号:
177)变量定义使用赋值符号=,赋值符号的两端不要有空格
18针对变量输出:
198)使用或者输出变量的内容,可用$变量名,例如echo $PATH
209)拖用变量名db和面有其它字符连接的时候,就必须给变量名加上大括号{},如$db_t改为${db}_t
21
22
23普通变量(局部变量)
24当前用户或者脚本中生效,离开当前用户或者脚本就会失效。
25变量的名称:遵循驼峰法则或者下划线分隔单词
26变量内容:
27变量名=value #<==不加引号。 ##解析变量或者命令,然后输出,纯数字选择不加引号。
28变量名='value' #<==加单引号。 ###所见即所得
29变量名="value" #<==加双引号。 ##解析变量或者命令,然后输出,字符串默认选择双引号,可以把要定义的内容作为一个整体。
30变量名=`ls` 或变量名=$(ls)
xxxxxxxxxx
561# 变量引用和变量替换
2`command_name_str` 反引号强引用,和$()等同var_name=`ls`
3
4$(command_name_str) $(),命令置换 var_name=$(ls)
5
6${var_name} 变量引用 ${var_name}_d
7
8$var_name 变量引用 $var_name_d ≠ ${var_name}_d
9
10
11位置变量 描述
12$0 脚本的路径或名称
13$n n的范围是0~9,表示传入的第n个参数的值
14$# 脚本中传入参数的个数
15$* 传入的所有参数,但合并为一个参数
16$@ 传入的所有参数,不合并为一个参数
17状态变量 描述
18$? 上一次执行程序的返回结果
19$$ 当前执行脚本的进程号
20$! 获取上一个后台工作进程的进程号
21$_ 获取上一个执行脚本的最后一个参数
22
23
24变量子串 描述
25${parameter} 返回变量的内容
26${#parameter} 返回变量的长度,也适合特殊变量。
27 echo ${#TEST}
28 expr length "${TEST}"
29 echo $TEST|awk '{print length ($0)}'
30${parameter:offset} 从offset开始取字串到结尾
31${parameter:offset:length} 从offset开始取length长度的字串
32${parameter#word} 从变量开头开始删除最短匹配的word字串,可用通配符
33${parameter##word} 从变量开头开始删除最长匹配的word字串,可用通配符
34${parameter%word} 从变量结尾开始删除最短匹配的word字串,可用通配符
35${parameter%%word} 从变量结尾开始删除最长匹配的word字串,可用通配符
36${parameter/pattern/string} 使用string代替第一个匹配的pattern,可用通配符
37${parameter//pattern/string} 使用string代替所有匹配的pattern,可用通配符
38
39# shell特殊变量扩展(冒号可以省略)
40${parameter:-word} result=${var:-word}
41 如果变量var值为空或未赋值,那么就把值word赋值给result,但是不复制给var变量
42 find $path -name "*.log" -mtime +7 | xargs rm -rf
43 find ${path:-/tmp} -name "*.log" -mtime +7 | xargs rm -rf
44 典型应用:httpd的启动脚本
45
46${parameter:=word} result=${var:-word}
47 如果变量var值为空或未赋值,那么就把值word赋值给result,然后再赋值给变量var
48
49
50${parameter:?word} result=${var:-word}
51 如果变量var值为空或未赋值,那么就把值word当做bash错误提示输出
52 -bash: var:word
53
54${parameter:+word} result=${var:-word}
55 如果变量var值为空或未赋值,那么无操作,如果变量var不为空,就把值赋值给result,但是不赋值给var变量
56
运算符号
xxxxxxxxxx
141常见的运算符 描述
2+、- # 加法、减法
3*、/、% # 乘法、除法、取余(模)
4** # 幂运算
5++、-- # 增加或减少,前置和后置表达式的结果是不一样的
6!、&&、|| # 逻辑非、逻辑与、逻辑或
7<、<=、>、>= # 小于、小于等于、大于、大于等于
8==、!=、= # 相等、不相等、对于字串可表示相当
9<<、>> # 左移位、右移位
10~、&、|、^ # 按位取反、按位与、按位或、安慰异或
11=、+=、-=、*=、/=、%= # 赋值、增强赋值
12 # 在强类型语言(Java)中,a+=b和a=a+b是有区别的,
13 # 他们的区别是:在处理过程中各自数据类型有转换,a+=b<=>a=(a+b),它是做了数据类型强制转换的
14
运算方法
xxxxxxxxxx
371shell中常用的数学运算方法 描述
2(()) 整数计算,效率高
3let 整数运算,类似(())
4expr 可用于整数运算,但是还有很多其它的功能
5bc 适合整数和小数运算
6$[] 整数计算
7awk 适合整数和小数运算
8 echo 2.1 1.4|awk '{print $1*$2}'
9declare 定义变量值和属性,-i参数用于定义整型变量,做运算
10 declare -i a=4+5
11
12表达式 描述
13$(i=i+1) 运算后赋值,即将i+1的运算结果复制给变量i。注意不能用echo ((i=i+1))来输出表达式的值,但是可以用echo $((i=i+1))来输出。
14i=$((i+)) 可以在(())前加$符号,将表达式运算后复制给i
15((8>7&&5==5)) 可以进行比较运算,还可以加入逻辑与和逻辑或,用于条件判断
16echo $((2+1)) 需要直接输出运算表达式结果时可以在(())前面加上$符号
17
18
19expr判断一个变量是否为整数
20
21expr 2 + $1 &>/dev/null
22if [ $? -eq 0 ];then
23 echo "$1 is integer"
24else
25 echo "$1 is not integer"
26fi
27
28判断扩展名
29
30expr "$1" : ".*\.txt" &>/dev/null
31if [ $? -eq 0 ];then
32 echo "file extension is txt"
33else
34 echo "file extension not is txt"
35fi
36计算字符长度
37expr length "str"
用户交互
xxxxxxxxxx
531
2a=$1
3b=$2
4echo "a-b=$(($a-$b))"
5echo "a+b=$(($a+$b))"
6echo "a*b=$(($a*$b))"
7echo "a/b=$(($a/$b))"
8echo "a**b=$(($a**$b))"
9echo "a%b=$(($a%$b))"
10
11-p 提示
12-t 等待用户输入的时间
13read -t 30 -p "请输入一个数字:"
14
15read -p "请输入两个数字:" a b
16echo "a-b=$(($a-$b))"
17echo "a+b=$(($a+$b))"
18echo "a*b=$(($a*$b))"
19echo "a/b=$(($a/$b))"
20echo "a**b=$(($a**$b))"
21echo "a%b=$(($a%$b))"
22
23
24cat <<EOF
25 1.install lamp
26 2.install lnmp
27 3.exit
28EOF
29read -p "请选择一个序号(必须是数字):" num
30#1.判断是否为整数
31expr 2 + $num &>/dev/null
32if [ $? -ne 0 ]
33then
34 echo "Usage:$0 {1|2|3}"
35 exit 1
36fi
37
38#2.判断执行处理
39if [ $num -eq 1 ]
40then
41 echo "install lamp..."
42elif [ $num -eq 2 ]
43then
44 echo "install lnmp..."
45elif [ $num -eq 3 ]
46then
47 echo "bye."
48 exit
49else
50 echo "Usage:$0 {1|2|3}"
51 exit 1
52fi
53
条件测试
xxxxxxxxxx
1331条件表达式6种写法:if,while
2 语法1: test <测试表达式>
3 语法2: [ <测试表达式> ] #两端有空格
4 语法3:[[ <测试表达式> ]] #两端有空格
5 语法4:((<测试表达式>)) #不需要空格
6
7 语法5:(命令表达式)
8 语法6:`命令表达式`
9
10编程语法:
11[ <测试表达式> ] && 命令1
12如果前面表达式成功,那么就执行后面命令。
13
14[ <测试表达式> ] || 命令1
15如果前面表达式失败,那么就执行后面命令。
16
17[ <测试表达式> ] && {
18命令1
19命令2
20命令3
21}
22如果前面表达式成功,那么就执行后面命令。
23
24[ <测试表达式> ] && 命令1 || 命令2
25如果前面表达式成功,那么就执行命令1,否则执行命令2。
26
27[ <测试表达式> ] && {
28命令1
29命令2
30}||{
31命令3
32命令4
33}
34如果前面表达式成功,那么就执行命令1,2,否则执行命令3,4。
35
36
37常用文件测试表达式 描述
38-d 文件,directory
39-f 文件,file
40-e 文件,exist
41-r 文件,read
42-s 文件,size
43-w 文件,write
44-x 文件,executable
45-L 文件,link
46f1 -nt f2,newer than
47其它内容可以直接man test 查找。
48
49
50在[]以及test中使用 在(())和[[]]中使用 描述
51-eq ==或= equal,等于
52-ne != not equal,不等于
53-gt > greater than,大于
54-ge >= greater equal,大于等于
55-lt < less than,小于
56-le <= less equal,小于等于
57
58注:[ ]是比较老旧的写法,[[ ]]是比较新的用法,它支持[ ]中的写法
59
60字符串测试表达式
61[ -n "字符串" ] 字符串长度[不]为0,表达式为真。 not zero。
62[ -z "字符串" ] 字符串长度为0,表达式为真。 zero。
63[ "字符串1" == "字符串2" ] 两个字符串相同则为真。
64[ "字符串1" !== "字符串2" ] 两个字符串不相同则为真。
65
66
67read -p "pls input two num:" a b
68
69if [ -z "$b" ]
70then
71 echo "请输入两个数"
72 exit 1
73fi
74expr $a + $b + 1 &>/dev/null
75if [ $? -ne 0 ]
76then
77 echo "Usage:$0 num1 num2"
78 exit 1
79fi
80
81
82
83read -p "please input two integer number." a b
84
85[ -z "$b" ] &&{
86 echo "please input two integer number."
87 exit 1
88}
89
90expr $a + $b + 1 &>/dev/null
91[ $? -ne 0 ] &&{
92 echo "please input two integer number."
93 exit 2
94}
95
96if [ $a -gt $b ];then
97 echo "$a>$b"
98 exit 0
99elif [ $a -eq $b ];then
100 echo "$a=$b"
101 exit 0
102else
103 echo "$a<$b"
104 exit 0
105fi
106
107
108在[ ]和test中 在[[]]和(())中 描述
109-a && and,与
110-o || or,或
111! ! not,非
112注:[ ]是比较老旧的写法,[[ ]]是比较新的用法,它支持[ ]中的写法
113[] [[]] (()) 这些符号之间连接 使用&& ||
114
115
116+-----------------+----------------+------------------+-----------------+-------------------+
117| 条件表达式符号 [] test [[]] (())
118+-----------------+----------------+------------------+-----------------+-------------------+
119| 边界是否需要空格 需要 需要 需要 不需要
120+-----------------+----------------+------------------+-----------------+-------------------+
121| 逻辑操作符 !、-a、-o !、-a、-o !、&&、|| !、&&、||
122+-----------------+----------------+------------------+-----------------+-------------------+
123| 整数比较操作符 -eq、-gt -eq、-gt -eq、-gt =、>、<
124| -lt、-ge -lt、-ge -lt、-ge、-le >=、<=
125| -le -le 或
126| =、>、<
127| >=、<=
128+-----------------+----------------+------------------+-----------------+-------------------+
129| 字符串比较操作符 =、==、!= =、==、!= =、==、!= =、==、!=
130+-----------------+----------------+------------------+-----------------+-------------------+
131| 是否支持通配符 不支持 不支持 支持 不支持
132+-----------------+----------------+------------------+-----------------+-------------------+
133
vim配置
xxxxxxxxxx
681set nocompatible
2set history=100
3filetype on
4filetype plugin on
5filetype indent on
6set autoread
7set mouse=c
8syntax enable
9set cursorline
10hi cursorline guibg=#00ff00
11hi CursorColumn guibg=#00ff00
12set foldenable
13set foldmethod=manual
14set foldcolumn=0
15setlocal foldlevel=3
16set foldclose=all
17nnoremap <space> @=((foldclosed(line('.')) < 0) ? 'zc' : 'zo')<CR>
18set expandtab
19set tabstop=4
20set shiftwidth=4
21set softtabstop=4
22set smarttab
23set ai
24set si
25set wrap
26set sw=4
27set wildmenu
28set ruler
29set cmdheight=1
30set lz
31set backspace=eol,start,indent
32set whichwrap+=<,>,h,l
33set magic
34set noerrorbells
35set novisualbell
36set showmatch
37set mat=4
38set hlsearch
39set ignorecase
40set encoding=utf-8
41set fileencodings=utf-8
42set termencoding=utf-8
43set smartindent
44set cin
45set showmatch
46set guioptions-=T
47set guioptions-=m
48set vb t_vb=
49set laststatus=4
50set pastetoggle=<F9>
51set background=dark
52highlight Search ctermbg=black ctermfg=white guifg=white guibg=black
53autocmd BufNewFile *.py,*.cc,*.sh,*.java exec ":call SetTitle()"
54func SetTitle()
55 if expand("%:e") == 'sh'
56 call setline(1, "#!/bin/bash")
57 call setline(2, "##############################################################")
58 call setline(3, "# File Name: ".expand("%"))
59 call setline(4, "# Version: V1.0")
60 call setline(5, "# Author: meizy")
61 call setline(6, "# Organization: ")
62 call setline(7, "# Contact: [email protected]")
63 call setline(8, "# Created Time : ".strftime("%F %T"))
64 call setline(9, "# Description:")
65 call setline(10, "##############################################################")
66 endif
67endfunc
68
流程控制语句语法
xxxxxxxxxx
2231if statement
2if <condition>;then
3 statement
4fi
5if <condition>;then
6 statement
7else
8 statement
9fi
10if <condition>;then
11 statement
12elif <condition>;then
13 statement
14elif <condition>;then
15 statement
16...
17else
18 statement
19fi
20
21例1:如果不存在/backup目录就创建。
22考查if单分支
23例2:开发Shell脚本判断系统剩余内存的大小,如果低于100MB就提示内存不足,否则提示内存充足。
24例3:分别使用变量定义、read读入及脚本传参方式实现比较2个整数的大小。
25例4:打印一个菜单如下,当用户选择对应的数字时,就执行对应项的应用。
26 1.install lamp
27 2.install lnmp
28 3.exit
29
30
31cat <<EOF
32 1.install lamp
33 2.install lnmp
34 3.exit
35EOF
36read -p "请选择一个序号(必须是数字):" num
37#1.判断是否为整数
38expr 2 + $num &>/dev/null
39if [ $? -ne 0 ]
40then
41 echo "Usage:$0 {1|2|3}"
42 exit 1
43fi
44
45#2.判断执行处理
46if [ $num -eq 1 ]
47then
48 echo "install lamp..."
49elif [ $num -eq 2 ]
50then
51 echo "install lnmp..."
52elif [ $num -eq 3 ]
53then
54 echo "bye."
55 exit
56else
57 echo "Usage:$0 {1|2|3}"
58 exit 1
59fi
60
61# case语句
62case statement
63case variable in
64 value1)
65 statement
66 ;;
67 value2)
68 statement
69 ;;
70 ...
71 valuen)
72 statement
73 ;;
74 *)
75 statement
76 ;; #这里可以省略,前面都不可以省略
77esac
78
79
80cat <<EOF-
811.apple
822.pear
833.banana
844.cherry
85 EOF
86
87
88
89cat <<EOF
901.apple
912.pear
923.banana
934.cherry
94EOF
95
96
97cat <<'EOF'
98$PATH
99EOF
100
101
102cat <<EOF
103$PATH
104EOF
105
106
107rsyncd启动脚本
108
109
110start(){
111 rsync --daemon
112 retval=$?
113 if [ $retval -eq 0 ]
114 then
115 echo "rsync startup ok"
116 return $retval
117 else
118 echo "rsync startup fail"
119 return $retval
120 fi
121}
122stop(){
123 killall rsync
124 retval=$?
125 if [ $retval -eq 0 ]
126 then
127 echo "rsync stop ok"
128 return $retval
129 else
130 echo "rsync stop fail"
131 return $retval
132 fi
133}
134case "$1" in
135 start)
136 start
137 retval=$?
138 ;;
139 stop)
140 stop
141 retval=$?
142 ;;
143 restart)
144 stop
145 sleep 1
146 start
147 retval=$?
148 ;;
149 *)
150 echo "usage:$0 {start|stop|restart}"
151 exit 1
152esac
153exit $retval
154
155输出内容时可以调用系统函数库
156
157. /etc/init.d/functions
158action "service starting " /bin/ture
159action "service staring" /bin/false
160
161rsyncd启动脚本
162
163. /etc/init.d/functions
164lockfile=/var/lock/subsys/rsyncd
165rsyncd_pid_file_path=/var/run/rsyncd.pid
166
167start(){
168 rsync --daemon
169 retval=$?
170 if [ $retval -eq 0 ]
171 then
172 action "rsync startup" /bin/true
173 touch $lockfile
174 return $retval
175 else
176 action "rsync startup" /bin/false
177 return $retval
178 fi
179}
180stop(){
181 if test -s "$rsyncd_pid_file_path";then
182 rsyncd_pid=`cat $rsyncd_pid_file_path`
183 if (kill -0 $rsyncd_pid &>/dev/null);then # pid对应的进程是否真实存在
184 kill $rsyncd_pid
185 rm -f $lockfile >/dev/null
186 retval=$?
187 if [ $retval -eq 0 ]
188 then
189 action "rsync stop" /bin/true
190 return $retval
191 else
192 action "rsync stop" /bin/false
193 return $retval
194 fi
195 else
196 echo "rsyncd process is no exists."
197 return 2
198 fi
199 else
200 echo "$rsyncd_pid_file_path is not exists,or rsyncd not start."
201 fi
202}
203case "$1" in
204 start)
205 start
206 retval=$?
207 ;;
208 stop)
209 stop
210 retval=$?
211 ;;
212 restart)
213 stop
214 sleep 1
215 start
216 retval=$?
217 ;;
218 *)
219 echo "usage:$0 {start|stop|restart}"
220 exit 1
221esac
222exit $retval
223
xxxxxxxxxx
1101for statement syntax
2for variable in list
3do
4 statement
5done
6for ((控制变量初始化;条件判断表达式;控制变量的修正表达式))
7do
8 statement
9done
10
11获取列表
12(1) 直接给出列表;
13(2) 整数列表:
14(a) {start..end}
15(b) $(seq [start [step]] end)
16(3) 返回列表的命令;
17$(COMMAND)
18(4) glob 通配的方式
19(5) 变量引用;
20$@, $*
21
22
23 #!/bin/bash
24 for((j=1;j<=9;j++));do
25 for((i=1;i<=j;i++))do
26 echo -e -n "${i}X${j}=$[$i*$j]\t"
27 done
28 echo
29 done
30
31将文件中的finished去掉
32 准备文件touch stu_{1..10}_finished.jpg
33
34 ls *.jpg|awk -F "_finished" '{print "mv",$0,$1$2}'|bash
35
36 rename "_finished" "" *.jpg #rename to file
37
38 #!/bin/bash
39 for file in `ls ./*.jpg`
40 do
41 mv $file `echo ${file/_finished/}`
42 done
43信号编号 短名称 定义
441 HUP 挂起
452 INT 键盘中断
463 QUIT 键盘退出
479 KILL 中断(无法拦截
4815 TERM 终止
4918 CONT 继续
5019 STOP 停止(无法拦截)
5120 TSTP 键盘停止
52note:先用SIGTERM 再用 SIGKILL 以避免SIGKILL可能造成的误用
53
54
55sh while1.sh &
56
57把脚本while1.sh放到后台执行(后台运行脚本时常用)*
58
59nohup while1.sh &
60
61使用nohup把脚本while1.sh放到后台执行,但消息会输出到标准输出
62
63ctl+c
64
65停止执行当前脚本或任务
66
67ctl+z
68
69暂停执行当前脚本或任务
70
71bg
72
73把当前脚本或任务放到后台执行,bg可以理解为background
74
75fg
76
77把当前脚本或任务拿到前台执行,如果有多个任务,可以使用fg加任务编号调出对应脚本任务,如fg 2,调出第二个脚本任务,fg可以理解为frontground
78
79jobs
80
81查看当前执行的脚本或任务
82
83kill
84
85关闭执行的脚本任务,即以“kill %任务编号”的形式关闭脚本,这个任务编号,可以通过jobs获得
86
87
88常用进程管理命令
89
90后台运行 &、nohup、screen(运维人员)
91
92l kill、killall、pkill:杀掉进程。
93l ps:查看进程。
94l pstree:显示进程状态树。
95l top:显示进程。
96l renice:改变优先权。
97l nohup:用户退出系统之后继续工作。
98l pgrep:查找匹配条件的进程。
99l strace:跟踪一个进程的系统调用情况。
100l ltrace:跟踪进程调用库函数的情况。
101
102
103nohup和&U区别
104
105no hangup的缩写,意即“不挂断”, 忽略所有挂断(SIGHUP)信号,不挂断的运行,注意没有后台运行功能,用nohup运行命令可以使命令永久的执行下去,和用户终端没有关系,例如我们断开SSH连接都不会影响他的运行,注意了nohup没有后台运行的意思;&才是后台运行。&是指在后台运行,但当用户退出(挂起)的时候,命令自动也跟着退出,那么把nohup和&结合起来用nohup COMMAND &这样就能使命令永久的在后台执行
106
107&:放入后台,当session断掉,会受到SIGHUP信号,直接关闭,Ctrl+C无法关闭,输出会放到前台。
108nohup:nohup: ignoring input and appending output to ‘nohup.out’,Ctrl+C程序收到SIGINT信号后,直接关闭,session断掉进程会自动把进程ID为1的进程当做父进程仍然运行,输出不会放到前台,。
109nohup和&:键入Ctrl + C,发送SIGINT信号和关闭session,发送SIGHUP信号都不能关闭。
110
xxxxxxxxxx
751while condition|true|false while read line
2do do
3 statement statement
4done done < /path/to/filename
5
6cat /path/to/filename | while read line exec </path/to/filename
7do while read line
8 statement do
9done statement
10这里会开启一个子shell,所以while外无法使用while中处理的变量。 done
11
12 #
13 read -p "Enter a user name: " username
14
15 while true; do
16 if who | grep "^$username" &> /dev/null; then
17 break
18 fi
19 sleep 3
20 done
21
22 echo "$username logged on." >> /tmp/user.log
23
24 #!/bin/bash
25 read -p "Enter a option: " option
26 while [ "$option" != 'cpu' -a "$option" != 'mem' -a "$option" != 'disk' -a "$option" != 'quit' ]; do
27 read -p "Wrong option, Enter again: " option
28 done
29
30 #!/bin/bash
31 while read line;do
32 if [ $[`echo $line | cut -d: -f3` % 2] -eq 0 ];then
33 echo -e -n "username: `echo $line | cut -d: -f1`\t"
34 echo "uid: `echo $line | cut -d: -f3 `"
35 fi
36 done < /etc/passwd
37
38 #!/bin/sh
39 while true
40 do
41 uptime >>/tmp/uptime.log
42 sleep 2 # usleep微妙
43 done
44
45
46猜数字游戏。首先让系统随机生成一个数字,给这个数字定一个范围(1-60),让用户输入猜的数字,对输入进行判断,如果不符合要求,就给予高或低的提示,猜对后则给出猜对用的次数,请用while语句实现。
47提示:可以赋予一个猜水果的价格游戏。
48分析:
491)给这个数字定一个范围(1-60)
50 echo $((RANDOM%60)) 执行脚本后是固定的,例如;50
51
522)read -p "输入猜数字:" num
53用户输入的数字和已知的随机数比较。
54
553)连续猜就需要用while
56 random="$((RANDOM%60))"
57 count=0
58 while true
59 do
60 ((count++))
61 read -p "请猜数字:" num
62 if [ $num -gt $random ]
63 then
64 echo "猜高了。"
65 elif [ $num -eq $random ]
66 then
67 echo "牛啊,猜对了,一共猜了${count}次。"
68 exit
69 else
70 echo "猜低了。"
71 fi
72 done
73
74Apache访问日志(access_2010-12-8.log),把日志中每行的访问字节数对应字段数字相加,计算出总的访问量。给出实现程序,请用while循环实现。(3分钟)
75
xxxxxxxxxx
281 until statement syntax
2until condition|true|false
3do
4 statement
5done
6
7#
8declare -i j=1
9declare -i i=1
10
11until [ $j -gt 9 ]; do
12 until [ $i -gt $j ]; do
13 echo -n -e "${i}X${j}=$[$i*$j]\t"
14 let i++
15 done
16 echo
17 let i=1
18 let j++
19done
20
21
22#
23read -p "Enter a user name: " username
24
25until who | grep "^$username" &> /dev/null; do
26 sleep 3
27done
28
select
xxxxxxxxxx
621select statement
2select variable in list
3do
4 statement
5done
6
7echo "Which car do you prefer?"
8select CAR in Benz Audi VolksWagen
9do
10 break
11done
12echo "You chose $CAR"
13
14
15
16select DAY in Mon Tue Wed Thu Fri Sat Sun
17do
18 case $DAY in
19 Mon)
20 echo "Today is Monday";;
21 Tue)
22 echo "Today is Tuesday";;
23 Wed)
24 echo "Today is Wednesday";;
25 Thu)
26 echo "Today is Thursday";;
27 Fri)
28 echo "Today is Friday";;
29 Sat|Sun)
30 echo "You can have a rest today";;
31 *)
32 echo "Unknown input ,exit now" && break;;
33 esac
34done
35
36
37
38 命令 说明
39break n 如果省略n表示跳出整个循环,n 表示跳出循环的层数
40continue n 如果省略n表示跳过本次循环,忽略本次循环的剩余代码,进入循环的下一次循环。n 表示退到第n层继续循环
41exit n 退出当前shell程序,n为上一次程序执行的状态返回值。n也可以省略,再下一个shell里可通过$?接收exit n的n值
42return n 用于在函数里,作为函数的返回值,用于判断函数执行是否正确。再下一个shell里可通过$?接收exit n的n值
43
44break[n]和continue[n]都是在循环语句中使用,break 结束整个循环,continue退出当次循环,进入下次循环。
45
46
47#
48declare -i i=0
49declare -i sum=0
50
51until [ $i -gt 100 ]; do
52 let i++
53 if [ $[$i%2] -eq 1 ]; then
54 continue
55 fi
56 let sum+=$i
57done
58
59echo "Even sum: $sum"
60
61break、continue在条件语句及循环语句(for、while、if等)中用于控制程序的走向,而exit则用于终止所有语句并退出当前脚本,除此之外,exit还可以返回上一次程序或命令的执行状态值给当前Shell;return类似exit,只不过return仅用于在函数内部返回函数执行的状态值。
62
xxxxxxxxxx
1241是函数的返回值,它返回值给调用者。
2
3函数调用和传参
4
5function test(){
6 local name="test" #仅在函数内生效
7 id="id_test" # 在函数内外都生效,不建议使用
8 echo "The test function \$1 is $1" #这里的$1是传入函数的参数
9 return 1
10}
11
12# 函数一定要先定义后调用
13test args
14test $1 #这里的$1是传入脚本的参数
15echo $? # 获取函数return的值
16echo ${id}
17# echo ${name} #获取不到
18
19其它脚本中调用函数
20
21. /path/to/func_filename
22source /path/to/func_filename
23test args
24test $1 #这里的$1是传入脚本的参数
25
26
27企业案例:通过脚本传参的方式,检查Web 网站URL是否正常。
28wget命令:
29 --spider 模拟爬虫
30 -q 安静访问
31 -o /dev/null 不输出
32 -T --timeout 超时时间
33 -t --tries 重试次数
34~]# wget --spider -T 5 -q -o /dev/null -t 2 www.baidu.com
35~]# echo $?
360
37curl命令:
38 -I 看响应头
39 -s 安静的
40 -o /dev/null 不输出
41 -w %{http_code} 返回状态码,200
42 -m 超时时间
43
44~]# curl www.baidu.com -s &>/dev/null
45~]# echo $?
460
47~]# curl -I -m 5 -s -w "%{http_code}\n" -o /dev/null www.baidu.com
48200
49
50
51不用函数的实现写法
52
53if [ $# -ne 1 ]
54 then
55 echo $"usage:$0 url"
56 exit 1
57fi
58wget --spider -q -o /dev/null --tries=1 -T 5 $1 #<==-T指定超时时间,这里的$1为脚本的参数。
59if [ $? -eq 0 ]
60 then
61 echo "$1 is yes."
62else
63 echo "$1 is no."
64fi
65高端专业的函数写法:
66
67cat checkurl.sh
68
69##############################################################
70# File Name: checkurl.sh
71# Version: V1.0
72# Author: oldboy
73# Organization: www.oldboyedu.com
74# Created Time : 2018-06-07 18:29:19
75# Description:
76##############################################################
77usage(){
78 echo "Usage:$0 url"
79 exit 1
80}
81checkurl(){
82 wget -q -o /dev/null -t 2 -T 5 $1
83 if [ $? -eq 0 ]
84 then
85 echo "$1 is ok"
86 else
87 echo "$1 is fail"
88 fi
89}
90main(){
91 if [ $# -ne 1 ]
92 then
93 usage
94 fi
95 checkurl $1
96}
97main $*
98
99[root@oldboy scripts]# cat 8_5_1.sh
100
101function usage() { #<==帮助函数
102 echo $"usage:$0 url"
103 exit 1
104}
105
106function check_url() { #<==检测URL函数。
107 wget --spider -q -o /dev/null --tries=1 -T 5 $1 #<==这里的$1就是函数传参。
108 if [ $? -eq 0 ]
109 then
110 echo "$1 is yes."
111 else
112 echo "$1 is no."
113 fi
114}
115
116function main() { #<==主函数。
117 if [ $# -ne 1 ] #<==如果传入的多个参数,则打印帮助函数,提示用户。
118 then
119 usage
120 fi
121 check_url $1 #<==接收函数的传参,即把结尾的$*传到这里。
122}
123main $* #<==这里的$*就是把命令行接收的所有参数作为函数参数传给函数内部,常用手法。
124
array
xxxxxxxxxx
501Shell数组的定义
2Shell数组的定义有多种方法,列举如下。
3方法1:用小括号将变量值括起来赋值给数组变量,每个变量值之间要用空格分隔。
4语法如下:
5array=(value1 value2 value3 ... )
6此为常用定义方法,需重点掌握。
7示例如下:
8~]# array=(1 2 3) #<==用小括号将数组内容赋值给数组变量,数组元素用“空格”分隔开。
9~]# echo ${array[*]} #<==输出上面定义的数组的所有元素值,注意语法。
101 2 3
11方法2:用小括号将变量值括起来,同时采用键值对的形式赋值。
12语法如下:
13array=([1]=one [2]=two [3]=three)
14此种方法为key-value键值对的形式,小括号里对应的数字为数组下标,等号后面的内容为下标对应的数组变量的值,此方法比较复杂,不推荐使用。
15示例如下:
16~]# array=([1]=one [2]=two [3]=three)
17~]# echo ${array[*]} #<==输出上面定义的数组的所有元素值。
18one two three
19~]# echo ${array[1]} #<==输出上面定义的数组的第一个元素值。
20one
21~]# echo ${array[2]} #<==输出上面定义的数组的第二个元素值。
22two
23~]# echo ${array[3]} #<==输出上面定义的数组的第三个元素值。
24three
25方法3:通过分别定义数组变量的方法来定义。
26语法如下:
27array[0]=a;array[1]=b;array[2]=c
28此种定义方法比较麻烦,不推荐使用。
29示例如下:
30~]# array[0]=a
31~]# array[1]=b
32~]# array[2]=c
33~]# echo ${array[0]}
34a
35方法4:动态地定义数组变量,并使用命令的输出结果作为数组的内容。
36语法为:
37array=($(命令))
38或
39array=(`命令`)
40示例如下:
41data]# mkdir /array/ -p
42data]# touch /array/{1..3}.txt
43data]# ls /array/
441.txt 2.txt 3.txt
45data]# array=($(ls /array))
46data]# echo ${array[*]}
471.txt 2.txt 3.txt
48说明:还可以使用declare -a array来定义数组类型,但是比较少这样用。
49
50
xxxxxxxxxx
1501Shell数组的打印及输出
21. 打印数组元素
3此为常用知识点,需重点掌握。示例如下:
4data]# array=(one two three)
5data]# echo ${array[0]}
6#<==打印单个数组元素用${数组名[下标]},当未指定数组下标时,数组的下标是从0开始。
7one
8data]# echo ${array[1]}
9two
10data]# echo ${array[2]}
11three
12data]# echo ${array[*]} #<==使用*或者@可以得到整个数组内容。
13one two three
14data]# echo ${array[@]} #<==使用*或者@可以得到整个数组内容。
15one two three
162. 打印数组元素的个数
17此为常用知识点,需重点掌握。示例如下:
18data]# echo ${array[*]} #<==使用*或者@可以得到整个数组内容。
19one two three
20data]# echo ${#array[*]} #<==用${#数组名[@或*]}可以得到数组长度,这和前文讲解的变量子串知识是一样的,因为数组也是变量,只不过是特殊的变量,因此也适合变量的子串替换等知识。
213
22data]# echo ${array[@]} #<==使用*或者@可以得到整个数组内容。
23one two three
24data]# echo ${#array[@]} #<==用${#数组名[@或*]}可以得到数组长度,这和前文讲解的变量子串知识是一样的,因为数组也是变量,只不过是特殊的变量,因此也适合变量的子串替换等知识。
253
263. 数组赋值
27此知识不常用,了解即可。可直接通过“数组名[下标] ”对数组进行引用赋值,如果下标不存在,自动添加新一个数组元素,如果下标存在就覆盖原来的值。
28示例如下:
29data]# array=(one two three)
30data]# echo ${array[*]}
31one two three
32data]# array[3]=four #<==增加下标为3的数组元素。
33data]# echo ${array[*]}
34one two three four
35data]# array[0]=oldboy
36data]# echo ${array[*]}
37oldboy two three four
38~]# array[0]=mei #<==修改数组元素。
39~]# echo ${array[@]}
40mei 2 3 4
414. 数组的删除
42因为数组本质上还是变量,因此可通过“unset 数组[下标]”清除相应的数组元素,如果不带下标,表示清除整个数组的所有数据。
43示例如下:
44data]# echo ${array[*]}
45oldboy two three four
46data]# unset array[1] #<==取消下标为1的数组元素。
47data]# echo ${array[*]} #<==打印输出后发现数组元素“two”,不见了。
48oldboy three four
49data]# unset array #<==删除整个数组。
50data]# echo ${array[*]}
51#<==没有任何内容了。
525. 数组内容的截取和替换
53这里和前文变量子串的替换是一样的,因为数组是特殊的变量。数组元素部分内容截取的示例如下:
54~]# array=(1 2 3 4 5)
55~]# echo ${array[@]:1:3} #<==从下标为1的元素开始截取,共取3个数组元素。
562 3 4
57data]# array=({a..z}) #<==将变量的结果赋值给数组变量。
58data]# echo ${array[@]}
59a b c d e f g h i j k l m n o p q r s t u v w x y z
60data]# echo ${array[@]:1:3} #<==从下标为1的元素开始截取,共取3个数组元素。
61b c d
62data]# echo ${array[@]:0:2} #<==从下标为0的元素开始截取,共取2个数组元素。
63a b
64数组元素部分内容的替换如下:
65data]# array=(1 2 3 1 1)
66data]# echo ${array[@]/1/b} #<==把数组中的1替换成b,原数组未被修改,和sed很像。
67b 2 3 b b
68提示:调用方法是:${数组名[@或*]/查找字符/替换字符} 该操作不会改变原先数组内容,如果需要修改,可以看上面例子,重新定义数组。
69数组元素部分内容的删除如下:
70data]# array=(one two three four five)
71data]# echo ${array[@]}
72one two three four five
73data]# echo ${array[@]#o*} #<==从左边开始匹配最短的,并删除。
74ne two three four five
75data]# echo ${array1[@]##o*} #<==从左边开始匹配最长的,并删除。
76two three four five
77data]# echo ${array[@]%f*} #<==从右边开始匹配最短的,并删除。
78one two three
79data]# echo ${array[@]%%f*} #<==从右边开始匹配最长的,并删除。
80one two three
81提示:数组也是变量,因此也适合于前面讲解过的变量的子串处理的功能应用。
82数组的其他相关知识通过man bash然后搜Arrays来了解。
83
84
85范例:使用循环批量输出数组的元素。
86方法1:通过C语言型的for循环语句打印数组元素。
87
88array=(1 2 3 4 5)
89for((i=0;i<${#array[*]};i++)) #<==从数组的第一个小标0开始,循环数组的所有下标。
90do
91 echo ${array[i]} #<==打印数组元素。
92done
93方法2:通过普通for循环语句打印数组元素。
94
95array=(1 2 3 4 5)
96for n in ${array[*]} #<==${array[*]}表示输出数组所有元素,相当于列表数组元素。
97do
98 echo $n #<==这里就不是直接去数组里取元素了,而是变量n的值。
99done
100输出结果同方法1,此处略过。
101方法3:使用while循环语句打印数组元素。
102
103array=(1 2 3 4 5)
104i=0
105while ((i<${#array[*]}))
106do
107 echo ${array[i]}
108 ((i++))
109done
110输出结果同方法1,此处略过。
111
112范例:通过竖向列举法定义数组元素并批量打印。
113
114array=( #<==对于元素特别长的时候,例如URL地址,竖向列出来看起来舒服和规范。
115 oldboy
116 oldgirl
117 xiaoting
118 bingbing
119)
120for ((i=0; i<${#array[*]}; i++))
121do
122 echo "This is num $i,then content is ${array[$i]}"
123done
124echo ----------------------
125echo "array len:${#array[*]}"
126输出结果如下:
127This is num 0,then content is oldboy
128This is num 1,then content is oldgirl
129This is num 2,then content is xiaoting
130This is num 3,then content is bingbing
131----------------------
132array len:4
133范例:把命令结果作为数组元素定义并打印。
134准备数据:
135scripts]# mkdir -p /array/
136scripts]# touch /array/{1..3}.txt
137scripts]# ls /array/
1381.txt 2.txt 3.txt
139以下为开发脚本:
140
141dir=($(ls /array)) #<==把ls /array命令结果放数组里。
142for ((i=0; i<${#dir[*]}; i++)) #<==${#dir[*]}为数组的长度。
143do
144 echo "This is NO.$i,filename is ${dir[$i]}"
145done
146输出结果如下:
147This is NO.0,filename is 1.txt
148This is NO.1,filename is 2.txt
149This is NO.2,filename is 3.txt
150
xxxxxxxxxx
331(1)定义命令
2静态数组:
3array=(1 2 3)
4动态数组:
5array=($(ls))或array=(`ls`)
6给数组赋值:
7array[3]=4
8(2)打印命令
9打印所有元素:
10${array[@]}或${array[*]}
11打印数组长度:
12${#array[@]}或${#array[*]}
13打印单个元素:
14${array[i]} #<==i是数组下标。
15(3)循环打印的常用基本循环
16
17arr=(
18 10.0.0.11
19 10.0.0.22
20 10.0.0.33
21)
22#C语言for循环语法
23for ((i=0;i<${#arr[*]};i++))
24do
25 echo "${arr[$i]}"
26done
27echo ---------------
28#普通for循环语法
29for n in ${arr[*]}
30do
31 echo "$n"
32done
33
xxxxxxxxxx
3911范例:利用bash for循环打印下面这句话中字母数不大于6的单词(某企业面试真题)。
2I am oldboy teacher welcome to oldboy training class
3解答思路:
41)先把所有的单词放到数组里,然后依次进行判断。命令如下:
5array=(I am oldboy teacher welcome to oldboy training class)
62)对变量内容计算长度,这在前文已经讲解过了。常见方法有4种:
7scripts]# char=oldboy
8scripts]# echo $char|wc -L
96
10scripts]# echo ${#char}
116
12scripts]# expr length $char
136
14scripts]# echo $char|awk '{print length}'
156
16方法1:通过数组方法实现。
17arr=(I am oldboy teacher welcome to oldboy training class)
18for ((i=0;i<${#arr[*]};i++))
19do
20 if [ ${#arr[$i]} -lt 6 ]
21 then
22 echo "${arr[$i]}"
23 fi
24done
25echo -----------------------
26for word in ${arr[*]}
27do
28 if [ `expr length $word` -lt 6 ];then
29 echo $word
30 fi
31done
32说明:本例给出了两种for循环语法打印数组元素的方法。
33方法2:使用for循环列举取值列表法
34for word in I am oldboy teacher welcome to oldboy training class #<==看起来有点low吧。
35do
36 if [ `echo $word|wc -L` -lt 6 ];then
37 echo $word
38 fi
39done
40
41chars="I am oldboy teacher welcome to oldboy training class" #<==定义字符串也可以。
42for word in $chars
43do
44 if [ `echo $word|wc -L` -lt 6 ];then
45 echo $word
46 fi
47done
48方法3:通过awk循环实现。
49scripts]# chars="I am oldboy teacher welcome to oldboy training class"
50scripts]# echo $chars|awk '{for(i=1;i<=NF;i++) if(length($i)<=6)print $i}'
51几种方法的输出结果统一为:
52I
53am
54oldboy
55to
56oldboy
57class
58范例:批量检查多个网站地址是否正常
59要求:
601)使用Shell数组方法实现,检测策略尽量模拟用户访问。
612)每10秒钟做一次所有的检测,无法访问的输出报警。
623)待检测的地址如下。
63http://blog.oldboyedu.com
64http://blog.etiantian.org
65http://oldboy.blog.51cto.com
66http://10.0.0.7
67解题思路:
681)把URL定义成数组,形成函数。
692)编写URL检查脚本函数,传入数组的元素,即URL。
703)组合实现整个案例,编写main主函数(即执行函数),每隔10秒检查一次。
71下面的参考答案采用了Shell数组方法,同时检测多个URL是否正常,并给出专业的展效果
72
73# this script is created by oldboy.
74# e_mail:[email protected]
75# function:case example
76# version:1.3
77. /etc/init.d/functions
78check_count=0
79url_list=( #<==定义检测的URL数组,包含多个URL地址。
80http://blog.oldboyedu.com
81http://blog.etiantian.org
82http://oldboy.blog.51cto.com
83http://10.0.0.7
84)
85
86function wait() #<==定义3,2,1倒计时函数。
87{
88 echo -n '3秒后,执行检查URL操作.';
89 for ((i=0;i<3;i++))
90 do
91 echo -n ".";sleep 1
92 done
93 echo
94}
95function check_url() #<==定义检测URL的函数。
96{
97 wait #<==执行倒计时函数。
98 for ((i=0; i<`echo ${#url_list[*]}`; i++)) #<==循环数组元素。
99 do
100 wget -o /dev/null -T 3 --tries=1 --spider ${url_list[$i]} >/dev/null 2>&1 #<==检测是否可以访问数组元素的地址。
101 if [ $? -eq 0 ] #<==如果返回值为0,表示访问成功。
102 then
103 action "${url_list[$i]}" /bin/true #<==优美的显示成功结果。
104 else
105 action "${url_list[$i]}" /bin/false #<==优美的显示失败结果。
106 fi
107 done
108 ((check_count++)) #<==检测次数加1。
109}
110main(){ #<==定义主函数。
111 while true #<==开启一个持续循环。
112 do
113 check_url #<==加载检测url的函数。
114 echo "-------check count:${check_count}---------"
115 sleep 10 #<==间歇10秒。
116 done
117}
118main #<==优美的显示成功结果,调用主函数运行程序。
119执行结果如图所示。
120检测数组内URL输出的专业效果图
121提示:实际使用时,一些基础的函数脚本(例如:加颜色的函数)是放在函数文件里的(例如:放在/etc/init.d/functions里,与执行的脚本内容部分分离,看起来更清爽,大型的语言程序都是这样开发的),另外,特别注意wget命令后要接重试次数--tries参数,否则检查时会卡住。
122
123范例:开发一个守护进程脚本,每30秒监控MySQL主从复制是否异常(包括不同步以及延迟),如果异常,则发送短信并发送邮件给管理员存档(此为生产实战案例)。
124提示:如果没主从复制的环境,可以把下面的文本放到文件里读取来模拟主从复制状态:
125*************************** 1. row ***************************
126 Slave_IO_State: Waiting for master to send event
127 Master_Host: 10.0.0.51
128 Master_User: rep
129 Master_Port: 3306
130 Connect_Retry: 60
131 Master_Log_File: mysql-bin.000013
132 Read_Master_Log_Pos: 502547
133 Relay_Log_File: relay-bin.000013
134 Relay_Log_Pos: 251
135 Relay_Master_Log_File: mysql-bin.000013
136 Slave_IO_Running: Yes #<==IO线程状态必须为Yes
137 Slave_SQL_Running: Yes #<==SQL线程状态必须为Yes
138 Replicate_Do_DB:
139 Replicate_Ignore_DB: mysql
140 Replicate_Do_Table:
141 Replicate_Ignore_Table:
142 Replicate_Wild_Do_Table:
143 Replicate_Wild_Ignore_Table:
144 Last_Errno: 0
145 Last_Error:
146 Skip_Counter: 0
147 Exec_Master_Log_Pos: 502547
148 Relay_Log_Space: 502986
149 Until_Condition: None
150 Until_Log_File:
151 Until_Log_Pos: 0
152 Master_SSL_Allowed: No
153 Master_SSL_CA_File:
154 Master_SSL_CA_Path:
155 Master_SSL_Cert:
156 Master_SSL_Cipher:
157 Master_SSL_Key:
158 Seconds_Behind_Master: 0 #<==和主库比同步延迟的秒数,这个参数很重要。
159Master_SSL_Verify_Server_Cert: No
160 Last_IO_Errno: 0
161 Last_IO_Error:
162 Last_SQL_Errno: 0
163 Last_SQL_Error:
164解题思路:
1651)判断主从复制是否异常,主要就是检测如下参数对应的值是否和如下一致。
166 Slave_IO_Running: Yes #<==IO线程状态必须为Yes。
167 Slave_SQL_Running: Yes #<==SQL线程状态必须为Yes。
168 Seconds_Behind_Master: 0 #<==和主库比同步延迟的秒数,这个参数很重要。
1692)读取状态数据或状态文件,然后取出对应值,和正确时的值进行比对,如果不符合就表示故障了,即调用报警脚本报警。
1703)为了更专业,还可以在当主从不同步时,查看相应错误号,判断对应错误号以进行自动恢复主从复制故障(这些错误号也可以通过配置文件里配置参数实现自动忽略故障)。
171以下为参考答案。
172首先给出模拟数据(注意,使用时要去掉中文注释)。
173[root@oldboy scripts]# cat slave.log
174*************************** 1. row ***************************
175 Slave_IO_State: Waiting for master to send event
176 Master_Host: 10.0.0.51
177 Master_User: rep
178 Master_Port: 3306
179 Connect_Retry: 60
180 Master_Log_File: mysql-bin.000013
181 Read_Master_Log_Pos: 502547
182 Relay_Log_File: relay-bin.000013
183 Relay_Log_Pos: 251
184 Relay_Master_Log_File: mysql-bin.000013
185 Slave_IO_Running: Yes
186 Slave_SQL_Running: Yes
187 Replicate_Do_DB:
188 Replicate_Ignore_DB: mysql
189 Replicate_Do_Table:
190 Replicate_Ignore_Table:
191 Replicate_Wild_Do_Table:
192 Replicate_Wild_Ignore_Table:
193 Last_Errno: 0
194 Last_Error:
195 Skip_Counter: 0
196 Exec_Master_Log_Pos: 502547
197 Relay_Log_Space: 502986
198 Until_Condition: None
199 Until_Log_File:
200 Until_Log_Pos: 0
201 Master_SSL_Allowed: No
202 Master_SSL_CA_File:
203 Master_SSL_CA_Path:
204 Master_SSL_Cert:
205 Master_SSL_Cipher:
206 Master_SSL_Key:
207 Seconds_Behind_Master: 0
208Master_SSL_Verify_Server_Cert: No
209 Last_IO_Errno: 0
210 Last_IO_Error:
211 Last_SQL_Errno: 0
212 Last_SQL_Error:
213然后开发脚本,开发脚本有多种方法,下面分别给出。
214方法1:
215scripts]# awk -F ': ' '/_Running|_Behind/{print $NF}' slave.log
216#<==获取所有复制相关的状态值。
217Yes
218Yes
2190
220[root@oldboy scripts]# cat 13_6_1.sh
221count=0
222status=($(awk -F ': ' '/_Running|_Behind/{print $NF}' slave.log)) #<==获取所有复制相关的状态值赋值给数组status。
223for((i=0;i<${#status[*]};i++)) #<==循环数组元素。
224do
225 if [ "${status[${i}]}" != "Yes" -a "${status[${i}]}" != "0" ] #<==如果数组元素值不为Yes并且不为0任意一个,那就表示复制出故障了。
226 then
227 let count+=1 #<==错误数加1。
228 fi
229done
230if [ $count -ne 0 ];then #<==只要错误数不等于0,就表示状态值肯定有有问题的。
231 echo "mysql replcation is failed" #<==提示复制出现问题。
232else
233 echo "mysql replcation is sucess" #<==否则提示复制正常。
234fi
235说明:本答案是为了引导读者,没有加每30秒。
236测试结果如下:
237scripts]# sh 13_6_1.sh
238mysql replcation is sucess
239scripts]# sed -i 's#Slave_IO_Running: Yes#Slave_IO_Running: No#g' slave.log #<==提模拟IO线程故障。
240scripts]# sh 13_6_1.sh
241mysql replcation is failed
242方法2:本方法和方法1实现的功能差不多,但是开发手法就更高大上一些。
243
244CheckDb(){
245 count=0
246status=($(awk -F ': ' '/_Running|_Behind/{print $NF}' slave.log))
247for((i=0;i<${#status[*]};i++))
248do
249 if [ "${status[${i}]}" != "Yes" -a "${status[${i}]}" != "0" ]
250 then
251 let count+=1
252 fi
253done
254if [ $count -ne 0 ];then
255 echo "mysql replcation is failed"
256 return 1
257else
258 echo "mysql replcation is sucess"
259 return 0
260fi
261}
262main(){
263while true
264do
265 CheckDb
266 sleep 3
267done
268}
269main
270测试结果如下:
271scripts]# sed -i 's#Slave_IO_Running: No#Slave_IO_Running: Yes#g' slave.log #<==模拟IO线程恢复正常。
272scripts]# sh 13_6_2.sh
273mysql replcation is sucess
274mysql replcation is sucess
275mysql replcation is sucess
276^C
277scripts]# sed -i 's#Slave_IO_Running: Yes#Slave_IO_Running: No#g' slave.log #<==提示复制出现问题。
278scripts]# sh 13_6_2.sh
279mysql replcation is failed
280mysql replcation is failed
281^C
282说明:本答案还是没有完全满足题意,例如,报警短信和邮件没有开发。
283方法3(此为企业生产正式检查脚本):
284
285###########################################
286# this script function is :
287# check_mysql_slave_replication_status
288# USER YYYY-MM-DD - ACTION
289# oldboy 2009-02-16 - Created
290############################################
291path=/server/scripts #<==定义脚本存放路径,大家注意这个规范。
292MAIL_GROUP="[email protected] [email protected]" #<==邮件列表,以空格隔开。
293PAGER_GROUP="18600338340 18911718229" #<==手机列表,以空格隔开。
294LOG_FILE="/tmp/web_check.log" #<==日志路径。
295USER=root #<==数据库用户。
296PASSWORD=oldboy123 #<==用户密码。
297PORT=3307 #<==端口。
298MYSQLCMD="mysql -u$USER -p$PASSWORD -S /data/$PORT/mysql.sock" #<==登录数据库命令。
299error=(1008 1007 1062) #<==可以忽略的主从复制错误号。
300RETVAL=0
301[ ! -d "$path" ] && mkdir -p $path
302function JudgeError(){ #<==定义判断主从复制错误的函数。
303 for((i=0;i<${#error[*]};i++))
304 do
305 if [ "$1" == "${error[$i]}" ] #<==如果传入的错误号和数组里的元素匹配,则执行then后命令。
306 then
307 echo "MySQL slave errorno is $1,auto repairing it."
308 $MYSQLCMD -e "stop slave;set global sql_slave_skip_counter=1;start slave;" #<==自动修复。
309 fi
310 done
311 return $1
312}
313function CheckDb(){ #<==定义检查数据库主从复制状态的函数。
314status=($(awk -F ': ' '/_Running|Last_Errno|_Behind/{print $NF}' slave.log))
315 expr ${status[3]} + 1 &>/dev/null #<==这个是延迟状态值,进行是否为数字判断。
316 if [ $? -ne 0 ];then #<==如果不为数字。
317 status[3]=300 #<==赋值300,当数据库出现复制故障时,延迟这个状态值有可能是NULL,即非数字。
318 fi
319 if [ "${status[0]}" == "Yes" -a "${status[1]}" == "Yes" -a ${status[3]} -lt 120 ]
320 #<==两个线程都为Yes,并且延迟小于120秒,即认为复制状态是正常的。
321 then
322 #echo "Mysql slave status is ok"
323 return 0 #<==返回0。
324 else
325 #echo "mysql replcation is failed"
326 JudgeError ${status[2]} #<==否则将错误号${status[2]},传入JudgeError函数,判断错误号是否可以自动修复。
327 fi
328}
329function MAIL(){ #<==定义邮件函数,在范例11_13讲过此函数。
330local SUBJECT_CONTENT=$1 #<==函数的第一个传参赋值给主题变量。
331for MAIL_USER in `echo $MAIL_GROUP` #<==遍历邮件列表。
332do
333 mail -s "$SUBJECT_CONTENT " $MAIL_USER <$LOG_FILE #<==发邮件。
334done
335}
336function PAGER(){#<==定义手机函数,在范例11_13讲过此函数。
337 for PAGER_USER in `echo $PAGER_GROUP` #<==遍历手机列表。
338 do
339 TITLE=$1 #<==函数的第一个传参赋值给主题变量。
340 CONTACT=$PAGER_USER #<==手机号赋值给CONTACT变量。
341 HTTPGW=http://oldboy.sms.cn/smsproxy/sendsms.action #<==发短信地址,这个地址需要用户付费购买的,如果免费的就得用139,微信替代了。
342 #send_message method1
343 curl -d cdkey=5ADF-EFA -d password=OLDBOY -d phone=$CONTACT -d message="$TITLE[$2]" $HTTPGW
344#<==发送短信报警的命令。cdkey是购买短信网关时,售卖者给的,password是密码,也是售卖者给的。
345 done
346}
347function SendMsg(){
348 if [ $1 -ne 0 ] #<==传入$1,如果不为0表示复制有问题,这里的$1即CheckDb里的返回值(用检测失败的次数作为返回值),在后文主函数main执行时调用SendMsg传参时传进来。
349 then
350 RETVAL=1
351 NOW_TIME=`date +"%Y-%m-%d %H:%M:%S"`#<==报警时间。
352 SUBJECT_CONTENT="mysql slave is error,errorno is $2,${NOW_TIME}."#<==报警主题。
353 echo -e "$SUBJECT_CONTENT"|tee $LOG_FILE #<==输出信息,并记录到日志。
354 MAIL $SUBJECT_CONTENT #<==发邮件报警,$SUBJECT_CONTENT作为函数参数传给MAIL函数体的$1。
355 PAGER $SUBJECT_CONTENT $NOW_TIME #<==发短信报警,$SUBJECT_CONTENT作为函数参数传给MAIL函数体的$1,$NOW_TIME作为函数体传给$2。
356 else
357 echo "Mysql slave status is ok"
358 RETVAL=0 #<==以0作为返回值。
359 fi
360 return $RETVAL
361}
362function main(){
363while true
364do
365 CheckDb
366 SendMsg $? #<==传入第一个参数$?,即CheckDb里的返回值(用检测失败的次数作为返回值)。
367 sleep 300
368done
369}
370main
371
372
373下面列举的知识点是老男孩要求所有学生必会的,这些脚本知识点中的很多内容不仅仅涉及脚本知识,还有系统命令、大量网络服务的知识,这些都需要读者了解和掌握,Shell编程仅仅是其中的一部分内容。
374作为一个合格运维人员,需要掌握的脚本列表如下:
3751)系统及各类服务的监控脚本,例如:文件、内存、磁盘、端口,URL监控报警等。
3762)监控网站目录下文件是否被篡改,以及站点目录批量被篡改后如何批量恢复的脚本。
3773)各类服务Rsync、Nginx、MySQL等的启动及停止专业脚本(使用chkconfig管理)。
3784)MySQL主从复制监控报警以及自动处理不复制故障的脚本。
3795)一键配置MySQL多实例、一键配置MySQL主从部署脚本。
3806)监控HTTP/MySQL/Rsync/NFS/Memcached等服务是否异常的生产脚本。
3817)一键软件安装及优化的脚本,比如LANMP、Linux一键优化,一键数据库安装、优化等。
3828)MySQL多实例启动脚本,分库、分表自动备份脚本。
3839)根据网络连接数以及根据Web日志PV封IP的脚本。
38410)监控网站的PV以及流量,并且对流量信息进行统计的脚本。
38511)检查Web服务器多个URL地址是否异常的脚本,要可以批量处理且通用。
38612)系统的基础优化一键优化的脚本。
38713)TCP连接状态及IP统计报警脚本。
38814)批量创建用户并设置随机8位密码的脚本。
389
390注:到此shell编程重要知识完,重在思路和多练习多实践并且熟悉Linux上的常用命令。
391
xxxxxxxxxx
281批量生成随机字符文件名
2成随机数的 7 种方法:
31)echo $RANDOM 范围是 0-32767
42)openssl rand -base64 100
53)date +%s%N
64)head /dev/urandom|cksum
75)uuidgen
86)cat /proc/sys/kernel/random/uuid
97)mkpasswd(yum install expect -y)
10mkpasswd -l 20 -d 10 -C 5 -c 3 -s 2
11-l 长度
12-d 数字
13-c 小写字母
14-C 大写字母
15-s 特殊字符
16
17echo "OLDBOY$RANDOM"|md5sum|tr "0-9" "m-z"|cut -c 2-11
18cat exam1.sh
19
20path=/data/testing
21[ -d $path ]||mkdir -p $path
22for n in {1..10}
23do
24 random=`echo "MEI$RANDOM"|md5sum|tr "0-9" "m-z"|cut -c 2-11`
25 touch $path/${random}_mei.txt
26done
27
28
xxxxxxxxxx
231批量改名
2将exam1中创建的文件中,文件名中mei字串改为test并将扩展名换为大写。
3先改一个:
4[root@foundation testing]# file=bdscsamccb_mei.txt
5[root@foundation testing]# echo ${file/mei.txt/test.TXT}
6bdscsamccb_test.TXT
7[root@foundation testing]# mv $file `echo ${file/mei.txt/test.TXT}`
8[root@foundation testing]# ls `echo ${file/mei.txt/test.TXT}` -l
9-rw-r--r--. 1 root root 0 Feb 4 15:50 bdscsamccb_test.TXT
10
11for循环
12
13dir=/data/testing
14for file in `ls $dir`;do
15 mv ${dir}/${file} `echo ${dir}\/${file/mei.txt/test.TXT}`
16done
17
18拼接
19[root@foundation testing]# ls *.TXT|awk -F "test.TXT" '{print "mv",$0,$1"mei.txt"}'|bash
20rename命令
21[root@foundation testing]# rename "mei.txt" "test.HTML" *.txt
22
23
xxxxxxxxxx
681批量创建特殊要求的用户
2用户mei01-mei10,并设置随机密码
3生成01-10
4echo {01..10}
5seq -w 10
6
7生成随机密码
8openssl rand -base64 100
9
10为用户设置密码
11echo "password" |passwd --stdin username
12chpasswd设置密码
13文件要满足下面格式
14username:passwd
15username:passwd
16
17使用循环
18exam]# cat exam3_1.sh
19
20for n in {1..10};do
21 pass=`openssl rand -base64 10`
22 useradd mei$n
23 echo $pass|passwd --stdin mei$n
24 echo -e "mei$n\t$passwd" >>./exam3_1.codebook
25done
26
27exam]# cat exam3_2.sh
28
29for n in `seq -w 11 15`;do
30 pass=`openssl rand -base64 10`
31 useradd mei$n
32 echo "mei$n:$pass" >>./exam3_2.codebook
33done
34chpasswd < ./exam3_2.codebool
35
36exam]# cat exam3_3.sh
37
38. /etc/init.d/functions
39if [ $UID -ne 0 ];then
40
41. /etc/init.d/functions
42if [ $UID -ne 0 ];then
43 echo -e "Permission denied\nneed account root exec the $0"
44 exit 1
45fi
46
47for n in {16..20};do
48 pass=`openssl rand -base64 10`
49 if [ `grep -w "mei$n" /etc/passwd |wc -l` -eq 0 ];then
50 useradd mei$n & >/dev/null &&\
51 echo $pass|passwd --stdin mei$n &>/dev/null &&\
52 echo -e "mei$n\t$pass" >>./exam3_3.codebook &&\
53 action "create mei$n user seccessful." /bin/true
54 else
55 action "create mei$n user false." /bin/false
56 fi
57done
58注意:如果使用循环,那么可以使用命令拼接的方式拼接出整个创建用户和设置密码的过程。
59
60echo stu{01..10}|tr " " "\n"|sed -r 's#(.*)#useradd \1 ; pass=$((RANDOM+10000000)); echo "$pass"|passwd --stdin \1; echo -e "\1 \t `echo "$pass"`">>/tmp/oldboy.log#g'|bash
61
62echo stu{11..12}|xargs -n1 useradd ;echo stu{11..12}:`cat /dev/urandom|tr -dc 0-9|fold -w8|head -1`|xargs -n1|tee -a pass.txt|chpasswd
63
64echo stu{21..30} | tr ' ' '\n' | sed -e 's/^/useradd /' -e 's/\(stu[0-9]\{2\}\)$/\1 \&\& echo "\1:`echo $[$RANDOM**3] | cut -c1-8`" | tee -a userInfo.txt | cut -d: -f2 | passwd --stdin \1/'|bash
65
66echo stu{01..10} |tr ' ' '\n'|sed -rn 's@^(.*)$@useradd \1 ; echo $RANDOM|md5sum|cut -c 1-8 >/data/\1;cat /data/\1|passwd --stdin \1@gp'|bash
67
68
xxxxxxxxxx
181扫描网络中存活的主机
2ping -c 2 -i 1 -w 3 172.25.0.55
3arping 172.25.0.55
4nmap -sP 172.25.0.0/24
5
6
7network="172.25.0."
8for n in {1..254};do
9 {
10 if `ping -c 1 -w 3 ${network}${n}` &>/dev/null
11 then
12 echo -e "${network}${n} is \e[40;32;1mup\e[0m"
13 else
14 echo -e "${network}${n} is \e[40;33;1mdown\e[0m"
15 fi
16 } &
17done
18
xxxxxxxxxx
2991解决DOS攻击
2写一个Shell脚本解决DOS攻击生产案例。
3请根据web日志或者或者网络连接数,监控当某个IP并发连接数或者短时内PV达到100(读者根据实际情况设定),即调用防火墙命令封掉对应的IP。
4
5封IP:iptables -I INPUT -s IP地址-j DROP。
6web日志或网络连接数:日志文件,netstat -an|grep -i EST>netstat.log,排序去重。
7判断pv或者链接数大于100,取出Ip让后封。
8netstat.log日志内容模拟
9Active Internet connections (servers and established)
10Proto Recv-Q Send-Q Local Address Foreign Address State
11tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
12tcp 0 0 115.29.49.213:80 117.136.27.254:13779 SYN_RECV
13tcp 0 0 115.29.49.213:80 113.97.117.157:1847 SYN_RECV
14tcp 0 0 115.29.49.213:80 113.97.117.157:1847 SYN_RECV
15tcp 0 0 115.29.49.213:80 113.97.117.157:1847 SYN_RECV
16tcp 0 0 115.29.49.213:80 113.97.117.157:1847 SYN_RECV
17tcp 0 0 115.29.49.213:80 113.97.117.157:1847 SYN_RECV
18tcp 0 0 115.29.49.213:80 113.97.117.157:1847 SYN_RECV
19tcp 0 0 115.29.49.213:80 113.97.117.157:1847 SYN_RECV
20tcp 0 0 115.29.49.213:80 113.97.117.157:1847 SYN_RECV
21tcp 0 0 115.29.49.213:80 113.97.117.157:1847 SYN_RECV
22tcp 0 0 115.29.49.213:80 113.97.117.157:1847 SYN_RECV
23tcp 0 0 115.29.49.213:80 113.97.117.157:1847 SYN_RECV
24tcp 0 0 115.29.49.213:80 113.97.117.157:1847 SYN_RECV
25tcp 0 0 115.29.49.213:80 113.97.117.157:1847 SYN_RECV
26tcp 0 0 115.29.49.213:80 113.97.117.157:1847 SYN_RECV
27tcp 0 0 115.29.49.213:80 113.97.117.157:1847 SYN_RECV
28tcp 0 0 115.29.49.213:80 113.97.117.157:1847 SYN_RECV
29tcp 0 0 115.29.49.213:80 113.97.117.157:1847 SYN_RECV
30tcp 0 0 115.29.49.213:80 113.97.117.157:1847 SYN_RECV
31tcp 0 0 115.29.49.213:80 113.97.117.157:1847 SYN_RECV
32tcp 0 0 115.29.49.213:80 113.97.117.157:1847 SYN_RECV
33tcp 0 0 115.29.49.213:80 113.97.117.157:1847 SYN_RECV
34tcp 0 0 115.29.49.213:80 113.97.117.157:1847 SYN_RECV
35tcp 0 0 115.29.49.213:80 113.97.117.157:1847 SYN_RECV
36tcp 0 0 115.29.49.213:80 113.97.117.157:1847 SYN_RECV
37tcp 0 0 115.29.49.213:80 113.97.117.157:1847 SYN_RECV
38tcp 0 0 115.29.49.213:80 113.97.117.157:1847 SYN_RECV
39tcp 0 0 115.29.49.213:80 113.97.117.157:1847 SYN_RECV
40tcp 0 0 115.29.49.213:80 117.136.40.20:19594 SYN_RECV
41tcp 0 0 115.29.49.213:80 117.136.40.20:19595 SYN_RECV
42tcp 0 0 115.29.49.213:80 121.236.219.69:45363 SYN_RECV
43tcp 0 0 0.0.0.0:21 0.0.0.0:* LISTEN
44tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
45tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN
46tcp 0 0 115.29.49.213:80 123.163.178.32:3009 ESTABLISHED
47tcp 0 0 115.29.49.213:80 123.163.178.32:3009 ESTABLISHED
48tcp 0 0 115.29.49.213:80 123.163.178.32:3009 ESTABLISHED
49tcp 0 0 115.29.49.213:80 123.163.178.32:3009 ESTABLISHED
50tcp 0 0 115.29.49.213:80 123.163.178.32:3009 ESTABLISHED
51tcp 0 0 115.29.49.213:80 123.163.178.32:3009 ESTABLISHED
52tcp 0 0 115.29.49.213:80 123.163.178.32:3009 ESTABLISHED
53tcp 0 0 115.29.49.213:80 123.163.178.32:3009 ESTABLISHED
54tcp 0 0 115.29.49.213:80 123.163.178.32:3009 ESTABLISHED
55tcp 0 0 115.29.49.213:80 123.163.178.32:3009 ESTABLISHED
56tcp 0 0 115.29.49.213:80 123.163.178.32:3009 ESTABLISHED
57tcp 0 0 115.29.49.213:80 123.163.178.32:3009 ESTABLISHED
58tcp 0 0 115.29.49.213:80 123.163.178.32:3009 ESTABLISHED
59tcp 0 0 115.29.49.213:80 123.163.178.32:3009 ESTABLISHED
60tcp 0 0 115.29.49.213:80 123.163.178.32:3009 ESTABLISHED
61tcp 0 0 115.29.49.213:80 123.163.178.32:3009 ESTABLISHED
62tcp 0 0 115.29.49.213:80 123.163.178.32:3009 ESTABLISHED
63tcp 0 0 115.29.49.213:80 123.163.178.32:3009 ESTABLISHED
64tcp 0 0 115.29.49.213:80 123.163.178.32:3009 ESTABLISHED
65tcp 0 0 115.29.49.213:80 123.163.178.32:3009 ESTABLISHED
66tcp 0 0 115.29.49.213:80 123.163.178.32:3009 ESTABLISHED
67tcp 0 0 115.29.49.213:80 123.163.178.32:3009 ESTABLISHED
68tcp 0 0 115.29.49.213:80 123.163.178.32:3009 ESTABLISHED
69tcp 0 0 115.29.49.213:80 123.163.178.32:3009 ESTABLISHED
70tcp 0 0 115.29.49.213:80 123.163.178.32:3009 ESTABLISHED
71tcp 0 0 115.29.49.213:80 117.136.1.202:21158 TIME_WAIT
72tcp 0 0 115.29.49.213:80 220.191.224.154:48550 ESTABLISHED
73tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
74tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
75tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
76tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
77tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
78tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
79tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
80tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
81tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
82tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
83tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
84tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
85tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
86tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
87tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
88tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
89tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
90tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
91tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
92tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
93tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
94tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
95tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
96tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
97tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
98tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
99tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
100tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
101tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
102tcp 0 0 115.29.49.213:80 27.17.23.22:51256 FIN_WAIT2
103tcp 0 0 115.29.49.213:80 218.242.161.183:50519 FIN_WAIT2
104tcp 0 0 115.29.49.213:80 223.104.12.101:49900 TIME_WAIT
105tcp 0 0 115.29.49.213:80 140.206.64.90:62291 TIME_WAIT
106tcp 0 0 115.29.49.213:80 120.237.97.10:54195 ESTABLISHED
107tcp 0 0 115.29.49.213:80 49.80.146.230:13453 FIN_WAIT2
108tcp 0 0 115.29.49.213:80 117.136.1.202:21158 TIME_WAIT
109tcp 0 0 115.29.49.213:80 220.191.224.154:48550 ESTABLISHED
110tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
111tcp 0 0 115.29.49.213:80 27.17.23.22:51256 FIN_WAIT2
112tcp 0 0 115.29.49.213:80 218.242.161.183:50519 FIN_WAIT2
113tcp 0 0 115.29.49.213:80 223.104.12.101:49900 TIME_WAIT
114tcp 0 0 115.29.49.213:80 140.206.64.90:62291 TIME_WAIT
115tcp 0 0 115.29.49.213:80 120.237.97.10:54195 ESTABLISHED
116tcp 0 0 115.29.49.213:80 49.80.146.230:13453 FIN_WAIT2
117tcp 0 0 115.29.49.213:80 117.136.1.202:21158 TIME_WAIT
118tcp 0 0 115.29.49.213:80 220.191.224.154:48550 ESTABLISHED
119tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
120tcp 0 0 115.29.49.213:80 27.17.23.22:51256 FIN_WAIT2
121tcp 0 0 115.29.49.213:80 218.242.161.183:50519 FIN_WAIT2
122tcp 0 0 115.29.49.213:80 223.104.12.101:49900 TIME_WAIT
123tcp 0 0 115.29.49.213:80 140.206.64.90:62291 TIME_WAIT
124tcp 0 0 115.29.49.213:80 120.237.97.10:54195 ESTABLISHED
125tcp 0 0 115.29.49.213:80 49.80.146.230:13453 FIN_WAIT2
126tcp 0 0 115.29.49.213:80 117.136.1.202:21158 TIME_WAIT
127tcp 0 0 115.29.49.213:80 220.191.224.154:48550 ESTABLISHED
128tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
129tcp 0 0 115.29.49.213:80 27.17.23.22:51256 FIN_WAIT2
130tcp 0 0 115.29.49.213:80 218.242.161.183:50519 FIN_WAIT2
131tcp 0 0 115.29.49.213:80 223.104.12.101:49900 TIME_WAIT
132tcp 0 0 115.29.49.213:80 140.206.64.90:62291 TIME_WAIT
133tcp 0 0 115.29.49.213:80 120.237.97.10:54195 ESTABLISHED
134tcp 0 0 115.29.49.213:80 49.80.146.230:13453 FIN_WAIT2
135tcp 0 0 115.29.49.213:80 117.136.1.202:21158 TIME_WAIT
136tcp 0 0 115.29.49.213:80 220.191.224.154:48550 ESTABLISHED
137tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
138tcp 0 0 115.29.49.213:80 27.17.23.22:51256 FIN_WAIT2
139tcp 0 0 115.29.49.213:80 218.242.161.183:50519 FIN_WAIT2
140tcp 0 0 115.29.49.213:80 223.104.12.101:49900 TIME_WAIT
141tcp 0 0 115.29.49.213:80 140.206.64.90:62291 TIME_WAIT
142tcp 0 0 115.29.49.213:80 120.237.97.10:54195 ESTABLISHED
143tcp 0 0 115.29.49.213:80 49.80.146.230:13453 FIN_WAIT2
144tcp 0 0 115.29.49.213:80 117.136.1.202:21158 TIME_WAIT
145tcp 0 0 115.29.49.213:80 220.191.224.154:48550 ESTABLISHED
146tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
147tcp 0 0 115.29.49.213:80 27.17.23.22:51256 FIN_WAIT2
148tcp 0 0 115.29.49.213:80 218.242.161.183:50519 FIN_WAIT2
149tcp 0 0 115.29.49.213:80 223.104.12.101:49900 TIME_WAIT
150tcp 0 0 115.29.49.213:80 140.206.64.90:62291 TIME_WAIT
151tcp 0 0 115.29.49.213:80 120.237.97.10:54195 ESTABLISHED
152tcp 0 0 115.29.49.213:80 49.80.146.230:13453 FIN_WAIT2
153tcp 0 0 115.29.49.213:80 117.136.1.202:21158 TIME_WAIT
154tcp 0 0 115.29.49.213:80 220.191.224.154:48550 ESTABLISHED
155tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
156tcp 0 0 115.29.49.213:80 27.17.23.22:51256 FIN_WAIT2
157tcp 0 0 115.29.49.213:80 218.242.161.183:50519 FIN_WAIT2
158tcp 0 0 115.29.49.213:80 223.104.12.101:49900 TIME_WAIT
159tcp 0 0 115.29.49.213:80 140.206.64.90:62291 TIME_WAIT
160tcp 0 0 115.29.49.213:80 120.237.97.10:54195 ESTABLISHED
161tcp 0 0 115.29.49.213:80 49.80.146.230:13453 FIN_WAIT2
162tcp 0 0 115.29.49.213:80 117.136.1.202:21158 TIME_WAIT
163tcp 0 0 115.29.49.213:80 220.191.224.154:48550 ESTABLISHED
164tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
165tcp 0 0 115.29.49.213:80 27.17.23.22:51256 FIN_WAIT2
166tcp 0 0 115.29.49.213:80 218.242.161.183:50519 FIN_WAIT2
167tcp 0 0 115.29.49.213:80 223.104.12.101:49900 TIME_WAIT
168tcp 0 0 115.29.49.213:80 140.206.64.90:62291 TIME_WAIT
169tcp 0 0 115.29.49.213:80 120.237.97.10:54195 ESTABLISHED
170tcp 0 0 115.29.49.213:80 49.80.146.230:13453 FIN_WAIT2
171tcp 0 0 115.29.49.213:80 117.136.1.202:21158 TIME_WAIT
172tcp 0 0 115.29.49.213:80 220.191.224.154:48550 ESTABLISHED
173tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
174tcp 0 0 115.29.49.213:80 27.17.23.22:51256 FIN_WAIT2
175tcp 0 0 115.29.49.213:80 218.242.161.183:50519 FIN_WAIT2
176tcp 0 0 115.29.49.213:80 223.104.12.101:49900 TIME_WAIT
177tcp 0 0 115.29.49.213:80 140.206.64.90:62291 TIME_WAIT
178tcp 0 0 115.29.49.213:80 120.237.97.10:54195 ESTABLISHED
179tcp 0 0 115.29.49.213:80 49.80.146.230:13453 FIN_WAIT2
180tcp 0 0 115.29.49.213:80 117.136.1.202:21158 TIME_WAIT
181tcp 0 0 115.29.49.213:80 220.191.224.154:48550 ESTABLISHED
182tcp 0 0 115.29.49.213:80 183.32.61.109:5600 ESTABLISHED
183tcp 0 0 115.29.49.213:80 27.17.23.22:51256 FIN_WAIT2
184tcp 0 0 115.29.49.213:80 218.242.161.183:50519 FIN_WAIT2
185tcp 0 0 115.29.49.213:80 223.104.12.101:49900 TIME_WAIT
186tcp 0 0 115.29.49.213:80 140.206.64.90:62291 TIME_WAIT
187tcp 0 0 115.29.49.213:80 120.237.97.10:54195 ESTABLISHED
188tcp 0 0 115.29.49.213:80 49.80.146.230:13453 FIN_WAIT2
189tcp 0 0 115.29.49.213:80 113.104.25.50:56714 FIN_WAIT2
190tcp 0 0 115.29.49.213:80 101.226.89.193:41639 ESTABLISHED
191tcp 0 0 115.29.49.213:80 119.147.225.185:58321 TIME_WAIT
192tcp 0 0 115.29.49.213:80 54.183.177.237:64129 TIME_WAIT
193tcp 0 0 115.29.49.213:80 120.198.202.48:41960 ESTABLISHED
194tcp 0 1 115.29.49.213:80 119.127.188.242:38843 FIN_WAIT1
195tcp 0 0 115.29.49.213:34081 223.4.9.70:80 TIME_WAIT
196tcp 0 0 115.29.49.213:80 58.223.4.14:46716 FIN_WAIT2
197tcp 0 0 115.29.49.213:80 122.90.74.255:12177 FIN_WAIT2
198tcp 0 0 115.29.49.213:80 59.53.166.165:62253 ESTABLISHED
199tcp 0 0 115.29.49.213:80 219.133.40.13:34113 ESTABLISHED
200tcp 0 0 115.29.49.213:80 222.175.140.230:29902 TIME_WAIT
201tcp 0 0 115.29.49.213:80 54.77.101.105:49967 TIME_WAIT
202tcp 0 0 115.29.49.213:80 54.207.37.100:63364 TIME_WAIT
203tcp 0 0 115.29.49.213:80 125.118.62.149:61840 FIN_WAIT2
204tcp 0 0 115.29.49.213:80 112.117.173.124:50367 ESTABLISHED
205tcp 0 0 115.29.49.213:80 120.194.52.156:2752 FIN_WAIT2
206tcp 0 0 115.29.49.213:80 114.106.68.5:54231 ESTABLISHED
207tcp 0 0 115.29.49.213:80 27.154.82.136:3013 FIN_WAIT2
208tcp 0 0 115.29.49.213:80 182.245.82.46:55306 FIN_WAIT2
209tcp 0 0 115.29.49.213:80 117.92.15.157:29926 TIME_WAIT
210tcp 0 0 115.29.49.213:80 163.179.63.118:62371 ESTABLISHED
211tcp 0 777 115.29.49.213:80 106.59.15.116:1673 ESTABLISHED
212tcp 0 777 115.29.49.213:80 117.22.215.8:1382 ESTABLISHED
213tcp 0 0 115.29.49.213:80 114.217.182.123:51960 TIME_WAIT
214tcp 0 0 115.29.49.213:80 118.242.18.177:24615 ESTABLISHED
215tcp 0 0 115.29.49.213:80 220.191.224.154:23380 TIME_WAIT
216tcp 0 0 115.29.49.213:80 119.78.240.118:59230 FIN_WAIT2
217tcp 0 0 115.29.49.213:80 218.83.11.138:52739 TIME_WAIT
218tcp 0 0 115.29.49.213:80 122.70.113.17:57809 TIME_WAIT
219tcp 0 0 115.29.49.213:80 121.235.160.76:2487 TIME_WAIT
220tcp 0 0 115.29.49.213:80 111.175.68.97:49920 TIME_WAIT
221tcp 0 1 115.29.49.213:80 221.137.78.206:54593 FIN_WAIT1
222tcp 0 0 115.29.49.213:80 119.121.180.245:14524 TIME_WAIT
223tcp 0 0 115.29.49.213:80 123.151.42.52:55816 ESTABLISHED
224tcp 0 0 115.29.49.213:80 120.192.146.19:26133 FIN_WAIT2
225tcp 0 0 115.29.49.213:80 113.107.56.233:45496 TIME_WAIT
226tcp 0 1 115.29.49.213:80 119.249.255.140:1664 FIN_WAIT1
227tcp 0 0 115.29.49.213:80 222.132.131.91:5451 ESTABLISHED
228tcp 0 0 115.29.49.213:80 183.32.61.109:5712 FIN_WAIT2
229tcp 0 52 115.29.49.213:22 119.2.28.4:13185 ESTABLISHED
230tcp 0 0 115.29.49.213:80 221.179.140.171:48647 TIME_WAIT
231tcp 0 0 115.29.49.213:80 111.161.61.49:60865 ESTABLISHED
232tcp 0 0 115.29.49.213:80 58.247.119.17:64369 TIME_WAIT
233tcp 0 0 115.29.49.213:80 121.35.208.125:50139 FIN_WAIT2
234tcp 0 0 115.29.49.213:80 118.242.18.177:24619 ESTABLISHED
235tcp 0 0 115.29.49.213:80 111.17.45.226:5492 TIME_WAIT
236tcp 0 0 115.29.49.213:80 114.250.252.127:50802 TIME_WAIT
237tcp 0 0 115.29.49.213:80 49.80.146.230:13424 TIME_WAIT
238tcp 0 0 115.29.49.213:80 113.241.77.56:18509 TIME_WAIT
239tcp 0 0 115.29.49.213:80 101.226.61.186:57302 ESTABLISHED
240tcp 0 0 115.29.49.213:80 59.38.233.215:18224 FIN_WAIT2
241tcp 0 0 115.29.49.213:80 222.70.73.234:52968 FIN_WAIT2
242tcp 0 0 115.29.49.213:80 114.100.142.6:3171 TIME_WAIT
243tcp 0 0 115.29.49.213:80 27.18.159.160:50095 TIME_WAIT
244tcp 0 0 115.29.49.213:80 122.64.91.155:35708 ESTABLISHED
245tcp 0 0 115.29.49.213:80 116.90.81.14:52978 TIME_WAIT
246tcp 0 0 115.29.49.213:80 124.227.212.140:38460 ESTABLISHED
247tcp 0 0 115.29.49.213:80 223.242.103.128:3997 TIME_WAIT
248tcp 0 0 115.29.49.213:80 113.116.147.94:50073 ESTABLISHED
249tcp 0 0 115.29.49.213:80 112.117.173.124:50366 TIME_WAIT
250tcp 0 0 115.29.49.213:80 122.227.191.174:4833 FIN_WAIT2
251tcp 0 0 115.29.49.213:80 42.95.73.152:51472 ESTABLISHED
252tcp 0 0 115.29.49.213:80 58.215.136.140:56794 TIME_WAIT
253tcp 0 0 115.29.49.213:80 116.90.81.14:52974 TIME_WAIT
254tcp 0 0 115.29.49.213:80 223.100.156.53:59779 TIME_WAIT
255tcp 0 0 115.29.49.213:80 125.112.122.240:44893 FIN_WAIT2
256tcp 0 0 115.29.49.213:80 14.211.169.36:26342 TIME_WAIT
257tcp 0 0 115.29.49.213:80 114.250.252.127:50809 TIME_WAIT
258tcp 0 0 115.29.49.213:80 14.157.228.55:3184 FIN_WAIT2
259tcp 0 0 115.29.49.213:80 112.113.160.225:3029 TIME_WAIT
260tcp 0 0 115.29.49.213:80 14.17.11.196:33403 ESTABLISHED
261tcp 0 0 115.29.49.213:80 36.249.78.78:2615 FIN_WAIT2
262tcp 0 0 115.29.49.213:80 114.105.192.151:1312 ESTABLISHED
263tcp 0 0 115.29.49.213:80 118.242.18.177:24616 FIN_WAIT2
264tcp 0 0 115.29.49.213:80 27.191.14.232:50272 FIN_WAIT2
265tcp 0 0 115.29.49.213:80 119.187.139.167:1779 FIN_WAIT2
266tcp 0 0 115.29.49.213:80 218.75.147.14:5195 TIME_WAIT
267tcp 0 0 115.29.49.213:80 1.204.201.226:12694 ESTABLISHED
268
269
270awk '{S[$1]++}END{for(key in S) print S[key],key}' access_2020-1-8.log|sort -rn|head >/tmp/ip.log
271while read line
272do
273ip=`echo $line|awk '{print $2}'`
274count=`echo $line|awk '{print $1}'`
275if [ $count -gt 100 -a `grep "$ip" /tmp/drop.log|wc -l` -lt 1 ]
276then
277iptables -I INPUT -s $ip -j DROP &&\
278echo "$ip" >>/tmp/drop.log
279else
280echo "$ip" >>/tmp/accept.log
281fi
282done</tmp/ip.log
283
284
285awk '/ESTAB/{print $0}' netstat.log |awk -F "[ :]+" '{print $(NF-3)}'|sort|uniq -c|sort -rn|head >
286/tmp/ip.log
287while read line
288do
289 ip=`echo $line|awk '{print $2}'`
290 count=`echo $line|awk '{print $1}'`
291 if [ $count -gt 10 -a `grep "$ip" /tmp/drop.log|wc -l` -lt 1 ]
292 then
293 iptables -I INPUT -s $ip -j DROP &&\
294 echo "$ip" >>/tmp/drop.log
295 else
296 echo "$ip" >>/tmp/accept.log
297 fi
298done</tmp/ip.log
299
xxxxxxxxxx
171数据库分库备份脚本
2常规备份
3mysqldump -B test mei|gzip >bak.sql.gz
4分库备份:
5mysqldump -B mei|gzip >bak.sql.gz
6mysqldump -B test|gzip >bak.sql.gz
7
8
9path=/backup
10mysql="mysql -uroot -ptest"
11mysqldump="mysqldump -uroot -ptest"
12[ -d $path ]||mkdir $path -p
13for dbname in `$mysql -e "show databases;" 2>/dev/null|grep -v _schema|sed 1d`
14do
15$mysqldump -B $dbname|gzip >$path/${dbname}_$(date +%F).sql.gz 2>/dev/null
16done
17
xxxxxxxxxx
211mysql数据库分库分表备份
2mysqldump mei t1 t2|gzip >bak.sql.gz
3mysqldump -B mei |gzip >bak.sql.gz:
4mysqldump mei t1
5mysqldump mei t2
6mysqldump mei t3
7
8
9path=/backup
10[ -d $path ]||mkdir $path -p
11for dbname in `mysql -e "show databases;"|grep -v _schema|sed 1d`
12do
13 for tname in `mysql -e "show tables from $dbname;"|sed 1d`
14 do
15 if [ "$dbname" = "mysql" ];then
16 mysqldump --skip-lock-tables $dbname $tname|gzip >$path/${dbname}-${tname}.sql.gz
17 else
18 mysqldump $dbname $tname|gzip >$path/${dbname}-${tname}.sql.gz
19 fi
20done
21
xxxxxxxxxx
1581SSH免交互批量分发脚本(CentOS6)
2
3# mzy 2019-09-22 Add Features
4# another: meizy
5# contact QQ:359462962
6export PATH=/bin:$PATH
7
8# output command help manual
9function output_help(){
10 echo -e "Usage :\n\n--help|-h\tget command help.\n\te.g:batchsent.sh --help\n\ncommand public key distribution:\n\t\e[40;32;1mbatchsent.sh [ip/hostname]\e[0;0;0m\n\nexample:\n\te.g:batchsent.sh 192.168.0.1\n\tor use default batchsent public key:\n\te.g:batchsent.sh\n\nexplanation:\n\t1.hostname needs to be able to be resolved IP address.\n\t2.Run this script need to have root privileges.\n\t3.The current system needs to be able to use yum install sshpass software."
11}
12
13# Check whether the IP address or host name of the obvious error
14function check_ip_format(){
15 ip=$1
16 echo ${ip} |sed -r 's#([0-9]+).#\1#g' |test -n "`sed -n '/^[0-9][0-9]*$/p'`" >/dev/null 2>&1
17 if [ $? -eq 0 ];then
18 count=`echo ${ip}|sed -r 's#([0-9]+).#\1\n#g'|grep -v '^$' | wc -l`
19 if [ ${count} -eq 4 ];then
20 return 0
21 else
22 echo -e "\e[40;31;1merror\e[0;0;0m:this host(${ip}) ip---\e[40;31;1mThere are obvious errors\e[0;0;0m"
23 output_help
24 return 1
25 fi
26 else
27 ping -c 3 ${ip} >/dev/null 2>&1
28 if [ $? -eq 0 ];then
29 return 0
30 else
31 echo -e "\e[40;31;1merror\e[0;0;0m:this host(${ip}) name---\e[40;31;1mcan not be resolved\e[0;0;0m"
32 output_help
33 return 1
34 fi
35 fi
36}
37
38# Single IP or host public key distribution
39function sent_pub_key(){
40 ip=$1
41 sshpass -prewqrewsdsds ssh "-o StrictHostKeyChecking=no" root@${ip} hostname >/dev/null 2>&1
42 if [ $? -eq 0 ];then
43 echo -e "${ip} \tpublic keys \e[40;34;1malready exist\e[0;0;0m,can be used normally."
44 else
45 ping -c 3 ${ip} >/dev/null 2>&1
46 if [ $? -eq 0 ];then
47 sshpass -ptemplate ssh-copy-id -i /root/.ssh/id_rsa.pub "-o StrictHostKeyChecking=no root@${ip}" >/dev/null 2>&1
48 echo -e "${ip} \tpublic keys \e[40;32;1msent successfully\e[0;0;0m,can be used normally."
49 else
50 echo -e "${ip} \tthis host(${ip}) is \e[40;31;1mnot online\e[0;0;0m"
51 fi
52 fi
53}
54
55# define default host
56function default_batch_sent_pub_key(){
57 for ip_addr in 172.16.0.{31,41,51,71,5,6,7,8,9};do
58 sent_pub_key ${ip_addr}
59 done
60}
61
62# default ip or host public key distribution
63function batch_sent_pub_key(){
64 ip_addr=$1
65 sent_pub_key ${ip_addr}
66}
67
68# check the packages needed
69function check_sshpass(){
70 if [ ! -f /usr/bin/sshpass ];then
71 yum install -y sshpass >/dev/null 2>&1
72 if [ $? -ne 0 ];then
73 echo -e "\e[40;31;1merror\e[0;0;0m:install sshpass failed,check to see if the current user has root privileges."
74 exit 1
75 fi
76 fi
77}
78
79# check -h or --help args
80function check_help_args(){
81 args=$1
82 case ${args} in
83 "--help")
84 output_help
85 exit 1
86 ;;
87 "-h")
88 output_help
89 exit 1
90 ;;
91 esac
92}
93
94# The implementation of public key distribution by check_help_args function
95# In this way the code is more complex, not recommended
96function exec_batch_sent_by_check_help_args(){
97 check_help_args $1
98 if [ $# -eq 1 ];then
99 check_ip_format $1
100 if [ $? -eq 0 ];then
101 batch_sent_pub_key $1
102 fi
103 fi
104}
105
106# The implementation of public key distribution by if statment
107# Such code simpler, recommended
108function exec_batch_sent_by_if_statment(){
109 if [ $# -eq 1 ];then
110 if [ $1 == '--help' ] || [ $1 == '-h' ];then
111 output_help
112 else
113 check_ip_format $1
114 if [ $? -eq 0 ];then
115 batch_sent_pub_key $1
116 fi
117 fi
118 fi
119}
120
121# Check the generated keys
122function check_the_generated_keys(){
123 if [ -f /root/.ssh/id_rsa -a -f /root/.ssh/id_rsa.pub ];then
124 return 0
125 else
126 ssh-keygen -t rsa -f /root/.ssh/id_rsa -N ""
127 if [ $? -eq 0 ];then
128 return 0
129 else
130 echo -e "\e[40;31;1merror\e[0;0;0m:install sshpass failed,check to see if the current user has root privileges."
131 return 1
132 fi
133 fi
134}
135
136# main
137if [ $# -eq 0 ];then
138 check_sshpass
139 check_the_generated_keys
140 if [ $? -eq 0 ];then
141 default_batch_sent_pub_key
142 else
143 exit 1
144 fi
145else
146 until [ $# -eq 0 ];do
147 check_sshpass
148 check_the_generated_keys
149 if [ $? -eq 0 ];then
150 exec_batch_sent_by_if_statment $1
151 else
152 exit 1
153 fi
154 shift
155 done
156fi
157
158
xxxxxxxxxx
421破解RANDOM随机数
2已知下面的字符串是通过RANDOM随机数变量md5sum后,再截取一部分连续字符串的结果,请破解这些字符串对应的使用md5sum处理前的RANDOM对应的数字?
321029299
400205d1c
5a3da1677
61f6d12dd
7890684b
8RANDOM范围:0-32767,需要把0-32767都全部用md5加密。
9
10
11
12array=(
1321029299
1400205d1c
15a3da1677
161f6d12dd
17890684b
18)
19Funmd5(){
20 for n in {0..32767};do
21 echo -e "$n\t`echo $n|md5sum`" >>/tmp/md5sum1.log &
22 done
23}
24FunJudge(){ # 速度要相对快些
25 char="`echo ${array[*]}|tr " " "|"`"
26 egrep "$char" /tmp/md5sum1.log
27}
28function judge(){
29 for n in ${array[*]};do
30 find=`grep $n /tmp/md5sum.log`
31 if [ `grep $n $find|wc -l` -eq 1 ];then
32 echo $find
33 fi
34 done
35}
36main(){
37 Funmd5
38 FunJudge
39}
40main
41
42
xxxxxxxxxx
391批量检查多个网站是否正常
2要求:
31、使用shell数组方法实现,检测策略尽量模拟用户访问。
42、每10秒钟做一次所有的检测,无法访问的输出报警。
53、待检测的地址如下
6www.mei.com
7http://10.0.0.7
8
9
10. /etc/init.d/functions
11URL=(
12http://www.mei.com
13http://10.0.0.7
14)
15CheckUrl(){
16 wget -T 5 --spider -o /dev/null -q $1
17 if [ $? -eq 0 ]
18 then
19 action "$1 is successful" /bin/true
20 else
21 action "$1 is failure" /bin/false
22 fi
23}
24DealUrl(){
25 for url in ${URL[*]}
26 do
27 CheckUrl $url
28 done
29}
30main(){
31 while true
32 do
33 DealUrl
34 sleep 2
35 echo "---------------------------------------------"
36 done
37}
38main
39
xxxxxxxxxx
391单词字母去重复并排序
2用shell 处理以下内容
31、按单词出现频率降序排序!
42、按字母出现频率降序排序!
5cat test.log
6the squid project provides a number of resources to assist users design,implement and support squid installations. Please browse the documentation and support sections for more infomation,by oldboy training.
7
8按词出现频率
9tr " ," "\n" < test.log | sort | uniq -c | sort -rn
10
11tr " ," "\n" < test.log | awk '{S[$1]++}END{for (k in S)print S[k],k}'|sort -rn
12
13xargs -n1 < test.log | awk '{S[$1]++}END{for (k in S)print S[k],k}'|sort -rn
14
15tr ",." " " <test.log|xargs -n 1|sort|uniq -c|sort -rn|head
16
17tr ",." " " <test.log|xargs -n 1|awk '{S[$1]++}END{for(key in S)print S[key],key}'|sort -rn|head
18
19awk -F "[,. ]+" '{for(i=1;i<=NF;i++)S[$i]++}END{for(key in S)print S[key],key}' test.log |sort -rn|head
20
21awk -F "[ ,.]+" '{for(i=1;i<NF;i++)S[$i]++}END{for(k in S)print S[k],k}' test.log | sort -rn
22
23按字母出现频率
24grep -o "[^ ]" test.log | sort | uniq -c | sort -rn
25
26grep -o "[^ ]" test.log | awk '{S[$1]++}END{for (k in S)print S[k],k}'|sort -rn
27
28tr "{ |,|.}" "\n"<test.log|awk -F "" '{for(i=1;i<=NF;i++)array[$i]++}END{for(key in array)print array[key],key|"sort -nr"}'
29
30tr "[ ,.]" "\n"<test.log|awk '{for(i=1; i<=length($0); i++) ++S[substr($0,i,1)]} END {for(a in S) print S[a], a|"sort -rn"}'
31
32cat test.log|sed 's# ##g'|sed -r 's#(.)#\1\n#g'|sort|uniq -c|sort -rn -k1
33
34cat test.log|sed 's# ##g'|awk -F "" '{for(n=1;n<=NF;n++) print $n}'|sort|uniq -c|sort -k1 -nr
35
36sed 's#[ ,\.]##g' test.log | awk -F "" '{for(i=1;i<NF;i++)S[$i]++}END{for(k in S)print S[k],k}'
37
38
39
xxxxxxxxxx
321批量管理和文件分发脚本
23 台机器A、B、C,实现从A 到B 和C 免秘钥登录,然后开发脚本实现,批量管理远程主机(执行任意命令),批量分发本地任意文件到远端任意路径下。
3
4分发脚本:
5
6. /etc/init.d/functions
7if [ $# -ne 2 ]
8 then
9 echo "usage:$0 localdir remotedir"
10 exit 1
11fi
12for n in 8 41 42 43
13do
14 scp -rp $1 172.25.0.$n:$2 &>/dev/null
15 if [ $? -eq 0 ]
16 then
17 action "172.25.0.$n is successful" /bin/true
18 else
19 action "172.25.0.$n is failure" /bin/false
20 fi
21done
22查看脚本:
23
24if [ $# -ne 1 ];then
25 echo "usage:$0 cmd"
26 exit 1
27fi
28for n in 55 30 35;do
29 echo "--------172.25.0.$n---------"
30 ssh 172.25.0.$n $1
31done
32
xxxxxxxxxx
1361mysql服务启动停止脚本
2
3# chkconfig: 2345 20 80
4lockfile=/var/lock/subsys/mysqld
5. /etc/init.d/functions
6mysqld_pid_file_path="/application/mysql/data/web01.pid"
7mysqld_safe=/application/mysql/bin/mysqld_safe
8
9start(){
10 /bin/sh $mysqld_safe --datadir=/application/mysql/data --pid-file=$mysqld_pid_file_path &>/dev/null &
11 retval=$?
12 if [ $retval -eq 0 ]
13 then
14 action "mysql startup ok" /bin/true
15 touch $lockfile
16 return $retval
17 else
18 action "mysql startup fail" /bin/false
19 return $retval
20 fi
21}
22stop(){
23 if test -s "$mysqld_pid_file_path"
24 then
25 mysqld_pid=`cat $mysqld_pid_file_path`
26 if (kill -0 $mysqld_pid &>/dev/null)
27 then
28 kill $mysqld_pid
29 retval=$?
30 if [ $retval -eq 0 ]
31 then
32 action "mysql stop ok" /bin/true
33 rm $lockfile
34 return $retval
35 else
36 action "mysql stop fail" /bin/false
37 return $retval
38 fi
39 else
40 echo " mysqld process is not exist."
41 return 2
42 fi
43 else
44 echo "$mysqld_pid_file_path is not exist,or mysqld does not startup."
45 fi
46}
47case "$1" in
48 start)
49 start
50 retval=$?
51 ;;
52 stop)
53 stop
54 retval=$?
55 ;;
56 restart)
57 stop
58 sleep 2
59 start
60 retval=$?
61 ;;
62 *)
63 echo "usage:$0 {start|stop|restart}"
64 exit 1
65esac
66exit $retval
67
68改进
69
70# chkconfig: 2345 20 80
71lockfile=/var/lock/subsys/mysqld
72. /etc/init.d/functions
73mysqld_pid_file_path="/application/mysql/data/web01.pid"
74mysqld_safe=/application/mysql/bin/mysqld_safe
75
76start(){
77 /bin/sh $mysqld_safe --datadir=/application/mysql/data --pid-file=$mysqld_pid_file_path &>/dev/null &
78 retval=$?
79 sleep 2
80 if [ $retval -eq 0 ]
81 then
82 action "mysql startup ok" /bin/true
83 touch $lockfile
84 return $retval
85 else
86 action "mysql startup fail" /bin/false
87 return $retval
88 fi
89}
90stop(){
91 if test -s "$mysqld_pid_file_path"
92 then
93 mysqld_pid=`cat $mysqld_pid_file_path`
94 if (kill -0 $mysqld_pid &>/dev/null)
95 then
96 kill $mysqld_pid
97 retval=$?
98 sleep 2
99 if [ $retval -eq 0 ]
100 then
101 action "mysql stop ok" /bin/true
102 rm $lockfile
103 return $retval
104 else
105 action "mysql stop fail" /bin/false
106 return $retval
107 fi
108 else
109 echo " mysqld process is not exist."
110 return 2
111 fi
112 else
113 echo "$mysqld_pid_file_path is not exist,or mysqld does not startup."
114 fi
115}
116case "$1" in
117 start)
118 start
119 retval=$?
120 ;;
121 stop)
122 stop
123 retval=$?
124 ;;
125 restart)
126 stop
127 sleep 2
128 start
129 retval=$?
130 ;;
131 *)
132 echo "usage:$0 {start|stop|restart}"
133 exit 1
134esac
135exit $retval
136
在linux下fd叫做文件描述符,在window下fd叫做句柄,所以这就说明了为什么在官方文档中fileno
解释是Return the file descriptor or handle used by the connection.
在内核中每一个打开的文件都需要由3种数据结构来进行维护。
根据文中内容,这三种数据结构分别为:打开文件描述符表、打开文件表、inode节点
1.每个进程对应一张打开文件描述符表,这是进程级数据结构,也就是每一个进程都各自有这样一个数据结构;
2.内核维持一张打开文件表,文件表由多个文件表项组成,这是系统级数据结构,也就是说这样的数据结构是针对于整个内核而言的,每个进程都可共享的;
3.每个打开的文件对应一个i节点(i-node)数据结构(Linux下只有i节点没有v节点),由于这是每一个打开的文件与之对应的,因此这也是一个系统级数据结构,存在于内核中,非进程所独有。
https://www.cnblogs.com/lwyeric/p/13598704.html
xxxxxxxxxx
31from multiprocessing import Pipe
2rpipe, wpipe = Pipe(duplex=False)
3print rpipe.fileno() #这个就得到的是fd
xxxxxxxxxx
51[root@comptserver ~ ]# ls -al /dev | grep fd
2lrwxrwxrwx. 1 root root 13 Aug 31 09:40 fd -> /proc/self/fd
3lrwxrwxrwx. 1 root root 15 Aug 31 09:40 stderr -> /proc/self/fd/2
4lrwxrwxrwx. 1 root root 15 Aug 31 09:40 stdin -> /proc/self/fd/0
5lrwxrwxrwx. 1 root root 15 Aug 31 09:40 stdout -> /proc/self/fd/1
https://www.cnblogs.com/alan666/p/8311890.html
xxxxxxxxxx
151[root@comptserver ~ ]# lsof +d /root
2COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
3bash 3735 root cwd DIR 253,0 4096 100663425 /root
4sftp-serv 3751 root cwd DIR 253,0 4096 100663425 /root
5bash 4003 root cwd DIR 253,0 4096 100663425 /root
6sftp-serv 4034 root cwd DIR 253,0 4096 100663425 /root
7vim 25909 root cwd DIR 253,0 4096 100663425 /root
8vim 25909 root 6u REG 253,0 12288 101335674 /root/.docker_config.txt.swp
9lsof 26796 root cwd DIR 253,0 4096 100663425 /root
10lsof 26797 root cwd DIR 253,0 4096 100663425 /root
11
12
13[root@comptserver ~ ]# exec 6>fd6.log
14[root@comptserver ~ ]# echo "this is fd6.log" 1>&6
15
xxxxxxxxxx
51[root@comptserver ~ ]# lsof -a -p $$ -d 0,1,2
2COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
3bash 4003 root 0u CHR 136,1 0t0 4 /dev/pts/1
4bash 4003 root 1u CHR 136,1 0t0 4 /dev/pts/1
5bash 4003 root 2u CHR 136,1 0t0 4 /dev/pts/1
xxxxxxxxxx
111[root@comptserver ~ ]# exec 1>fd1.log
2[root@comptserver ~ ]# lsof -a -p $$ -d 0,1,2
3# 打开新的连接,然后查看
4[root@comptserver ~ ]# cat fd1.log
5COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
6bash 4003 root 0u CHR 136,1 0t0 4 /dev/pts/1
7bash 4003 root 1w REG 253,0 0 101335674 /root/fd1.log
8bash 4003 root 2u CHR 136,1 0t0 4 /dev/pts/1
9
10[root@comptserver ~ ]# exec 1>&- # 关闭文件描述符
11
bash shell的内建命令exec将并不启动新的shell,而是用要被执行命令替换当前的shell进程,并且将老进程的环境清理掉,而且exec命令后的其它命令将不再执行。
因此,如果你在一个shell里面,执行exec ls;那么,当列出了当前目录后,这个shell就自己退出了,因为这个shell进程已被替换为仅仅执行ls命令的一个进程,执行结束自然也就退出了。为了避免这个影响我们的使用,一般将exec命令放到一个shell脚本里面,用主脚本调用这个脚本,调用点处可以用bash a.sh,(a.sh就是存放该命令的脚本),这样会为a.sh建立一个sub shell去执行,当执行到exec后,该子脚本进程就被替换成了相应的exec的命令。source命令或者”.”,不会为脚本新建shell,而只是将脚本包含的命令在当前shell执行。不过,要注意一个例外,当exec命令来对文件描述符操作的时候,就不会替换shell,而且操作完成后,还会继续执行接下来的命令。
exec 3<&0
:这个命令就是将操作符3也指向标准输入。总结:exec 命令:常用来替代当前 shell 并重新启动一个 shell,换句话说,并没有启动子 shell。使用这一命令时任何现有环境都将会被清除。exec 在对文件描述符进行操作的时候,也只有在这时,exec 不会覆盖你当前的 shell 环境。
exec | 描述 |
---|---|
exec ls | 在shell中执行ls,ls结束后不返回原来的shell中了 |
exec <file | file中的内容作为标准输入(替代STDIN) |
exec >file | 将标准输出写入file(替代STDOUT) |
exec 3<file | 将file读入到文件描述符3中(此时,创建了文件描述符3) |
sort <&3 | 将文件描述符3作为临时输入,用于sort排序 |
exec 4>file | 将写入文件描述符4中的内容写入file中(此时,创建了文件描述符4) |
ls >&4 | ls将不会有显示,直接写入文件描述符4中了,即上面的file中 |
exec 5<&4 | 创建文件描述符4的拷贝文件描述符5 |
exec 3<&- | 关闭文件描述符3 |
&-
关闭标准输出
n&-
表示将 n 号输出关闭
上述所有形式都可以前导一个数字,此时建立的文件描述符由这个数字指定而不是缺省的 0 或 1。如:
2>file
运行一个命令并把错误输出(文件描述符 2)定向到 file。
2>&1
运行一个命令并把它的标准输出和输出合并。(严格的说是通过复制文件描述符 1 来建立文件描述符 2 ,但效果通常是合并了两个流。)
我们对 2>&1详细说明一下 :2>&1 也就是 FD2=FD1 ,这里并不是说FD2 的值 等于FD1的值,因为 > 是改变送出的数据信道,也就是说把 FD2 的 “数据输出通道” 改为 FD1 的 “数据输出通道”。如果仅仅这样,这个改变好像没有什么作用,因为 FD2 的默认输出和 FD1的默认输出本来都是 monitor,一样的!
但是,当 FD1 是其他文件,甚至是其他 FD 时,这个就具有特殊的用途了。请大家务必理解这一点。
如果 stdin, stdout, stderr 进行了重定向或关闭, 但没有保存原来的 FD, 可以将其恢复到 default 状态吗?
1.如果关闭了
stdin
,因为会导致退出,那肯定不能恢复。2.如果重定向或关闭 1stdou1t和1stderr1其中之一,可以恢复,因为他们默认均是送往1monitor1(但不知会否有其他影响)。
如恢复重定向或关闭的 stdout:
exec 1>&2
,恢复重定向或关闭的stderr:exec 2>&1
。3.如果stdout和stderr全部都关闭了,又没有保存原来的FD,可以用:
exec 1>/dev/tty
恢复。
管道和重定向的区别
1.管道是把一个程序的输出作为另一个程序的输入。
2.重定向是把输出定向到文件或者标准流。
Linux mktemp命令用于建立暂存文件。 mktemp建立的一个暂存文件,供shell script使用。 mktemp命令专门用来创建临时文件,并且其创建的临时文件是唯一的。shell会根据mktemp命令创建临时文件,但不会使用默认的umask值(管理权限的)。它会将文件的读写权限分配给文件属主,一旦创建了文件,在shell脚本中就拥有了完整的读写权限,其他人不可访问(除了root)
xxxxxxxxxx
211参数:
2-q 执行时若发生错误,不会显示任何信息。
3-u 暂存文件会在mktemp结束前先行删除。
4[文件名参数] 文件名参数必须是以"自订名称.XXXXXX"的格式。
5默认情况:mktemp会在本地当前目录创建一个临时文件,创建临时文件时只需要创建模板文件,模板可以包含任意的文件名,文件末尾可以根据需要添加n个X。Demo如下:
6[root@master ~] # tempfile=$(mktemp test.XXXX)
7[root@master ~] # echo $tempfile
8test.coCi
9[root@master ~] # mktemp test.XXX // 不能少于三个X test.eIB
10
11
12-t 选项:-t选项会强制mktemp命令在系统的临时目录中创建临时文件,创建时mktemp命令会返回临时文件的全路径。
13
14[root@master ~] # mktemp -t test.XXXX
15/tmp/test.1OKR
16[root@master ~] # mktemp -t test.XXXXX
17/tmp/test.jSwmV
18[root@master ~] # mktemp -t test.XXXX
19/tmp/test.sQTP
20
21-d 选项:-d选项告诉mktemp命令创建一个临时目录而不是临时文件
创建命名管道
"FIFO"是一种特殊的文件类型,它允许独立的进程通讯. 一个进程打开FIFO文件进行写操作,而另一个进程对之进行读操作, 然后数据便可以如同在shell或者其它地方常见的的匿名管道一样流式执行.
管道是一种通信机制,用于进程间的通信(也可通过socket进行网络通信),表现出来的形式将前面的每一个进程的输出,直接作为下一个进程的输入
管道命令仅能处理stdout,而error则会忽略
FIFO不同于pipe的地方: 1)FIFO可以看作高级的管道。它突破了pipe的限制(只能用于同源进程之间的通信),可以给任意进程之间建立通信连接;
2)FIFO是一个实际存在于磁盘中的文件;而pipe是由进程创建的,依赖于进程的存活期。
因为它本质上是一个文件,所以进程用open函数来打开一个FIFO,并在打开时指定文件操作模式(只读,只写还是读写)。之后用read(write)函数来读(写)FIFO
当一个进程以只写方式打开FIFO文件,另一个进程以只读方式打开同一个FIFO文件,这样就建立了两个进程之间的通信管道。
实际工作时,pipe和FIFO基本相同的。下面是两者相同的性质:
1)当读一个写端已经被关闭的pipe(或者是读一个没有为写打开的进程的FIFO)时,在所有数据都被读取后,read返回0,以指示到达了文件结束处
2)当写一个读端已经被关闭的pipe(或者是写一个没有为读打开的进程的FIFO)时,write返回-1,并将errno设置为EPIPE
3)在写pipe或者FIFO时,常量PIPE_BUF规定了内核中管道缓冲区的大小。如果多个进程同时写一个管道(或者FIFO),要保证写的字节数不大于PIPE_BUF,这样多个写进程的数据不会相互穿插而造成混乱
4)open使用O_NONBLOCK 旗标时,打开FIFO 文件来读取的操作会立刻返回,但是若还没有其他进程打开FIFO 文件来读取,则写入的操作会返回ENXIO 错误代码。没有使用O_NONBLOCK 旗标时,打开FIFO 来读取的操作会等到其他进程打开FIFO文件来写入才正常返回。同样地,打开FIFO文件来写入的操作会等到其他进程打开FIFO 文件来读取后才正常返回。
xxxxxxxxxx
71|(竖线)为管道,是两个进程之间的通信通道
2例如:ls|grep txt
3ls和grep由|分开,管道创建了程序之间的通信通道,将ls的输出作为输入传给grep
4
5由mkfifo创建出来的就是一个命名管道
6例如:mkfifo pipe2
7pipe2就是一个命名管道。
xxxxxxxxxx
161[root@servera ~]# mkfifo --help
2Usage: mkfifo [OPTION]... NAME...
3Create named pipes (FIFOs) with the given NAMEs.
4
5Mandatory arguments to long options are mandatory for short options too.
6 -m, --mode=MODE set file permission bits to MODE, not a=rw - umask
7 -Z set the SELinux security context to default type
8 --context[=CTX] like -Z, or if CTX is specified then set the SELinux
9 or SMACK security context to CTX
10 --help display this help and exit
11 --version output version information and exit
12
13GNU coreutils online help: <https://www.gnu.org/software/coreutils/>
14Full documentation at: <https://www.gnu.org/software/coreutils/mkfifo>
15or available locally via: info '(coreutils) mkfifo invocation'
16
可以将输出信道化到不同终端、
xxxxxxxxxx
61例如:
2在第一个终端执行
3ls > pipe2
4在第二个终端执行
5cat < pipe2(或cat pipe2,是取一次。cat < pipe2是持续输入,只要有内容传到pipe2中,就会有内容输出)
6pipe2更像是一个临时存储的地方,使用cat pipe2取过内容之后,再执行cat pipe2 ,则不会有显示
xxxxxxxxxx
321lsof abc.txt 显示开启文件abc.txt的进程
2lsof -c abc 显示abc进程现在打开的文件
3lsof -c -p 1234 列出进程号为1234的进程所打开的文件
4lsof -g gid 显示归属gid的进程情况
5lsof +d /usr/local/ 显示目录下被进程开启的文件
6lsof +D /usr/local/ 同上,但是会搜索目录下的目录,时间较长
7lsof -d 4 显示使用fd为4的进程
8lsof -i 用以显示符合条件的进程情况
9lsof -i[46] [protocol][@hostname|hostaddr][:service|port]
10 46 --> IPv4 or IPv6
11 protocol --> TCP or UDP
12 hostname --> Internet host name
13 hostaddr --> IPv4地址
14 service --> /etc/service中的 service name (可以不止一个)
15 port --> 端口号 (可以不止一个)
16
17lsof `which httpd` //那个进程在使用apache的可执行文件
18lsof /etc/passwd //那个进程在占用/etc/passwd
19lsof /dev/hda6 //那个进程在占用hda6
20lsof /dev/cdrom //那个进程在占用光驱
21lsof -c sendmail //查看sendmail进程的文件使用情况
22lsof -c courier -u ^zahn //显示出那些文件被以courier打头的进程打开,但是并不属于用户zahn
23lsof -p 30297 //显示那些文件被pid为30297的进程打开
24lsof -D /tmp 显示所有在/tmp文件夹中打开的instance和文件的进程。但是symbol文件并不在列
25lsof -u1000 //查看uid是100的用户的进程的文件使用情况
26lsof -utony //查看用户tony的进程的文件使用情况
27lsof -u^tony //查看不是用户tony的进程的文件使用情况(^是取反的意思)
28lsof -i //显示所有打开的端口lsof -i:80 //显示所有打开80端口的进程
29lsof -i -U //显示所有打开的端口和UNIX domain文件
30lsof -i UDP@[url]www.akadia.com:123 //显示那些进程打开了到www.akadia.com的UDP的123(ntp)端口的链接
31lsof -i [email protected]:ftp -r //不断查看目前ftp连接的情况(-r,lsof会永远不断的执行,直到收到中断信号,+r,lsof会一直执行,直到没有档案被显示,缺省是15s刷新)
32lsof -i [email protected]:ftp -n //lsof -n 不将IP转换为hostname,缺省是不加上-n参数
要与Linux交互,脚本获取键盘输入的结果是必不可少的,read可以读取键盘输入的字符。
read [-rs] [-a ARRAY] [-d delim] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [var_name1 var_name2 ...]
read命令用于从标准输入中读取输入单行,并将读取的单行根据IFS变量分裂成多个字段,并将分割后的字段分别赋值给指定的变量列表var_name。第一个字段分配给第一个变量var_name1,第二个字段分配给第二个变量var_name2,依次到结束。如果指定的变量名少于字段数量,则多出的字段数量也同样分配给最后一个var_name,如果指定的变量命令多于字段数量,则多出的变量赋值为空。
如果没有指定任何var_name,则分割后的所有字段都存储在特定变量REPLY中。
xxxxxxxxxx
91选项说明:
2-a:将分裂后的字段依次存储到指定的数组中,存储的起始位置从数组的index=0开始。
3-d:指定读取行的结束符号。默认结束符号为换行符。
4-n:限制读取N个字符就自动结束读取,如果没有读满N个字符就按下回车或遇到换行符,则也会结束读取。
5-N:严格要求读满N个字符才自动结束读取,即使中途按下了回车或遇到了换行符也不结束。其中换行符或回车算一个字符。
6-p:给出提示符。默认不支持"\n"换行,要换行需要特殊处理,见下文示例。例如,"-p 请输入密码:"
7-r:禁止反斜线的转义功能。这意味着"\"会变成文本的一部分。
8-s:静默模式。输入的内容不会回显在屏幕上。
9-t:给出超时时间,在达到超时时间时,read退出并返回错误。也就是说不会读取任何内容,即使已经输入了一部分。
使用示例:
(1).将读取的内容分配给数组变量,从索引号0开始分配。
xxxxxxxxxx
81[root@xuexi ~]# read -a array_test
2what is you name?
3
4[root@xuexi ~]# echo ${array_test[@]}
5what is you name?
6
7[root@xuexi ~]# echo ${array_test[0]}
8what
(2).指定读取行的结束符号,而不再使用换行符。
xxxxxxxxxx
21[root@xuexi ~]# read -d '/'
2what is you name \// # 输入完尾部的"/",自动结束read
由于没有指定var_name,所以通过$REPLY变量查看read读取的行。
xxxxxxxxxx
21[root@xuexi ~]# echo $REPLY
2what is you name /
(3).限制输入字符。
例如,输入了5个字符后就结束。
xxxxxxxxxx
51[root@xuexi tmp]# read -n 5
212345
3
4[root@xuexi tmp]# echo $REPLY # 输入12345共5个字符
512345
如果输入的字符数小于5,按下回车会立即结束读取。
xxxxxxxxxx
51[root@xuexi ~]# read -n 5
2123
3
4[root@xuexi ~]# echo $REPLY
5123
但如果使用的是"-N 5"而不是"-n 5",则严格限制读满5个字符才结束读取。
xxxxxxxxxx
61[root@xuexi ~]# read -N 5
2123\n4
3
4[root@xuexi ~]# read -N 5
5123 # 3后的回车(换行)算是一个字符
64
(4).使用-p选项给出输入提示。
xxxxxxxxxx
51[root@xuexi ~]# read -p "pls enter you name: "
2pls enter you name: Junmajinlong
3
4[root@xuexi ~]# echo $REPLY
5Junmajinlong
"-p"选项默认不带换行功能,且也不支持"\n"换行。但通过$'string'的方式特殊处理,就可以实现换行的功能。例如:
xxxxxxxxxx
31[root@node2 ~]# read -p $'Enter your name: \n'
2Enter your name:
3JunMaJinLong
关于$'String'
和$"String"
的作用如下:
有些时候在某些服务管理脚本中看到
$"$string"
或$"string"
,经过一些测试,又发现引号外面的$有和没有是一样的。一直也没去找究竟,刚才有人问了我,于是就去翻了下man bash,找到了解释。(1).如果没有特殊定制bash环境或有特殊需求,
""只是为了保证本地化。 以下是man bash关于$""的解释:
xxxxxxxxxx
21A double-quoted string preceded by a dollar sign ($"string") will cause the string to be translated according to the current locale. If
2the current locale is C or POSIX, the dollar sign is ignored. If the string is translated and replaced, the replacement is double-quoted.
(2).还有
'string',这在bash中被特殊对待:会将某些反斜线序列(如\n,\t,",'等)继续转义,而不认为它是字面符号(如果没有$符号,单引号会强制将string翻译为字面符号,包括反斜线)。简单的例子: xxxxxxxxxx
51[root@xuexi ~]# echo 'a\nb'
2a\nb
3[root@xuexi ~]# echo $'a\nb'
4a
5b
以下是man bash里关于$'的说明:
xxxxxxxxxx
191Words of the form $'string' are treated specially. The word expands to string, with backslash-escaped characters replaced as specified by the ANSI C standard. Backslash escape sequences, if present, are decoded as follows:
2\a alert (bell)
3\b backspace
4\e
5\E an escape character
6\f form feed
7\n new line
8\r carriage return
9\t horizontal tab
10\v vertical tab
11\\ backslash
12\' single quote
13\" double quote
14\nnn the eight-bit character whose value is the octal value nnn (one to three digits)
15\xHH the eight-bit character whose value is the hexadecimal value HH (one or two hex digits)
16\uHHHH the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value HHHH (one to four hex digits)
17\UHHHHHHHH
18the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value HHHHHHHH (one to eight hex digits)
19\cx a control-x character
(5).禁止反斜线转义功能。
xxxxxxxxxx
51[root@xuexi ~]# read -r
2what is you name \?
3
4[root@xuexi ~]# echo $REPLY
5what is you name \?
(6).不回显输入的字符。比如输入密码的时候,不回显输入密码。
xxxxxxxxxx
51[root@xuexi ~]# read -s -p "please enter your password: "
2please enter your password:
3
4[root@xuexi ~]# echo $REPLY
5123456
另一种方法
xxxxxxxxxx
71
2stty -echo
3read -p "输入密码:" pwd
4stty echo
5echo
6echo 输入完毕。
7其中,选项-echo禁止将输出发送到终端,而选项echo则允许发送输出。
(7).将读取的行分割后赋值给变量。
xxxxxxxxxx
51[root@xuexi ~]# read var1 var2 var3
2abc def galsl djks
3
4[root@xuexi ~]# echo $var1:::$var2:::$var3
5abc:::def:::galsl djks
(8).给出输入时间限制。没完成的输入将被丢弃,所以变量将赋值为空(如果在执行read前,变量已被赋值,则此变量在read超时后将被覆盖为空)。
xxxxxxxxxx
61[root@xuexi ~]# var=5
2
3[root@xuexi ~]# read -t 3 var
41
5
6[root@xuexi ~]# echo $var
(9).读文件
xxxxxxxxxx
61count=1
2cat /etc/fstab | while read line
3do
4 echo "Line ${count}:${line}"
5 count=$[ $count + 1 ]
6done
xxxxxxxxxx
151File=/etc/passwd
2{
3read line1
4read line2
5} < $File
6
7echo "First line in ${File}"
8echo "${line1}"
9
10echo "----------"
11
12echo "Second line in ${File}"
13echo "${line2}"
14
15
xxxxxxxxxx
701
2# assign the file descriptor to file for input fd # 3 is Input file
3exec 3< test.txt
4
5# read the file using fd # 3
6count=0
7while read -u 3 var
8do
9 let count=$count+1
10 echo "Line $count:$var"
11done
12echo "finished"
13echo "Line no is $count"
14
15# Close fd # 3
16exec 3<&-
17
18
19
20count=1
21cat test.txt | while read line
22do
23 echo "Line $count:$line"
24 let count=$count+1
25done
26echo "finished"
27echo "Line no is $count"
28exit 0
29
30# 执行效果
31[roc@roclinux ~]$ ./test.sh
32Line 1:19248
33Line 2:19247
34Line 3:19246
35finished
36Line no is 1
37
38咦,有个问题。脚本最后输出的是 Line no is 1,怎么行数是 1 呢,明明是 3 才对啊?
39上面这个问题,是由于管道导致的。我们知道,管道的两边一般需要新建进程,当执行完 while 语句后,新进程也就结束了。而脚本中 count 是新进程中的自定义变量,进程结束后该变量也就消失了(自定义变量的生命周期结束)。当脚本执行 echo 时,显示的 count 变量是脚本中第一行定义的变量的值,而不是 while 语句中的那个 count 变量了,因而输出的结果当然就是 1 了。
40
41
42
43count=0
44while read line
45do
46 let count=$count+1
47 echo "Line $count:$line"
48done < test.txt
49echo "finished"
50echo "Line no is $count"
51exit 0
52
53
54
55# assign the file descriptor to file for input fd # 3 is Input file
56exec 3< test.txt
57
58# read the file using fd # 3
59count=0
60while read -u 3 -r var
61do
62 let count=$count+1
63 echo "Line $count:$var"
64done
65echo "finished"
66echo "Line no is $count"
67
68
69# Close fd # 3
70exec 3<&-
xxxxxxxxxx
831lsof abc.txt 显示开启文件abc.txt的进程
2lsof -c abc 显示abc进程现在打开的文件
3lsof -c -p 1234 列出进程号为1234的进程所打开的文件
4lsof -g gid 显示归属gid的进程情况
5lsof +d /usr/local/ 显示目录下被进程开启的文件
6lsof +D /usr/local/ 同上,但是会搜索目录下的目录,时间较长
7lsof -d 4 显示使用fd为4的进程
8lsof -i 用以显示符合条件的进程情况
9lsof -i[46] [protocol][@hostname|hostaddr][:service|port]
10 46 --> IPv4 or IPv6
11 protocol --> TCP or UDP
12 hostname --> Internet host name
13 hostaddr --> IPv4地址
14 service --> /etc/service中的 service name (可以不止一个)
15 port --> 端口号 (可以不止一个)
16
17
18lsof -a // 默认多个条件组合时,lsof使用OR逻辑,而使用-a表示AND逻辑。
19lsof `which httpd` //那个进程在使用apache的可执行文件
20lsof /etc/passwd //那个进程在占用/etc/passwd
21lsof /dev/hda6 //那个进程在占用hda6
22lsof /dev/cdrom //那个进程在占用光驱
23lsof -c sendmail //查看sendmail进程的文件使用情况
24lsof -c courier -u ^zahn //显示出那些文件被以courier打头的进程打开,但是并不属于用户zahn
25lsof -p 30297 //显示那些文件被pid为30297的进程打开
26lsof -D /tmp 显示所有在/tmp文件夹中打开的instance和文件的进程。但是symbol文件并不在列
27
28lsof -u1000 //查看uid是100的用户的进程的文件使用情况
29lsof -utony //查看用户tony的进程的文件使用情况
30lsof -u^tony //查看不是用户tony的进程的文件使用情况(^是取反的意思)
31lsof -i //显示所有打开的端口
32lsof -i:80 //显示所有打开80端口的进程
33lsof -i -U //显示所有打开的端口和UNIX domain文件
34lsof -i UDP@[url]www.akadia.com:123 //显示那些进程打开了到www.akadia.com的UDP的123(ntp)端口的链接
35lsof -i [email protected]:ftp -r //不断查看目前ftp连接的情况(-r,lsof会永远不断的执行,直到收到中断信号,+r,lsof会一直执行,直到没有档案被显示,缺省是15s刷新)
36lsof -i [email protected]:ftp -n //lsof -n 不将IP转换为hostname,缺省是不加上-n参数
37
38lsof -a -p $$
39
40
41is the File Descriptor number of the file or:
42
43 cwd current working directory;
44 Lnn library references (AIX);
45 err FD information error (see NAME column);
46 jld jail directory (FreeBSD);
47 ltx shared library text (code and data);
48 Mxx hex memory-mapped type number xx.
49 m86 DOS Merge mapped file;
50 mem memory-mapped file;
51 mmap memory-mapped device;
52 pd parent directory;
53 rtd root directory;
54 tr kernel trace file (OpenBSD);
55 txt program text (code and data);
56 v86 VP/ix mapped file;
57
58FD is followed by one of these characters, describing the mode under which the file is open:
59
60 r for read access;
61 w for write access;
62 u for read and write access;
63 space if mode unknown and no lock
64 character follows;
65 `-' if mode unknown and lock
66 character follows.
67
68The mode character is followed by one of these lock characters, describing the type of lock applied to the file:
69
70 N for a Solaris NFS lock of unknown type;
71 r for read lock on part of the file;
72 R for a read lock on the entire file;
73 w for a write lock on part of the file;
74 W for a write lock on the entire file;
75 u for a read and write lock of any length;
76 U for a lock of unknown type;
77 x for an SCO OpenServer Xenix lock on part of the file;
78 X for an SCO OpenServer Xenix lock on the entire file;
79 space if there is no lock.
80
81See the LOCKS section for more information on the lock information character.
82
83The FD column contents constitutes a single field for parsing in post-processing scripts.
循环实现并发程序:
并发的实现原理是将进程放到后台运行,从而不影响当前shell的运行。在shell脚本中有&符号可以实现这个操作。
xxxxxxxxxx
121
2echo "hello multiprocess"
3
4for ((i=0;i<10;i++))
5do
6 {
7 echo $i
8 sleep 2
9 }&
10done
11wait # 等待子进程结束,类似于高级语言的线程同步
12echo "process end"
上述脚本已经可以产生并发的效果,但是如果并发数量过于庞大,那么系统将无法处理,你将看到系统CPU负载极高的直观现象。
程序的并发数量并不是无限的,进程过多会导致机器卡死,所以需要控制并发的数量。可以使用管道来实现控制并发的数量。
原理:
linux管道文件特性制作队列,控制线程数目
1.管道具有存一个读一个,读完一个就少一个,没有则阻塞,放回的可以重复取,这正是队列特性,但是问题是当往管道文件里面放入一段内容,没人取则阻塞,这样你永远也没办法往管道里面同时放入10段内容(想当与10把钥匙),解决这个问题的关键就是文件描述符了。
2.mkfifo /tmp/fd1
创建有名管道文件exec 3<>/tmp/fd1,创建文件描述符3关联管道文件,这时候3这个文件描述符就拥有了管道的所有特性,还具有一个管道不具有的特性:无限存不阻塞,无限取不阻塞,而不用关心管道是否为空。也不用关心是否有内容写入引用文件描述符:&3可以执行n次echo >&3往管道里放入n次内容
xxxxxxxxxx
271
2echo "hello multiprocess"
3process=5
4tmp_fifofile=/tmp/$$.fifo # 使用当前pid作为管道文件名称,防止文件名称冲突
5mkfifo ${tmp_fifofile} # 创建管道文件
6exec 9<> ${tmp_fifofile} # 读写方式打开文件并将文件描述符设置为9
7rm -rf ${tmp_fifofile} # 删除管道文件,注:这一操作不会影响文件描述符
8
9for i in `seq $process`
10do
11 echo >&9 # 向文件描述符传递5个空行
12done
13
14for i in {1..10}
15do
16 read -u 9 # 读取管道内容,每次读取一行
17 {
18 echo $i # 显示当前值
19 sleep 1 # 使用程序延时
20 echo >&9 # 程序结束追加空行
21 }&
22done
23
24wait # 等待子进程结束,类似于高级语言的线程同步
25exec 9>&- # 释放文件描述符
26exec 9<&-
27echo "process end"
其中
xxxxxxxxxx
61exec fd< file # 以只读方式打开文件,并关联文件描述符fd
2exec fd> file # 以只写方式打开文件,并关联文件描述符fd
3exec fd<>file # 以读写方式打开文件,并关联文件描述符fd
4
5read -u fd # 读取文件描述符fd,关联其中一行内容,即一次只读去文件描述符fd一行
6