很有用的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 "
"

# "$@"
echo -e "${BLUE}"$ @":"
for i in "$@";do
echo -e "${BLUE}$i${CLOSE_ALL}"
done
test.sh

结果截图

输入/输出重定向

 输入/输出重定向列表

命令说明
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"
batch.sh

color.sh(颜色脚本)

#!/usr/bin/bash

# Example:
#       echo -e "33[字背景颜色;文字颜色m          字符串          33[0m"
#       echo -e "33[41;36m                   something here       33[0m"
#       echo -e "$RED                   something here       $CLOSE_ALL"

# font color: 30-37
BLACK="33[30m"                            # 黑色
RED="33[31m"                              # 红色
GREEN="33[32m"                            # 绿色
YELLOW="33[33m"                           # 黄色
BLUE="33[34m"                             # 蓝色
PURPLE="33[35m"                           # 紫色
SKY_BLUE="33[36m"                         # 天蓝色
WHITE="33[37m"                            # 白色

# blackground color: 40-47
BLACK_WHITE="33[40;37m"                   # 黑底白字
RED_WHITE="33[41;37m"                     # 红底白字
GREEN_WHITE="33[42;37m"                   # 绿底白字
YELLOW_WHITE="33[43;37m"                  # 黄底白字
BLUE_WHITE="33[44;37m"                    # 蓝底白字
PURPLE_WHITE="33[45;37m"                  # 紫底白字
SKY_BLUE_WHITE="33[46;37m"                # 天蓝底白字
WHITE_BLACK="33[47;30m"                   # 白底黑字

# Control options
CLOSE_ALL="33[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"                      # 清除从光标到行尾的内容
color.sh

sshLogin.exp(expect登录脚本)

#!/usr/bin/expect

if { $argc != 3 } {
    send -- "Usage: expect sshLogin.exp username ip password
"
    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
" }
    "*(yes/no)?*" { send -- "yes
";exp_continue }
}

expect {
    eof { exit 0 }
    timeout { exit 1 }
    "*#*" { send -- "find /etc -names "*.txt"  >list 2>&1
" }
}

expect {
    eof { exit 0 }
    timeout { exit 1 }
    "*#*" { send -- "cat list
" }
}

set timeout 5
expect {
    eof { exit 0 }
    timeout { exit 1 }
    "*#*" { send -- "
" }
}

expect {
    eof { exit 0 }
    timeout { exit 1 }
    "*#*" { send -- "exit
" }
}
expect eof
exit
sshLogin.sh

iplist(用于登录的IP、用户名和用户密码)

#ip username password

10.10.3.128 root ******
10.10.1.21  root ******
iplist

结果截图

 实例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 "33[35m  first code is:$code 33[0m"

#echo "please reboot this hac now"
if [ $? == 0 ];
  then
   echo -e "33[35m  Import license success,please reboot this hac now. 33[0m"
 else
   echo -e "33[31m Import license failure,please Import license by yourself ! 33[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


作者:yusq77

-------------------------------------------

Wish you all the best and good health in 2021.

原文地址:https://www.cnblogs.com/yusq77/p/10913427.html