马哥M28二十七、 进制转换、 $(())可以将其他进制转成十进制显示出来,用法如下: echo $((N#xxxxx)) N表示进制名称如2 8 16;#后面跟的是当前进制数值 echo $((2#110)) -> 6

计划任务crontab -e: 1.注意:crontab计划任务中,最好的就是使用绝对路径执行命令或者脚本,因为PATH定义不全 2.contab中 % 是有特殊含义的,必须使用\ 进行反转义

1.参数相关的命令表示,$#表示命令行传递的参数个数;$*或者$@表示打印所有传递的参数; $1,$2,$n 表示每个对应的参数; $@与$只有在使用双引号""包含时才会有所不同,"$"将所有参数作为一个整体字符串;而"$@"会将参数单独输出"$1" "$2".. 2.| xargs -n 1 userdel -r xargs本就是一个循环,使用-n 1将管道符传递的参数竖排显示传递给后面的命令,将本能一次只能接收一个参数的命令可以循环接收多个参数 3.检测所有用户无论是通过终端tty还是su - 切换的方式都能过滤出来:ps aux,既是查看终端所有用户的所有进程 4.排序: echo 1 -1 1.2 100 4 |xargs -n1 |sort -n 5.df |grep sda查看具体磁盘利用率 6.df |grep $diskname |while read lines;do 这种方式通过管道符将结果集传给 while read lines;do .. done,这样就可以不用生成文件再重定向获取文件了 7.echo $RANDOM |md5sum |cut -c1-5 :学习md5sum对数字进行加密;因为md5加密方式是固定字符串了,所以可以循环逆向破解 $RANDOM 0~32767

#!/bin/bash sum=0 for i in {1..32767};do num=echo $i |md5sum | cut -c1-10 case $num in efbaf275cd|4be9c40b8b|44b2395c46|f8c8873ce0|b902c16c8b|ad865d2f63) echo $i let sum++ ;; esac if [ $sum -lt 6 ];then continue else break fi done

练习:使用一条命令,一次创建指定的用户,如执行createuser.sh tom bob alice harry #!/bin/bash while [ $# -gt 0 ] do id $1 &>/dev/null if [ $? -eq 0 ];then echo "$1 is already exsit." shift continue fi useradd $1 echo "$1 用户创建成功" shift done

练习:每隔3秒钟到系统上获取已经登录的用户信息,如果发现用户kacker登录,则将登陆时间和主机记录于日志/var/log/login.log中,并退出脚本 #!/bin/bash while true;do if $(ps au |grep "^hacker." &>/dev/null);then echo $(ps au |grep "^hacer." |tr -s " " |cut -d" " -f1,7,9 )>>/var/log/login.log break exit else sleep 3s done

2.用两个以上的数字为参数,显示其中的最大值和最小值: 方法一: #!/bin/bash min=$1 max=$1 while [ $# -gt 0 ];do value=$1 if [ $value -gt max ];then max=value elif [ $value -lt $min ];then min=$value fi shift done echo "min is $min" echo "max is $max"

练习:select in .. 配合case in ... esac #!/bin/bash PS3="Please choose your menu:" select menu in a b c d do case in $REPLY in a) echo "";; b) echo "";; ... done

练习:打印国际象棋(使用函数编写脚本,每个格子由8个空格组成) #!/bin/bash red () { echo -e "\033[41m \033[0m\c" } yel () { echo -e "\033[43m \033[0m\c" } redyel () { for ((i=;i<=4;i++));do for ((j=1;j<=4;j++));do [ "$1" = "-r" ] && { yel;red; } || { red;yel; }

											done
						          echo 
						done

} for ((line=1;line<=8;line++));do [ $[$line%2] -eq 0 ] && redyel || redyel -r done

第二十九天、 函数.1.学习编程时调用系统shell好用的函数放到单独的文件里来实现某些功能调用存放函数的文件, . /path或者 source /path 使文件在当前shell环境中被读取里面的函数中的命令体并执行(调用函数时生效); 2.使用export声明的变量是环境变量,可以被子shell使用 3.函数必须就是在当前shell环境下运行,使用脚本就是开启一个子shell,函数在此下运行,又不会对脚本shell的shell产生影响; 4.ldd which 命令 查看命令所需要的所有类库(查找并解决类库丢失,使用cp不加任何参数复制时如果遇到软连接等直接将所连接到源文件内容复制到新的链接文件中) 5.source /etc/init.d/functions 使其生效,有许多可以调用使用的函数,现成的学习范例,加以理解和学习使用 6.注意:推荐,在函数里定义变量时,通常都需要使用Local或者set定义,Local定义局部变量只在函数体中生效,不影响外部shell以及外部函数;declare可以直接加变量名,但是不能单独使用-g 7.平日里,经常进行的操作或者功能都可以联想到创建函数或者使用python程序实现,方便以后调用(功能模块化

函数的返回值: return var 可以将值储存在变量中,return返回变量,也可以直接返回指定值,但不结束; unset取消函数或者变量的定义(set var 定义变量),仅影响当前shell及其子shell.

练习:3.斐波那契数列--黄金分割数列,数列是:0,1,1,2,3,5,8,13,21.。。。 斐波那契数列以如下被递归的方法定义:F(0)=0,F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2) (n>=2) 利用函数,求n阶斐波那契数列 #!/bin/bash shulie () { if [ $1 -eq 1 ];then echo -n "0" elif [ $1 -eq 2 ];then echo -n "1" elif [ $1 -gt 2 ];then echo -n "$[$(shulie $[$1-1])+$[$(shulie $[$1-2])]" fi

			 }
     a=$1
				for i in $(seq 1 $a);do
									shulie  $i
				done
				echo 

