shell编程之免交互

发布于:2024-06-25 ⋅ 阅读:(136) ⋅ 点赞:(0)

Here Document 

        它在 Linux Shell 中使用 I/O 重定向的方式将命令列表提供给交互式程序或命令

        Here Document 是标准输入的一种替代品

        帮助脚本开发不必使用临时文件来构建输入信息,而是直接生成文件并用作命令的标准输入

        示例

[root@bogon ~]# cat > my.cof << xiaojing
> asdfaf
> asdfs
> asdcvd
> asdv
> xiaojing
[root@bogon ~]# 

                标记可以使用任意的合法字符

                结尾的标记一定要顶格写,前面不能有任何字符

                结尾的标记后面也不能有任何字符(包括空格)

                开头的标记前后的空格会被省略掉

        什么是免交互

                它通过I/O重定向的方式将命令列表提供给交互式程序或命令,从而避免了用户的手工输入,提高了脚本的自动化程度

                 统计文件内有多少行内容

                        wc -l 命令后面直接跟文件名就可以

                Here Document 格式控制

                        关闭变量替换的功能

passwd lisi << 'eof'
#单引号的作用代表以下特殊字符,失去特殊含义
123
123
eof

                            去掉每行之前的 TAB 字符(抑制各行首 TAB 的作用)

[root@localhost ~]# vim here_format_tab.sh
#!/bin/bash cat <<-'EOF'
This is Line 1.
$kgc
EOF
[root@localhost ~]# sh here_format_tab.sh
This is Line 1.
$kgc	//输出结果同上一示例
                变量设定

                        标记之间有变量被使用,会先替换变量值

[root@localhost ~]# vim here_var_replace.sh
#!/bin/bash doc_file="2019.txt" i="company"
cat > $doc_file << HERE Take him from home to $i HERE
[root@localhost ~]# chmod +x here_var_replace.sh [root@localhost ~]# ./here_var_replace.sh [root@localhost ~]# cat 2019.txt
Take him from home to company

       expect 概述

                expect

                        可以让一些需要交互的任务自动化地完成

                        进行自动化控制和测试的工具

                        主要解决 shell 脚本中不可交互的问题

                expect 安装

                        1.安装软件

                                yum -y install expect

                        2.编辑ssh连接脚本文件


#!/usr/bin/expect

#设置超时时间
set timeout 60


#连接地址
spawn ssh root@192.168.27.131
expect {  
    "*(yes/no)*" { send "yes\r"; exp_continue }  # 如果出现"yes/no"提示,发送"yes"并继续等待  
    "*password:*" { send "123456\r" }  # 使用更具体的匹配模式  
}  
#确认登录成功,能匹配到#号就代表成功
expect "*#" {send "ifconfig ens33 \r" }


#退出方式
interact

                                # expect eof :等待执行结束,若没有这一句,可能导致命令还没执行,脚本就结束了
                                # interact : 执行完成后保持交互状态, 把控制权交给控制台,这时可以手动输入信息。 需要注意的是,expect eof 与 interact 只能二选一。

                    脚本    

#!/usr/bin/expect
# expect 将超时时间设置为 60 秒
set timeout 60
# 记录日志文件
log_file test.log
# 开启控制台输出,为0时,控制台不输出
log_user 1

# $argc 表示参数个数
if {$argc<1} { 
# send_user相当于shell的echo
send_user "usage: $argv0 <param1><param2> ... " 
exit 
}

set hostname [lindex $argv 0]
set password [lindex $argv 1]
# spawn 后面通常跟一个命令,表示开启一个会话、启动进程,并跟踪后续交互信息
spawn ssh root@${hostname}
expect {
  "(yes/no)"
  # 匹配的(yes/no)时自动输入yes,exp_continue 表示允许 expect 继续向下执行指令
  {send "yes\r"; exp_continue}
  "*password"
  {send "$password\r"}
}

expect "*#" {send "ifconfig\r"}

# expect eof :等待执行结束,若没有这一句,可能导致命令还没执行,脚本就结束了
# interact : 执行完成后保持交互状态, 把控制权交给控制台,这时可以手动输入信息。 需要注意的是,expect eof 与 interact 只能二选一。
interact

                        创建用户脚本

#!/bin/bash 
user=$1 
password=$2 
useradd $user 
expect << EOF 
# 开启一个进程跟踪 passwd 命令,expect 只能捕捉该进程信息
spawn passwd $user 
# 匹配输出信息"New password:" 
expect "New password:"
# 自动输入密码 ,英文版的可以捕捉,中文版的可能会报错
send "${password}\r"
# 匹配输出信息"Retype new password:"
expect "Retype new password:" 
# 自动输入密码
send "${password}\r" 
# 等待结束标记
expect eof; 
EOF

 课后作业  免交互式等ssh

#!/bin/bash


# 检查是否安装expect命令
check_expect_cmd() {
	#查找命令是否存在,返回0存在,否则是不存在
	if command -v expect &> /dev/null ;then
		return 0
	else
		return 1
		
	fi

}

