很有用的shell脚本
基础知识
expect基础知识
- exp_continue是匹配一行后,从当前expect块第一行开始匹配
- expect块的每一行匹配后,直接退出当前expect块,往下一个expect块开始匹配
- expect块需要send的信息中包含双引号 ”“ ,需要进行 \ 转义
shell基础知识
脚本其实就是短小的、用来让计算机自动化完成一系列工作的程序,这类程序可以用文本编辑器修改,不需要编译,通常是解释运行的。
变量
用语句给变量赋值
for file in `ls /etc` 或 for file in $(ls /etc) 或 ip=`awk '{ print $1 }' iplist` # 变量能重新赋值,使用变量可以用$ip、${ip} 或 ip=$(awk '{ print $1 }' iplist)
函数
- 所有函数在使用前必须定义。这意味着必须将函数放在脚本开始部分,直至shell解释器首次发现它时,才可以使用。调用函数仅使用其函数名即可。
- 在函数体内部,当n>=10时,需要使用${n}来获取参数。
- 函数返回值在调用该函数后通过 $? 来获得。
处理参数列表
参数处理 | 说明 |
---|---|
$# | 传递到脚本的参数个数 |
$* | 以一个单字符串显示所有向脚本传递的参数 |
$$ | 脚本运行的当前进程ID号 |
$! | 后台运行的最后一个进程的ID号 |
$@ | 与$*相同,但是使用时加引号,并在引号中返回每个参数。 |
$- | 显示Shell使用的当前选项,与set命令功能相同。 |
$? | 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。 |
$@与$*加引号时区别:$@在引号中返回每个参数
#!/usr/bin/bash source ./color.sh # "$*" echo -e "${RED}\"$ *\":" for i in "$*";do echo -e "${RED}$i${CLOSE_ALL}" done echo -e "\n" # "$@" echo -e "${BLUE}\"$ @\":" for i in "$@";do echo -e "${BLUE}$i${CLOSE_ALL}" done
结果截图
输入/输出重定向
输入/输出重定向列表
命令 | 说明 |
---|---|
command > file | 将输出重定向到 file。 |
command < file | 将输入重定向到 file。 |
command >> file | 将输出以追加的方式重定向到 file。 |
n > file | 将文件描述符为 n 的文件重定向到 file。 |
n >> file | 将文件描述符为 n 的文件以追加的方式重定向到 file。 |
n >& m | 将输出文件 m 和 n 合并。 |
n <& m | 将输入文件 m 和 n 合并。 |
<< tag | 将开始标记 tag 和结束标记 tag 之间的内容作为输入。 |
文件描述符 0 通常是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。
实例
$ command1 < infile > outfile
同时替换输入和输出,执行command1,从文件infile读取内容,然后将输出写入到outfile中。command 命令将 stdin 重定向到 file1,将 stdout 重定向到 file2。
$ command > file 2>&1
$ find /etc -name "*.txt" > list 2>&1
stdout 和 stderr 合并后重定向到 file。先将要输出到stdout的内容重定向到文件,此时文件list就是这个程序的stdout,再将stderr重定向到stdout,也就是文件list。此时屏幕不显示信息,在list中显示,通过cat list查看。
$ command 2>&1 > file
$ find /etc -name "*.txt" 2>&1 >list
stderr重定向到stdout,stdout重定向到file。先将要输出到stderr的内容重定向到stdout,此时会产生一个stdout的拷贝,作为程序的stderr,而程序原本要输出到stdout的内容,依然是对接在stdout原身上的,
因此第二步重定向stdout,对stdout的拷贝不产生任何影响。此时屏幕会输出错误信息,标准输出在list中显示,通过cat list查看。
$ command > /dev/null 2>&1
屏蔽 stdout 和 stderr,不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。
文件包含
. filename
或
source filename
包含外部脚本。这样可以很方便的封装一些公用的代码作为一个独立的文件。如实例中batch.sh通过source包含color.sh脚本。
实例1、批量登录远程Linux服务器
包括4个文件:batch.sh(批量管理expect登录脚本)color.sh(颜色脚本)、sshLogin.exp(expect登录脚本)、iplist(用于登录的IP、用户名和用户密码)
batch.sh(批量管理expect登录脚本)
#!/usr/bin/bash source ./color.sh callSSH() { # $$:pid $1:filename $2:username $3:ip $4:password echo -e "$GREEN Param init(pid: $$): $1 $2 $3 $4 $CLOSE_ALL" expect $1 $2 $3 $4 return $? } sshManage() { i=1 for ip in `awk 'NR>2 {print $1}' iplist` do user=$(awk -v IP=$ip '{if(IP==$1) print $2}' iplist) password=`awk -v IP=$ip '{if(IP==$1) print $3}' iplist` if [ $i -le 9 ] then i="0$i" else i="$i" fi echo -e "$BLUE<<-------------- Login $ip($i) begin -------------->>$CLOSE_ALL" callSSH sshLogin.exp $user $ip $password echo -e "${BLUE}return_value = $? $CLOSE_ALL" echo -e "$BLUE<<-------------- Login $ip($i) end-------------->>$CLOSE_ALL" let "i++" done } echo -e "$RED<<<<<<<<<<<<<<<<<<<<<< sshManage begin >>>>>>>>>>>>>>>>>>>>>>$CLOSE_ALL" sshManage echo -e "$RED<<<<<<<<<<<<<<<<<<<<<< sshManage end >>>>>>>>>>>>>>>>>>>>>>$CLOSE_ALL"
color.sh(颜色脚本)
#!/usr/bin/bash # Example: # echo -e "\033[字背景颜色;文字颜色m 字符串 \033[0m" # echo -e "\033[41;36m something here \033[0m" # echo -e "$RED something here $CLOSE_ALL" # font color: 30-37 BLACK="\033[30m" # 黑色 RED="\033[31m" # 红色 GREEN="\033[32m" # 绿色 YELLOW="\033[33m" # 黄色 BLUE="\033[34m" # 蓝色 PURPLE="\033[35m" # 紫色 SKY_BLUE="\033[36m" # 天蓝色 WHITE="\033[37m" # 白色 # blackground color: 40-47 BLACK_WHITE="\033[40;37m" # 黑底白字 RED_WHITE="\033[41;37m" # 红底白字 GREEN_WHITE="\033[42;37m" # 绿底白字 YELLOW_WHITE="\033[43;37m" # 黄底白字 BLUE_WHITE="\033[44;37m" # 蓝底白字 PURPLE_WHITE="\033[45;37m" # 紫底白字 SKY_BLUE_WHITE="\033[46;37m" # 天蓝底白字 WHITE_BLACK="\033[47;30m" # 白底黑字 # Control options CLOSE_ALL="\033[0m" # 关闭所有属性 HIGH_BRIGHTNESS="\33[1m" # 设置高亮度 UNDERLINE="\33[4m" # 下划线 FLICKER="\33[5m" # 闪烁 REVERSE_DISPLAY="\33[7m" # 反显 SET_FOREGROUND="\33[30m — \33[37m" # 设置前景色 SET_BACKGROUND="\33[40m — \33[47m" # 设置背景色 SET_CURSOR_POS="\33[y;xH" # 设置光标位置 N_CURSOR_UP="\33[nA" # 光标上移n行 N_CURSOR_DOWN="\33[nB" # 光标下移n行 N_CURSOR_RIGHT="\33[nC" # 光标右移n行 N_CURSOR_LEFT="\33[nD" # 光标左移n行 CURSOR_POS_SAVE="\33[s" # 保存光标位置 CURSOR_POS_RECOVER="\33[u" # 恢复光标位置 CURSOR_HIDE="\33[?25l" # 隐藏光标 CURSOR_DISPLAY="\33[?25h" # 显示光标 CLEAR_SCREEN="\33[2J" # 清屏 CLEAR_CONTENT="\33[K" # 清除从光标到行尾的内容
sshLogin.exp(expect登录脚本)
#!/usr/bin/expect if { $argc != 3 } { send -- "Usage: expect sshLogin.exp username ip password\n" exit 1 } #Param set userName [lindex $argv 0] set IP [lindex $argv 1] set password [lindex $argv 2] set timeout 30 spawn ssh -P22 $userName@$IP expect { eof { exit 0 } timeout { exit 1 } "*password*" { send -- "$password\n" } "*(yes/no)?*" { send -- "yes\n";exp_continue } } expect { eof { exit 0 } timeout { exit 1 } "*#*" { send -- "find /etc -names \"*.txt\" >list 2>&1\n" } } expect { eof { exit 0 } timeout { exit 1 } "*#*" { send -- "cat list\n" } } set timeout 5 expect { eof { exit 0 } timeout { exit 1 } "*#*" { send -- "\n" } } expect { eof { exit 0 } timeout { exit 1 } "*#*" { send -- "exit\n" } } expect eof exit
iplist(用于登录的IP、用户名和用户密码)
#ip username password 10.10.3.128 root ****** 10.10.1.21 root ******
结果截图
实例2、批量激活脚本
#!/bin/bash chmod 777 spv*.bin ./spv*.bin echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" eth=`ifconfig |awk '{print $1}' | awk 'NR==1{print}' | awk -F':' '{print $1}'` ip=`ifconfig $eth | grep netmask |awk '{print $2}'| awk -F '.' '{print $4}'` mv /tmp/spv_License/spv_License/License$ip.txt /home/spv/config/spvlicense chown apache.apache /home/spv/config/spvlicense mysql -uuser -ppassword dbname -e "insert into user_role (userID,roleID) values (100,1);" #echo "first code is:" #cat /tmp/spv_License/spv_License/ code=`cat /tmp/spv_License/spv_License/$ip\_license.txt` #echo "first code is:$code" echo -e "\033[35m first code is:$code \033[0m" #echo "please reboot this hac now" if [ $? == 0 ]; then echo -e "\033[35m Import license success,please reboot this hac now. \033[0m" else echo -e "\033[31m Import license failure,please Import license by yourself ! \033[0m" fi
/tmp/spv_License/spv_License目录下的文件,包含所有的激活文件。
eth为ifconfig下的第一列中的第一行以逗号分隔的第一个字段。也就是eth0。
ip为ifconfig eth0下的查找关键字netmask所在行的第二个字段下以逗号分隔的第四个字段,也就是126。
连接MySQL数据库,执行SQL:mysql -uuser -ppassword -e " sql "
chown将spvlicense文件的拥有者改为apache.apache
-------------------------------------------
Wish you all the best and good health in 2021.