汉诺塔(又称河内塔)问题是源于印度一个古老传说。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘,利用函数,实现N片盘的汉诺塔的移动步骤

#!/bin/bash count=0 n_1() { let count++ echo "第${count}步:将${2}号圆盘从${1}移动到${3}" } n_2() { if [ $1 -eq 1 ];then n_1 $2 1 $4 else n_2 $[$1-1] $2 $4 $3 n_1 $2 $1 $4 n_2 $[$1-1] $3 $2 $4 } read -p "please input the number: " num n_2 $num X Y Z

num=3 n_2 3 X Y Z n_2 2 X Z Y fi n_2 1 X Y Z n_1 X 1 Z 输出:第1步:将1由X移到Z n_1 X 2 Y 输出:第2步:将2由X移到Y n_2 1 Z X Y n_1 Z 1 Y 输出:第3步:将1由Z移到Y n_1 X 3 Z 输出:第4步:将3由X移到Z n_2 2 Y X Z n_2 1 Y Z X n_1 Y 1 X 输出:第5步:将1由Y移动X

		n_1 Y 2 Z
			输出:第6步:将2由Y移到Z

		n_2 1 X Y Z
			n_1 X 1 Z
				输出:第7步:将1由X移到Z

第三十天、 数组: declare -x varname :声明环境变量 declare -xf 函数名 :声明环境函数 declare -g :设置函数为全局函数 declare -a [数组名] 声明索引数组或者查看所有索引数组 declare -A [数组名] 声明关联数组或者查看所有关联数组