#安装expect命令
install_expect() {
	#判断操作系统,根据系统不同,执行不同的安装指令
	if command -v dnf &> /dev/null ;then
		dnf -y install expect
	elif command -v yum &> /dev/null ;then
		yum -y install expect
	elif command -v apt-get &> /dev/null ;then
		apt-get -y install expect
	else
		echo "$(data) ERROR:未知错误,请手动添加"
	fi

}
#执行命令
runcmd() {
	local hostip=$1
	local user=$2
	local password=$3
	local port=$4
	local cmd=$5
expect << EOF

#定义超时时间
set timeout 60
#追踪ssh命令
spawn ssh -p ${port} ${user}@${hostip}
expect {
	"(yes/no)"
	{ send "yes\r";exp_continue}
	"*password"
	{ send "${password}\r"}
}

#匹配密码错误时退出
expect "*please try again*" {
	send_user "\nERROR: password error\n"
}

#执行命令
expect -re "(#|\$)" { send "${cmd}\n"}
expect -re "(#|\$)" { send "exit\n"}

#等待结束
expect eof;
EOF
}
if ! check_expect_cmd ;then
	install_expect
fi
runcmd "192.168.27.129" "root" "123456" "22" "pwd"


etc/os-release   Linux中都存在这个文件,可以用来过滤操作系统
dnf是yum命令的升级版:
 

[root@bogon ~]# cat host.cfg
[test]
192.168.27.131 username=root password=123456 port=22
192.168.27.110 username=root password=123456 port=22


[kgc]
192.168.27.128 username=root password=123456 port=22
192.168.27.131 username=root password=123456 port=22


根据文本文件连接

#!/bin/bash

file_name="hosts.cfg"

# 判断配置文件是否存在
check_file() {
	local file=$1
	if [ ! -f "$file" ];then
		echo "$(date) ERROR: ${file} 不存在"
		exit 1
	fi
}

# 判断组是否存在
check_group() {
	local group=$1
	grep -w "\[${group}\]" $file_name &> /dev/null
	if [ "$?" -eq 0 ];then
		return 0
	else
		exit 1
	fi
}

# 检测是否有expect命令
# 返回0表示存在命令,返回1表示不存在命令
check_expect_cmd() {
	if command -v expect &> /dev/null ;then
		return 0
	else
		return 1
	fi
}

# 安装expect
install_expect() {
	if command -v dnf &> /dev/null ;then
		dnf -y install expect
	elif command -v yum &> /dev/null ;then
		yum -y install expect
	elif command -v apt-get &> /dev/null ;then
		apt-get -y install expect
	else
		echo "$(date) ERROR: 未知的操作系统,请手动安装expect命令"
	fi
}

# 执行命令
runcmd() {
	local hostip=$1
	local user=$2
	local password=$3
	local port=$4
	local cmd=$5
expect << EOF
# 定义超时时间
set timeout 10

# 追踪ssh命令
spawn ssh -p ${port} ${user}@${hostip}
expect {
	"(yes/no)"
		{ send "yes\r";exp_continue }
	"*password"
		{ send "${password}\r" }
}

# 匹配到密码错误时退出
expect "*please try again*" {
	send_user "\nERROR: password error\n"
}

# 执行命令
expect -re "(#|\$)" { send "${cmd}\n" }
expect -re "(#|\$)" { send "exit\n" }

# 等待结束标记
expect eof;
EOF
}

# 获取指定组里面的信息
get_group_info() {
	local group_name=$1
	local ip
	local user
	local password
	local port
	local cmd=$2
	local info=$(awk -v group="$group_name" '
        $0 ~ "^\\[" group "\\]$" { test=1; next }
        $0 ~ "^\\[" { test=0 }
        test && /^[^[:space:]]+/{ print $1, $2, $3, $4 }
    ' "$file_name")
	echo "$info" | while IFS= read -r line;do 
        # 获取相关信息
        ip=$(echo "${line}" | awk '{print $1}')
        user=$(echo "${line}" | awk '{print $2}' | awk -F '=' '{print $2}')
        password=$(echo "${line}" | awk '{print $3}' | awk -F '=' '{print $2}')
        port=$(echo "${line}" | awk '{print $4}' | awk -F '=' '{print $2}')
 
        # 执行命令
        runcmd "${ip}" "${user}" "${password}" "${port}" "${cmd}"
    done 
}

main() {
    while getopts "f:g:c:h" opt; do
        case $opt in
            f)
                file_name=$OPTARG
                ;;
            g)
                group=$OPTARG
                ;;
            c)
                cmd=$OPTARG
                if [ -z "$cmd" ]; then
                    echo "no command"
                    exit 1
                fi
                ;;
            h)
                echo "Usage: $0 -f hosts.cfg -g group -c cmd"
        esac
    done
    # 判断是否有命令
    if ! check_expect_cmd ;then
	install_expect
    fi
    
    # 检测配置文件是否存在
    check_file "$file_name"
    # 检测组是否存在
    if [ "$?" -eq 0 ] ;then
	check_group "$group"
    else
	exit 1
    fi
    # 批量执行命令
    get_group_info "$group" "$cmd"
}

if [ "$#" -eq 0 ];then
	main -h
	exit 1
fi

main "$@"


网站公告

今日签到

点亮在社区的每一天
去签到