1.编写一个shell脚本自动连接其他的虚拟机
[root@shenzhen mnt]# vim file1.sh ##编辑脚本
[root@shenzhen mnt]# sh file1.sh 172.25.254.228 redhat ##尝试执行脚本并写入想要连接的ip和密码
[root@xiaan ~]# exit ##退出连接的虚拟机
脚本中写入的内容如下:
#!/bin/bash ##运行环境可以使用which查看
/usr/bin/expect <<EOF ##在EOF内的命令都会被定义在/usr/bin/expect中
spawn ssh root@$1
expect {
"yes/no" { send "yes\r";exp_continue }
"password" { send "$2\r" }
}
expect eof
EOF
说明:
在执行过程中可能会出现以下情况,因为无法保留expect的交互界面,所以无法在连接的虚拟机中输入命令,而且其会自动退出,如下所示:
<1>在连接的虚拟机中输入的命令会进行延续
[root@shenzhen mnt]# sh file1.sh 172.25.254.228 redhat
[root@xiaan ~]# ls
[root@shenzhen mnt]# ls
<2>在连接的虚拟机中输入的命令会进行延续
[root@shenzhen mnt]# sh file1.sh 172.25.254.228 redhat
[root@xiaan ~]# exit
[root@shenzhen mnt]# exit
<3>在连接的虚拟机中如果不输入任何命令,会自动退出
[root@shenzhen mnt]# sh file1.sh 172.25.254.228 redhat
[root@xiaan ~]# [root@shenzhen mnt]#
分析:
1.#!/bin/bash这一行告诉操作系统脚本里的代码使用哪一个shell来执行,这里的expect其实和linux下的bash,windows下的cmd是一类东西
2.set timeout 30 指设置超时时间
3.spawn是进入expect环境后才可以执行的expect内部命令,如果没有装expect或者直接在默认的shell下执行是找不到spawn命令的。所以不要用“which spawn”之类的命令去赵spawn命令。好比windows里的dir就是一个内部命令,这个命令由shell自带,你无法找到一个dir.com或dir.exe可执行文件。它只要的功能就是给ssh运行进程加个壳,用来传递交互指令
4.expect “password:”:这里的expect也是expect的一个内部命令,expect的shell命令和内部命令是一样的,但不是一个功能。这个命令的意思是判断上次输出结果里是否包含”password:“色字符串,如果有则立即返回,否则就等待一段时间后返回,这里等待时间就是前面的超时设置
5.send “ispass\r”:这里就是执行交互动作,与手工输入密码的动作等效,如果出现异常等待可以查看一下
6.interact:执行完成之后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了,如果没有这一句登陆完成后会自动退出,而不是留在远程终端上
7.expext在做系统管理时,我们很多时候需要输入密码,例如:连接ssh/ftp,当我们使用expect时,就能代替我们实现与终端的交互,不用守在电脑旁边输出密码,或是根据系统的输出再运行相应的命令。
8.expect是一种脚本语言
9.一个脚本的运行环境只能是一个(如#!/bin/bash)
10.在EOF内的命令都会被定义在/usr/bin/expect中
11.可以使用$1,因为运行环境是shell,最终的结果会倒到expect中
12.不会保留环境,因为会自动退出
13.shell和expect的混合之后是不能用的,运行成功后也无法使用,因为无法保留expect的交互界面
14.批量执行命令的时候用shell和expect结合
2.编写一个脚本使其可以自动连接别的虚拟机,并且将成功连接好的虚拟机的主机名保存到一个某一个为文件中
[root@shenzhen mnt]# vim auto_ssh.sh ##编写脚本
[root@shenzhen mnt]# sh auto_ssh.sh heihei ##执行脚本并将其可以连接成功的的ip的主机名放至名称为heihei的文件中
[root@shenzhen mnt]# vim heihei ##查看文件heihei中是否有连接成功的主机名
脚本中的内容如下:
#!/bin/bash
Auto_ssh()
{
/usr/bin/expect <<EOF
spawn ssh [email protected].$1 $2
expect {
"yes/no" { send "yes\r";exp_continue }
"password" { send "redhat\r" }
}
expect eof
EOF
}
for IP_ID in {225..229} ##设置的ip范围为172.25.254.225-172.25.254.229
do
ping -c1 -w1 172.25.254.$IP_ID &> /dev/null ##尝试连接ip并将其可能出现的报错或其他提示信息放至垃圾箱中
if
[ "$?" -eq "0" ] ##如果命令的退出值等于0
then
Auto_ssh $IP_ID hostname | grep "password:" -A1 | tail -n 1 >>$1 ##调用函数Auto_ssh,并且“$IP_ID”为函数中的第一串字符(即$1),hostname为函数的第二串字符(即$2);-A1表示下一行;并将最后一行内容放到执行脚本时写的文件中
fi
done
运行后的结果如下:
注意:
1.脚本中实现了自动登陆,自动检测
2.脚本中一个是函数的$1,一个是脚本的$1
3.编写一个shell脚本使论坛自动部署
要求:
服务自动部署示例:
执行脚本 lamp.sh
脚本执行后部署好论坛,并设定apache的网络接口为8080
实验:
首先查看/mnt目录下是否有论坛的安装包,并编写脚本lamp.sh
[root@shenzhen mnt]# ls
[root@shenzhen mnt]# vim lamp.sh
脚本的内容如下:
#!/bin/bash
unzip /mnt/Discuz_X3.2_SC_UTF8.zip -d /tmp &> /dev/null ##解压论坛安装包并将其放至/tmp目录下
Install_APP() ##设置安装过程为一个函数
{
yum list $1 &> /dev/null ##查看yum列表是否有其软件包
[ "$?" = "0" ]&&{ ##如果退出值是0的话说明系统有该软件,进行以下操作
yum install $1 -y &> /dev/null ##安装其软件
}||{
echo $1 is can not find from yumstore ##如果退出值不是0的话进行报错,说明输入的软件名出现了错误
exit 1
}
}
for APP in httpd mariadb-server.x86_64 php php-mysql ##将要安装的软件写进for循环中
do
Install_APP $APP ##执行函数
done
cp -r /tmp/upload /var/www/html ##将upload移至共享目录下
#chmod 777 -R /var/www/html/upload ##更改upload下所有文件的权限为777,不太安全,所以不建议
chmod 777 -R /var/www/html/upload/config ##依次更改安装说明中需要更改的目录的权限,-R表示递归
chmod 777 -R /var/www/html/upload/data
chmod 777 -R /var/www/html/upload/uc*
sed "/^Listen/cListen 8080" /etc/httpd/conf/httpd.conf -i /etc/httpd/conf/httpd.conf ##改变httpd的端口为8080,“^"表示以什么开头
systemctl restart httpd mariadb ##设置完毕后,重新启动httpd服务和mariadb服务
systemctl stop firewalld ##保险起见,可关闭防火墙
setenforce 0 ##设置其selinux状态为Permission
firefox http://172.25.254.166:8080/upload ##打开防火墙,注意要写入8080,因为端口号已经发生了改变
测试,运行脚本后,会发现可以成功安装
[root@shenzhen mnt]# sh lamp.sh
4.数据库备份
执行auto.sh westos(数据库密码)
脚本执行后会备份数据库中的所有库到/mnt/mysqldump目录中
备份文件名称为“库名称.sql”,当此文件存在时报错并询问动作
输入“S”跳出备份,当输入“B”时备份“库名称.sql”文件为“库名称_backup.sql“,当输入”O“时,覆盖源文件
分解讲解:
<1>编写脚本,在脚本中写入其如果没有开启数据库服务,则会出现报错,并进行测试
[root@shenzhen mnt]# vim auto.sh
脚本中的内容如下:
#!/bin/bash
mysql -uroot -p$1 -e "show databases;" &> /dev/null
[ "$?" != 0 ] && {
echo ERROR:connect databases failed
exit 1
}
测试:
没有开启mariabd服务时,会出现脚本中的报错信息
[root@shenzhen mnt]# sh auto.sh westos
开启mariadb服务后,再次执行脚本,没有出现报错
[root@shenzhen mnt]# systemctl start mariadb
[root@shenzhen mnt]# sh auto.sh westos
<2>编写脚本查看是否输入密码,如果输入,则正常进行,如果没有输入,会出现报错
[root@shenzhen mnt]# vim auto.sh
脚本中的内容如下:
#!/bin/bash
[ -z "$1" ] && {
echo please input password for databases
exit 2
}
mysql -uroot -p$1 -e "show databases;" &> /dev/null
[ "$?" != 0 ] && {
echo ERROR:connect databases failed
exit 1
}
没有输入密码时,执行脚本,会出现脚本中的报错信息,查看其退出值,会发现是2,说明没有写密码
[root@shenzhen mnt]# sh auto.sh
[root@shenzhen mnt]# echo $?
输入密码后,不会报错,查看其退出值,会发现是1
[root@shenzhen mnt]# sh auto.sh westos
[root@shenzhen mnt]# echo $?
<3>在脚本中首先查看是否存在/mnt/mysqldump目录,如果有,先删除目录并将重新创建/mnt/mysqldump目录。然后在mysql中写入内容(使用EOF重定向即可)
[root@shenzhen mnt]# vim auto.sh
脚本中的内容如下:
#!/bin/bash
[ -z "$1" ] && {
echo please input password for databases
exit 2
}
mysql -uroot -p$1 -e "show databases;" &> /dev/null
[ "$?" != 0 ] && {
echo ERROR:connect databases failed
exit 1
}
[ ! -d "/mnt/mysqldump" ] && {
rm -rf /mnt/mysqldump
mkdir -p /mnt/mysqldump
}
for DATABASE in `mysql -uroot -p$1 <<EOF | grep -E "Database|schema$" -v
show databases;
EOF`
do
echo $DATABASE
done
运行脚本并输入密码,发现会输出自己想要的数据库
[root@shenzhen mnt]# sh auto.sh westos
查看/mnt下是否有新建的mysqldump目录,并查看其下是否有内容
[root@shenzhen mnt]# ls
[root@shenzhen mnt]# cd mysqldump
[root@shenzhen mysqldump]# ls
<4>编写完整的脚本(添加题目中要求的选项并设置函数方便查使用
[root@shenzhen mnt]# vim auto.sh
脚本中的内容如下:
#!/bin/bash
DB_BACKUP()
{
read -p "Please input action: " ACTION
case $ACTION in
S)
;;
B)
mv /mnt/mysqldump/${DATABASE}.sql /mnt/mysqldump/${DATABASE}_backup.sql
mysqldump -uroot -p$1 $DATABASE > /mnt/mysqldump/${DATABASE}.sql
;;
O)
mysqldump -uroot -p$1 $DATABASE > /mnt/mysqldump/${DATABASE}.sql
;;
*)
echo error action
DB_BACKUP
esac
}
[ -z "$1" ] && {
echo please input password for databases
exit 2
}
mysql -uroot -p$1 -e "show databases;" &> /dev/null
[ "$?" != 0 ] && {
echo ERROR:connect databases failed
exit 1
}
[ ! -d "/mnt/mysqldump" ] && {
rm -rf /mnt/mysqldump
mkdir -p /mnt/mysqldump
}
for DATABASE in `mysql -uroot -p$1 <<EOF | grep -E "Database|schema$" -v
show databases;
EOF`
do
if
[ -e "/mnt/mysqldump/${DATABASE}.sql" ]
then
echo "${DATABASE}.sql is exist and what do you want?
[S]kip [B]ack [O]verwrite"
DB_BACKUP $1
fi
mysqldump -uroot -p$1 $DATABASE > /mnt/mysqldump/${DATABASE}.sql
done
测试:
第一次运行脚本:
[root@shenzhen mnt]# sh auto.sh westos ##运行脚本并输入数据库的密码
[root@shenzhen mnt]# ls ##查看/mnt目录下是否有新生成的mysqldump
[root@shenzhen mnt]# cd mysqldump ##进入mysqldump目录
[root@shenzhen mysqldump]# ls ##查看目录下是否有文件且文件名都加了后缀.sql
第二次运行脚本(即mysqldump中已经存在了.sql文件,所以再次执行脚本时会出现选项):
[root@shenzhen mnt]# sh auto.sh westos
报错:
如果出现以下错误(mysqldump: Got error: 1049: “Unknown database ‘Database’” ),原因是因为书写格式有错误(即可能将 grep -E “Database|schema
” -v)
出现的报错信息:
脚本中的错误写法: