标签:shell
把懂的一点shell知识,汇总一下,以便自己以后学习,查找~
shell引号:
名称 | 解释 |
单引号 | 所见即所得:将单引号内的所有内容都原样输出,或者单引号里面看到的是什么 就会输出什么 |
双引号 | 把双引号内的所有内容都输出出来:内容中有命令(用反引号)、变量、特殊转义 符号等,会先把变量、命令、转义字符解析出结果,然后再输出最终内容 |
无引号 | 将内容输出,会将含有空格的字符串视为一个整体输出,如果内容中有命令(反 引号)、变量等,会先把变量、命令解析出结果,然后再输出最终内容,如果字符 串中带有空格等特殊字符,则不能完整的输出,需要加双引号,一般连续的字符串, 数字,路径等可以不加任何引号,无引号的情况,最好用双引号替代 |
反引号 | ``,一般用于引命令,窒息的时候命令会被执行 |
提示:某些语言可能不适合,例如:awk |
位置变量:
$# 获取当前执行的shell脚本后面接的参数的总个数
$0 获取当前执行的shell脚本的文件名,如果执行脚本带路径,那么就包括脚本路径
$n 获取当前执行的shell脚本的第n个参数值,当n大于10时,需要用大括号括起来${10},参数以空格隔开
进程状态变量
$$ 获取当前shell脚本的进程号(PID)
$! 执行上一个指令的PID
$? 获取执行上一个指令的返回值(0 位成功,非零为失败)
#!/bin/sh
#no1
if [ $# -ne 1 ]
then
echo "USAGE:/data/3306/$0 {start|stop}"
exit 1
fi
#no2
if [ "$1" == "start" ]
then
/bin/sh /application/mysql/bin/mysqld_safe --defaults-file=/data/3306/my.cnf 2>&1 > /dev/null &
exit 0
fi
#no3
if [ "$1" == "stop" ]
then
mysqladmin -u root -poldboy123 -S /data/3306/mysql.sock shutdown
exit 0
fi
#!/bin/sh #no.1 judge arg nums. [ $# -ne 2 ]&&{ echo "USAGE:"$0" num1 num2" exit 1 } #no.2 judge if int. expr $1 + $2 &>/dev/null [ $? -ne 0 ]&&{ echo "pls input two nums:" exit 2 } #no.3 compare two int. [ $1 -lt $2 ]&&{ echo "$1<$2" exit 0 } [ $1 -eq $2 ]&&{ echo "$1=$2" exit 0 } [ $1 -gt $2 ]&&{ echo "$1>$2" exit 0 }
#!/bin/bash a=$1 b=$2 echo "a-b =$(( $a - $b ))" echo "a+b =$(( $a + $b ))" echo "a*b =$(( $a * $b ))" echo "a/b =$(( $a / $b ))" echo "a**b =$(( $a ** $b ))" echo "a%b =$(( $a % $b ))"
逻辑操作符
在[ ] 和test中使用的操作符 | 在[[ ]]和(( ))中使用的操作符 | 说明 |
-a | && | and,与,两端都威震,结果为真 |
-o | || | or,或,两端一个为真,结果为真 |
! | ! | not,非,两端相反,结果为真 |
二元比较操作符
在[ ]已经test中使用的比较符号 | 在(( ))和[[ ]]中使用的比较符号 | 说明 |
-eq | ==或= | 相等,equal |
-ne | != | 不相等,not equal |
-gt | > | 大于,greater than |
-ge | >= | 大于等于,greater equal |
-lt | < | 小于,less than |
-le | <= | 小于等于,less equal |
=和!= 也可在[] 中使用,但在[]中使用包含>和<的符号时,需要用反斜线转义,不转义结果可能有误
三种计算字符长度的方法:
[root@zabbix ~]# John="I am John"
[root@zabbix ~]# expr length "$John"
9
[root@zabbix ~]# echo $John|wc -L
9
[root@zabbix ~]# echo ${#John}
9
例1:
for n in I am John welcome to ucloudlink
do
if [ ${#n} -lt 6 ]
then
echo $n
fi
done
比较三种方法的效率:
[root@zabbix ~]# chars=`seq -s " " 100`
[root@zabbix ~]# echo $chars
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
[root@zabbix ~]# echo ${#chars}
291
[root@zabbix ~]# echo $(expr length "$chars")
291
[root@zabbix ~]# echo ${chars} |wc -L
291
[root@zabbix ~]# time for i in $(seq 1111); do count=`echo ${chars} |wc -L`;done;
real 0m2.775s
user 0m0.734s
sys 0m1.657s
[root@zabbix ~]# time for i in $(seq 1111); do count=`echo $(expr length "$chars")`;done;
real 0m3.511s
user 0m0.726s
sys 0m1.797s
[root@zabbix ~]# time for i in $(seq 1111); do count=${#chars};done;
real 0m0.158s
user 0m0.152s
sys 0m0.001s
结论:管道效率低
替换:
表达式 | 说明 |
${#string} | 返回$string的长度 |
${string:position} | 在$string中,从位置$position之后开始提取子串 |
${string:position:length} | 在$string中,从位置$position之后开始提取长度为$length子串 |
${string#substring} | 从变量$string开头开始删除最短匹配$substring子串 |
${string##substring} | 从变量$string开头开始删除最长匹配$substring子串 |
${string%substring} | 从变量$string结尾开始删除最短匹配$substring子串 |
${string%%substring} | 从变量$string结尾开始删除最长匹配$substring子串 |
${string/substring/replace} | 使用$replace,来替代第一个匹配的$substring |
${string/#substring/replace} | 如果%string前缀匹配$substring,就用$replace来代替匹配$substring,第一个匹配的$substring |
${string/%substring/replace} | 如果%string后缀匹配$substring,就用$replace来代替匹配$substring,最后一个匹配的$substring |
小结:#开头删除匹配最短 ##开头删除匹配最长 %结尾删除匹配最短 %%结尾删除匹配最长 |
变量替换表:
运算符号 | 替换 |
${value:-word} | 如果变量名存在且非null,则返回变量的值。否则,返回word字符串 用途:如果变量未定义,则返回默认值 例:${value:-word},如果value未定义,则表达式的值为word |
${value:=word} | 如果变量名存在且非null,则返回变量的值。否则,设置这个变量为word,并返回其值 用途:如果变量未定义,则设置变量为默认值,并返回默认值。 例:${value:=word},如果value未定义,则设置value值为word,返回表达式的值也为word |
expr只能进行整数运算
[root@zabbix ~]# cat judge_int.sh
read -p "Pls input:" a
expr $a + 1 &>/dev/null
[ $? -eq 0 ] && echo int || echo chars
awk也可以计算小数
[root@zabbix ~]# echo "5.5 5.6"|awk ‘{print ($2-$1)/5}‘
0.02
bc既能计算整数,又能计算小数
[root@zabbix ~]# echo "`seq -s ‘+‘ 10`="$((`seq -s "+" 10`))
1+2+3+4+5+6+7+8+9+10=55
常用字符串测试操作符 | 说明 |
-z "字符串" | 若串长度为0则为真,-z可以理解为zero |
-n "字符串" | 若串长度不为0则为真,-n可以理解为no zero |
"串 1”=“串 2” | 若串1等于串2则为真,可使用“==”代替“=” |
"串 1”!=“串 2” | 若串1不等于串2则为真,可使用“!==”代替“!=” |
注意:以上表格中的字符串测试操作符号务必要用“”引起来 字符串之间比较,比较符号两边最好有空格 |
整数比较,推荐下面方法:
[ $num1 -eq $num2 ] <<注意空格
(($num1>$num2)) <<无需空格
read -p "提示"
-t 超时
特殊写法:
if [ -f "$file1" ];then echo 1; fi相当于:[ -f "$fil1" ]&& echo 1
if [ -f "$file1" ]
then
echo 1
fi
grep精确过滤
[root@zabbix ~]# cat John.log
200
0200
2000
[root@zabbix ~]# grep "\b200\b" John.log
200
[root@zabbix ~]# grep -w "200" John.log
200
[root@zabbix ~]# grep -x "200" John.log
200
[root@zabbix ~]# grep "^200$" John.log
200
shell输入错误操作,回退:
shift + delete
ctrl + u
sh while.sh & | 把脚本while.sh放到后台执行 |
ctrl+c | 停止执行当前脚本或任务 |
ctrl+z | 暂停执行当前脚本或任务 |
bg | 把当前脚本或任务放到后台执行,backgroud |
fg | 当前脚本或任务拿到前台执行,如果有多个任务,可以fg加任务编号调出,如fg 1 frontground |
jobs | 查看当前执行的脚本或任务 |
kill | [root@zabbix ~]# jobs [1]- Running sh while.sh & [2]+ Running sh while.sh & [root@zabbix ~]# kill %2 [root@zabbix ~]# jobs [1]- Running sh while.sh & [2]+ Terminated sh while.sh |
pstree:显示进程状态树
nice:改变优先权
nohup:用户退出系统后任然可以继续工作
pgrep:查找匹配条件的进程
strace:跟踪一个进程的系统调用情况
ltrace:跟踪进程调用库函数的情况
vmstat:报告虚拟内存统计信息
top命令,前五行是系统整体的统计信息,第六行开始为具体的进程统计信息:
top - 11:29:28 up 2 days, 4:28, 1 user, load average: 0.01, 0.08, 0.03
#同uptime结果,该项显示当前时间(11:29:28),系统运行时间(up 2 days, 4:28),当前登录用户数(1 user)最近1分,5分,15分的三个平均负载值(load average: 0.01, 0.08, 0.03)
Tasks: 1244 total, 1 running, 1243 sleeping, 0 stopped, 0 zombie
#processess自最近一次刷新依赖的运行进程总是(1244 total),进程被分为正在运行的(1 running),休眠的(1243 sleeping),停止的( 0 stopped),僵尸的( 0 zombie)
Cpu(s): 1.5%us, 0.7%sy, 0.0%ni, 97.3%id, 0.5%wa, 0.0%hi, 0.0%si, 0.0%st
#CPU states显示用户( 1.5%us),系统(0.7%sy),优先级进程(只有优先级为负的列入考虑)(0.0%ni)闲置(97.3%id),等待(0.5%wa,)等情况所占用CPU的百分比。优先级进程所消耗的时间也被列入到用户和系统的时间中,所以总的百分比将大于100%
Mem: 16336324k total, 16154176k used, 182148k free, 184208k buffers
#Mem内存使用统计,其中包括总的物理内存总量(16336324k total),已使用的物理内存总量(16154176k used),可用于交换内存(182148k free),用作内存缓存的内存量(184208k buffers)
Swap: 8392696k total, 5808k used, 8386888k free, 11161972k cached
#swap交换分析统计,其中包括总的交换分区总量(8392696k total)已用交换内存量(5808k used,),可用交换内存( 8386888k free),缓存的内存总量(11161972k cached)
top命令参数,按TMP1记
M | 根据驻留内存大小进行排序 |
P | 根据CPU使用百分比大小进行排序 |
T | 根据时间、累计时间进行排序 |
1(数字) | 显示多个多核CPU单个状态信息 |
W | 当前设置写入~/.toprc文件中 |
f | f添加删除列 |
o | o改变列显示的顺序 |
h或者? | 显示帮忙画面 |
扩展:while按行读文件的方式:
方式1:
exec <FILE
sum=0
while read line
do
cmd
done
方式2:
cat ${FILE_PATH} |while read line
do
cmd
done
方式3:
while read line
do
cmd
done<FILE
从日志计算访问当天流量大小
sum=0
while read line
do
value=`echo $line|awk ‘{print $10}‘`
expr $value +1 &>/dev/null
[ $? -ne 0 ] && continue
((sum+=value))
done<access_2010-12-8.log
echo $sum
while循环:
1、while循环的特长是执行守护进程以及我们希望循环不退出持续执行的情况,用于频率小于1分钟循环处理(crond),其他的while循环几乎都可以被for循环替代
2、case语句可以用if语句替换,一般在系统启动脚本传入少量固定规则字符串,用case语句,其他普通判断用if
3、一句话,if,for语句最常用,其次while(守护进程),case(服务启动脚本)
直接列出变量列表所有元素,打印5、4、3、2、1 需要空格隔开
for num in 5 4 3 2 1
do
echo $num
done
for ip in 10.0.0.18 10.0.0.19
do
echo $ip
done
for num in `seq 10`
for num in {1..10}
for file in `ls`
do
if [ -d $file ];tthen
echo "this is $file fir"
else
echo "this is $file file"
fi
done
for 循环批量改名,三种方法:
ls *.jpg|awk -F "_finished" ‘{print "mv "$0" " $1$2}‘|bash
mv $file `echo $file|sed ‘s#_finished##g‘`
mv $file `echo $file|cut -d . -f1`.jpg
rename "_finished" "" *.jpg
9 9 乘法表
[root@zabbix ~]# cat 1-9.sh
for a in `seq 1 9`
do
for b in `seq 1 9`
do
if [ $a -ge $b ]
then
echo -en "$a x $b = $(expr $a \* $b) "
fi
done
echo " "
done
[root@zabbix ~]# sh 1-9.sh
1 x 1 = 1
2 x 1 = 2 2 x 2 = 4
3 x 1 = 3 3 x 2 = 6 3 x 3 = 9
4 x 1 = 4 4 x 2 = 8 4 x 3 = 12 4 x 4 = 16
5 x 1 = 5 5 x 2 = 10 5 x 3 = 15 5 x 4 = 20 5 x 5 = 25
6 x 1 = 6 6 x 2 = 12 6 x 3 = 18 6 x 4 = 24 6 x 5 = 30 6 x 6 = 36
7 x 1 = 7 7 x 2 = 14 7 x 3 = 21 7 x 4 = 28 7 x 5 = 35 7 x 6 = 42 7 x 7 = 49
8 x 1 = 8 8 x 2 = 16 8 x 3 = 24 8 x 4 = 32 8 x 5 = 40 8 x 6 = 48 8 x 7 = 56 8 x 8 = 64
9 x 1 = 9 9 x 2 = 18 9 x 3 = 27 9 x 4 = 36 9 x 5 = 45 9 x 6 = 54 9 x 7 = 63 9 x 8 = 72 9 x 9 = 81
分库备份
mysql -uroot -pJohn123 -S /data/3306/mysql.sock -e ‘show databases;‘|sed ‘1d‘|grep -v "_schema"
[root@zabbix ~]# vim bak_by_db.sh
#!/bin/sh
MYUSER=root
MYPASS=John123
SOCKET=/data/3306/mysql.sock
MYCMD="mysql -u$MYUER -p$MYPASS -S $SOCKET"
BAKPATH="/server/backup/$(date +%F)"
[ ! -d $BAKPATH ] && mkdir -p $BAKPATH
for dbname in `$MYCMD -e ‘show databases;‘|sed ‘1d‘|grep -v "_schema"`
do
$MYDUMP -B -x --events $dbname|gzip >$BAKPATH/${dbname}.sql.gz
if [ $? -eq 0 ];then
echo "$dbname" >>$BAKPATH/${dbname}.log
fi
done
分库分表备份:
[root@zabbix ~]# cat bak_by_db.sh
#!/bin/sh
MYUSER=root
MYPASS=John123
SOCKET=/data/3306/mysql.sock
MYCMD="mysql -u$MYUER -p$MYPASS -S $SOCKET"
BAKPATH="/server/backup/$(date +%F)"
[ ! -d $BAKPATH ] && mkdir -p $BAKPATH
for dbname in `$MYCMD -e ‘show databases;‘|sed ‘1d‘|grep -v "_schema"`
do
for tname in `$MYCMD -e "show tables from $dbname;"|sed 1d`
do
$MYDUMP -x --events $dbname $tname|gzip >$BAKPATH/${dbname}_${tname}.sql.gz
if [ $? -eq 0 ];then
echo "${dbname}_${tname}" >>$BAKPATH/${dbname}.log
fi
done
done
文件改名:
[root@zabbix ~]# cat k2.sh
cd /home
for n in `ls *.html`
do
mv $n `echo $n|sed -r ‘s#^o.*y(.*)html+linux\1HTML#g‘`
done
自定义生成用户,密码
for n in `seq -2 10`
do
pass=`echo $RANDOM|md5sum|cut -c 2-9`
useradd oldboy$n && \
echo $pass|passwd --stdin oldboy$n
echo -e "oldboy$n \t $pass" >> /tmp/user.log
done
获取随机数方法:
echo $RANDOM
RANDOM范围0-32767
echo "$RANDOM oldboy"|md5sum
openssl rand -base64 65|cut -c 30-40
时间序列
date +$s%N
head /dev/urandom|cksum
cat /proc/sys/kernel/random/uuid
yum install expect -y
mkpasswd -1 8
chpasswd批量生成用户密码
1.log
liuxia:12345
lixiang:19876
chpasswd <1.log
用户必须存在
命令 | 说明 |
break n | n表示跳出循环的层数,如果省略n表示跳出整个循环 |
continue n | n表示推到第n层继续循环,如果省略n表示跳过本次循环,忽略本次循环的剩余代码,进入循环的下一次循环 |
exit n | 退出当前shell程序,n为返回值。n也可以省略,再下一个shell里面$?接收这个n的值 |
return n | 用于在函数里,作为函数的返回值,用于判断函数执行是否正确 |
结论:break continue exit 一般用于循环结构中控制循环的走向 |
数组:
[root@zabbix ~]# array=(1 2 3)
[root@zabbix ~]# echo ${#array[@]}
3
[root@zabbix ~]# echo ${#array[*]}
3
[root@zabbix ~]# echo ${array[0]}
1
[root@zabbix ~]# echo ${array[1]}
2
[root@zabbix ~]# echo ${array[2]}
3
[root@zabbix ~]# vim 1.sh
array=(1 2 3)
for ((i=0;i<${#array[*]};i++))
do
echo ${array[i]}
done
echo ===================
for i in ${array[*]}
do
echo $i
done
数组增删
[root@zabbix ~]# echo ${array[@]}
1 2 3
[root@zabbix ~]# array[3]=4
[root@zabbix ~]# echo ${array[@]}
1 2 3 4
[root@zabbix ~]# unset array[2]
[root@zabbix ~]# echo ${array[@]}
1 2 4
数组定义:
静态数组array=(1 2 3)
动态数组array=($(ls))
打印:
${array[@]}或${array[*]} 打印所有元素
${#array[@]}或${#array[*]}打印数组长度
${array[i]} 打印单个元素,i是数组下标。
函数:
#!/bin/bash
john(){
echo "I am john."
}
function lili(){
echo "I am lili."
}
john
lili
检查网站状态
function check_url(){ wget --spider -q -o /dev/null --tries=1 -T 5 $1 if [ $? -eq 0 ] then echo "$1 is yes." else echo "$1 is no." fi }
字体颜色
#!/bin/sh
RED_COLOR=‘\E[1;31m‘
GREEN_COLOR=‘\E[1;32m‘
YELLOW_COLOR=‘\E[1;33m‘
BLUE_COLOR=‘\E[1;34m‘
RES=‘\E[0m‘
echo -e "$RED_COLOR John$RES"
echo -e "$YELLOW_COLOR Lili$RES"
#!/bin/sh add(){ RED_COLOR=‘\E[1;31m‘ GREEN_COLOR=‘\E[1;32m‘ YELLOW_COLOR=‘\E[1;33m‘ BLUE_COLOR=‘\E[1;34m‘ FLASH_COLOR=‘\33[5m‘ RES=‘\E[0m‘ case "$1" in red|RED) echo -e "$RED_COLOR $2 $RES" ;; green|GREEN) echo -e "$GREEN_COLOR $2 $RES" ;; yellow|YELLOW) echo -e "$YELLOW_COLOR $2 $RES" ;; blue|BLUE) echo -e "$BLUE_COLOR $2 $RES" ;; *) echo "plu use:{red|green|yellow|blue} {chars}" exit esac } menu(){ cat <<END ================= 1.apple 2.pear 3.banana 4.cherry 5.exit ================== END } fruit(){ read -p "pls input the fruit your like:" fruit case "$fruit" in 1) add red apple ;; 2) add green pear ;; 3) add yellow banana ;; 4) add blue cherry ;; 5) exit ;; *) echo "pls select right num:{1|2|3|4}" exit esac } main(){ while true do menu fruit done } main
读取输入内容:
#!/bin/sh read -t 5 -p "Pls input a character:" a echo "your input is: $a"
read -p "Please input a number:" ans case "$ans" in 1) echo "the num you input is 1" ;; 2) echo "the num you input is 2" ;; [3-9]) echo "the num you input is $ans" ;; *) echo "the num you input must be less 9." exit;
esac
#!/bin/sh #no.1 menu cat <<EOF 1.[install lamp] 2.[install lnmp] 3.[exit] EOF #no.2 read -t 20 -p " pls input the num you want:" num [ "$num" != "1" -a "$num" != "2" -a "$num" != "3" ]&&{ echo "Input error" exit } #no.3 [ $num -eq 1 ]&&{ echo "install lamp" [ -f /server/scripts/lamp.sh ]&& /bin/sh /server/scripts/lamp.sh exit } [ $num -eq 2 ]&&{ echo "install lnmp" [ -f /server/scripts/lnmp.sh ]&& /bin/sh /server/scripts/lnmp.sh exit } [ $num -eq 3 ]&&{ echo "bye!" exit }
read -p "Pls input:" a expr $a + 1 &>/dev/null [ $? -eq 0 ] && echo int||echo chars
shell日志分级别输出函数
#!/bin/bash
#可将log函数单独放一个文件,通过.命令引入,这样就可以共用了
#. log.sh
#设置日志级别
loglevel=0 #debug:0; info:1; warn:2; error:3
logfile=$0".log"
function log {
local msg;local logtype
logtype=$1
msg=$2
datetime=`date +‘%F %H:%M:%S‘`
#使用内置变量$LINENO不行,不能显示调用那一行行号
#logformat="[${logtype}]\t${datetime}\tfuncname:${FUNCNAME[@]} [line:$LINENO]\t${msg}"
logformat="[${logtype}]\t${datetime}\tfuncname: ${FUNCNAME[@]/log/}\t[line:`caller 0 | awk ‘{print$1}‘`]\t${msg}"
#funname格式为log error main,如何取中间的error字段,去掉log好办,再去掉main,用echo awk? ${FUNCNAME[0]}不能满足多层函数嵌套
{
case $logtype in
debug)
[[ $loglevel -le 0 ]] && echo -e "\033[30m${logformat}\033[0m" ;;
info)
[[ $loglevel -le 1 ]] && echo -e "\033[32m${logformat}\033[0m" ;;
warn)
[[ $loglevel -le 2 ]] && echo -e "\033[33m${logformat}\033[0m" ;;
error)
[[ $loglevel -le 3 ]] && echo -e "\033[31m${logformat}\033[0m" ;;
esac
} | tee -a $logfile
}
#以下为测试
debug () {
log debug "there are $# parameters:$@"
}
info() {
log info "funcname:${FUNCNAME[@]},lineno:$LINENO"
}
warn() {
log warn "funcname:${FUNCNAME[0]},lineno:$LINENO"
}
error() {
log error "the first para:$1;the second para:$2"
}
set -x
debug first second
set +x
info first second
warn first second
error first second
本文出自 “那些年,学习的IT知识” 博客,谢绝转载!
标签:shell
原文地址:http://johnzheng.blog.51cto.com/1978756/1971698