title[0]=boss; name=(liubei guanyu zhanfei zhaoyun) course=(/var/log/*.log) -->所有以.log结尾的文件保存到course数组中,支持通配; b=([0]=linux [2]=python [5]=oracle) :稀疏索引数组,下标数值可以不连续; read -a menu -->接收参数作为menu数组的元素存储;

script=(/root/t*.sh) digit=({1..20})

数组的引用 echo $digit :此为只引用digit数组的第一个值 echo ${digit[N]} 指定下标以引用索引数组对应下标的值; echo ${digit[|@]} 引用数组的所有值 打印数组元素的数量 echo ${#array[]} ${#..}

练习:分别显示每一个值,每个值换行 1.for n in $(seq 0 $[${#array[*]}-1];do echo array[$n] is ${array[$n]} done 2.当下标默认是连续索引的索引数组 awk '{for (i in array).. } :在awk此类的语言中,循环遍历数组的元素,此时i会循环遍历array数组的索引,输出$i只是打印遍历的第一个索引对应的元素; [root@magedu 2018-03-24 test_sh]# awk 'BEGIN{split('""172.18.0.1""',a,".");for(i in a)print i,a[i]}'
4 1 1 172 2 18 3 0

3.在索引数组中加值,加到最后: array[${#testshuzu[*]}]=machao; 删除数组中的某个值: unset array[i]; 删除整个数组: unset array;

数组的切片:
	offset:要跳过的元素个数;
	number:要取出的元素个数;
	取偏移量之后的所有元素
	echo ${testshuzu[@]:1:3}  :跳过数组第一个元素,取之后的三个
	echo ${testshuzu[@]:1}   :跳过一个值,取到最后

关联数组: 一、先声明,再赋值 declare -A testshuzu testshuzu=([zhugong]=liubei [erdi]=guanyu [sandi]=zhangfei) 二、声明,赋值一步到位 declare -A weiguo=([chengxiang]=caocao ...)

	练习:写一个脚本会生成一个名为digit的数组包含十个随机数,显示数组的所有值,再取最大值、最小值   ($RANDOM  0-32767)
	   #!/bin/bash
		 declare -i  min max
		 declare -a digit
		 for ((i=0;i<10;i++));do
					 digit[$i]=$RANDOM
					 [ $i -eq 0 ] && { min=${digit[0]};max=${digit[0]}; } && continue
					 [ ${digit[$i]} -gt $max ] && max=${digit[$i]} &&continue
					 [ ${digit[$i]} -lt $min ]  && min=${digit[$i]} &&continue
		 done
		 echo ALL digits are ${digit[*]}
		 echo MAX is $max
		 echo MIN  is $min
		 
练习2.编写脚本,定义一个数组,数组中的元素是/var/log目录下的所有以.log结尾的文件,统计出其下标为偶数的文件中的行数之和
	 #!/bin/bash
	 sum=0
	 declare  -a logfile=(/var/log/*.log)
	 echo ALL logfiles name are ${logfile[*]}
	 for i in $(seq 0 $[${#logfile[*]}-1]);do
			   [ $[i%2] -eq 0 ] && let sum+=`cat ${logfile[$i]} |wc -l` ||continue
	 done
	 echo All lines are $sum

1.作业:输入若干数值存入数组中,采用冒泡算法进行升序或降序排序; 2.实现转置矩阵matrix.sh 1 2 3 1 4 7 4 5 6 ==> 2 5 8 7 8 9 3 6 9

显示变量或数组元素的字符数:
echo ${#var}     echo ${#array[N]}
echo ${name:2:3}   从变量name左边跳过2个字符,取3个字符
echo ${name:2}   从变量name左边跳过2个字符,取到最后
echo  ${name:  -2}   从变量name右侧向左取两个字符,注意冒号后至少打一个空格
echo ${name:  -3:1}  从右向左取3个字符,再从左向右去掉1个字符

echo ${name: -3: -1} 从右向左取3个字符,再从右向左去掉一个字符

字符串处理 从左向右查找:echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin echo ${PATH#*local} : /sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin ${var#*pattern} :从左向右匹配变量var的pattern并将左侧第一个以及到最左侧的字符串删除

 echo ${PATH##*local}   :贪婪模式,将匹配到的最后一个local及其到最左侧的字符串全部删除显示
 
从右至左
echo ${PATH%local*}   
echo ${PATH%%local*}
url=http://www.magedu.com:8080
echo ${url%%/*}  http:
echo ${url##*:}     8080

for i in /etc/profile.d/*.sh ;do if [ -r "$i" ];then if [ "${-#*i}" != "$-" ];then : '-' 减号是一个变量,通过"$-"查看支持的扩展功能 . "$i" else . "$i" >/dev/null fi fi done

查找替换: ${var/pattern/substr} :查找var所表示的字符串中,第一次被pattern所匹配到的字符串,以substr替换之; ${var//pattern/substr} :查找var所表示的字符串中,所有能被pattern所匹配到的字符串,以substr替换之; ${var/#pattern/substr} :查找var所表示的字符串中,行首被pattern所匹配到的字符串,以substr替换之; ${var/%pattern/substr} :查找var所表示的字符串中,行尾被pattern所匹配到的字符串,以substr替换之;

查找并删除: ${var/pattern} : 删除所表示的字符串中第一次被pattern所匹配到的字符串 ${var//pattern} : 删除var所表示的字符串中所有被pattern所匹配到的字符串 ${var/#pattern}: 删除var所表示的字符串中所有以pattern为行首所匹配到字符串 ${var/%pattern} : 删除var所表示的字符串中所有以pattern为行尾所匹配到的字符串

大小写转换 name="Zhangfei Liubei" echo ${name,,} 变量后面跟两个逗号,表示大写全部转换成小写 echo ${name^^} 变量后面跟两个^^,表示小写全部转换成大写

Shell变量一般是无类型的,但是bash Shell提供了declare和 typeset两个命令用于指定变量的类型,两个命令是等价的  declare [选项] 变量名 -r 声明或显示只读变量 -i 将变量定义为整型数 -a 将变量定义为数组 -A 将变量定义为关联数组 -f 显示已定义的所有函数名及其内容 -F 仅显示已定义的所有函数名 -x 声明或显示环境变量和函数 -l 声明变量为小写字母 declare –l var=UPPER -u 声明变量为大写字母 declare –u var=lower

[root@centos7 ~]# mage=linux [root@centos7 ~]# linux=centos [root@centos7 ~]# eval echo $$mage
centos

[root@centos7 ~]# centos=redhat

[root@centos7 ~]# eval echo $$(eval echo $$mage)
redhat

[root@centos7 ~]# n=10 [root@centos7 ~]# echo {1..$n} {1..10} [root@centos7 ~]# eval echo {1..$n} 1 2 3 4 5 6 7 8 9 10

[root@centos7 ~]# echo $mage linux [root@centos7 ~]# echo $linux centos [root@centos7 ~]# test=${!mage} [root@centos7 ~]# echo $test centos

mktemp命令:创建并显示临时文件,可避免冲突  mktemp [OPTION]... [TEMPLATE] TEMPLATE: filename.XXX X至少要出现三个  OPTION: -d: 创建临时目录 -p DIR或--tmpdir=DIR:指明临时文件所存放目录位置  示例: mktemp /tmp/test.XXX tmpdir=mktemp –d /tmp/testdir.XXX mktemp --tmpdir=/testdir test.XXXXXX

ll命令: install [OPTION]... [-T] SOURCE DEST 单文件 install [OPTION]... SOURCE... DIRECTORY install [OPTION]... -t DIRECTORY SOURCE... install [OPTION]... -d DIRECTORY...创建空目录  选项: -m MODE,默认755 -o OWNER -g GROUP  示例: install -m 700 -o wang -g admins srcfile desfile install –m –d /testdir/installdir

install -m 700 -o liubei -g root /etc/passwd /app/hellopasswd

expect

ssh1.exp #!/usr/bin/expect spawn ssh root@172.18.253.95 expect { "yes/no" { send "yes\n" ;exp_continue } "password" { send "centos\n" } } interact #expect eof

#!/usr/bin/expect set user root set remotehost 172.18.253.95 set password centos spawn ssh $user@$remotehost expect { "yes/no" { send "yes\n" ;exp_continue } "password" { send "$password\n" } } interact #expect eof

执行登录后的后续操作 #!/usr/bin/expect set user [lindex $argv 0] set remotehost [lindex $argv 1] set password [lindex $argv 2] spawn ssh $user@$remotehost expect { "yes/no" { send "yes\n" ;exp_continue } "password" { send "$password\n" } } expect "]#" { send "useradd liubei\n" } expect "]#" { send "echo redhat|passwd --stdin liubei\n" } send "exit\n" expect eof ~

使用shell脚本格式 #!/bin/bash user=$1 remotehost=$2 password=$3 expect << EOF spawn ssh $user@$remotehost expect { "yes/no" { send "yes\n" ;exp_continue } "password" { send "$password\n" } } expect "]#" { send "useradd liubei\n" } expect "]#" { send "echo redhat|passwd --stdin liubei\n" } send "exit\n" expect eof EOF