shell4(批量修改文件名、Expect、网段ip测试)
1、从FTP服务器下载文件
#!/bin/bash
if [ $# -ne 1 ]; then
echo "Usage: $0 filename"
fi
dir=$(dirname $1)
file=$(basename $1)
ftp -n -v << EOF # -n 自动登录
open 192.168.1.10 # ftp服务器
user admin password
binary # 设置ftp传输模式为二进制,避免MD5值不同或.tar.gz压缩包格式错误
cd $dir
get "$file"
EOF
2、将结果分别赋值给变量
应用场景:希望将执行结果或者位置参数赋值给变量,以便后续使用。
方法1:
for i in $(echo "4 5 6"); do eval a$i=$i done echo $a4 $a5 $a6
方法2:将位置参数192.168.1.1{1,2}拆分为到每个变量
num=0 for i in $(eval echo $*);do #eval将{1,2}分解为1 2 let num+=1 eval node${num}="$i" done echo $node1 $node2 $node3 # bash a.sh 192.168.1.1{1,2} 192.168.1.11 192.168.1.12
方法3:
arr=(4 5 6)
INDEX1=$(echo ${arr[0]}) INDEX2=$(echo ${arr[1]}) INDEX3=$(echo ${arr[2]})
3、批量修改文件名
# touch article_{1..3}.html # ls article_1.html article_2.html article_3.html 目的:把article改为bbs
方法1:
for file in $(ls *html); do mv $file bbs_${file#*_} # mv $file $(echo $file |sed -r 's/.*(_.*)/bbs\1/') # mv $file $(echo $file |echo bbs_$(cut -d_ -f2) done
方法2:
for file in $(find . -maxdepth 1 -name "*html"); do mv $file bbs_${file#*_} done
方法3:
# rename article bbs *.html
4、统计当前目录中以.html结尾的文件总大
方法1:
# find . -name "*.html" -exec du -k {} \; |awk '{sum+=$1}END{print sum}'
方法2:
for size in $(ls -l *.html |awk '{print $5}'); do sum=$(($sum+$size)) done echo $sum
5、Expect实现SSH免交互执行命令
Expect是一个自动交互式应用程序的工具,如telnet,ftp,passwd等,需先安装expect软件包。
方法1:EOF标准输出作为expect标准输入
#!/bin/bash USER=root PASS=123.com IP=192.168.1.120 expect << EOF set timeout 30 spawn ssh $USER@$IP expect { "(yes/no)" {send "yes\r"; exp_continue} "password:" {send "$PASS\r"} } expect "$USER@*" {send "$1\r"} expect "$USER@*" {send "exit\r"} expect eof EOF
方法2:
#!/bin/bash USER=root PASS=123.com IP=192.168.1.120 expect -c " spawn ssh $USER@$IP expect { \"(yes/no)\" {send \"yes\r\"; exp_continue} \"password:\" {send \"$PASS\r\"; exp_continue} \"$USER@*\" {send \"df -h\r exit\r\"; exp_continue} }"
方法3:将expect脚本独立出来
登录脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | #!/bin/bash password = xxxxxx # 安装 expect 自动捕获工具 yum - y install expect 1 > / dev / null 2 >& 1 # 自动生成密钥 key_generate() { expect - c " set timeout - 1 ; spawn ssh - keygen - t ed25519; expect { {Enter file in which to save the key * } {send - - \r;exp_continue} {Enter passphrase * } {send - - \r;exp_continue} {Enter same passphrase again:} {send - - \r;exp_continue} {Overwrite (y / n) * } {send - - n\r;exp_continue} eof {exit 0 ;} };" ssh - add } # 将密钥发送至需要免密登录的服务器 auto_ssh_copy_id () { expect - c " set timeout - 1 ; spawn ssh - copy - id - o StrictHostKeyChecking = no - o UserKnownHostsFile = / dev / null $ 1 ; expect { { * password:} {send - - $ 2 \r; exp_continue;} eof {exit 0 ;} };" } key_generate #echo > /root/.ssh/known_hosts # 根据 /etc/hosts 文件中的 IP 地址和预定的密码设置免密登录 ips = $(cat / etc / hosts | grep - v "::" | grep - v "127.0.0.1" | cut - f 1 ) for ip in $ips do auto_ssh_copy_id $ip $password done |
补充:Ed25519
-
Ed25519 算法:
- 安全性:Ed25519 是一种基于椭圆曲线密码学(Elliptic Curve Cryptography, ECC)的密钥生成算法,提供高效的加密安全性。与传统的 RSA 算法相比,在相同的安全级别下,Ed25519 的密钥长度更短。
- 性能:生成和验证 Ed25519 密钥比传统算法(如 RSA 或 DSA)更快,特别是在低功耗设备上表现更佳。
-
生成过程:
- 当你运行
ssh-keygen -t ed25519
时,程序会提示你输入文件名以保存密钥。如果你直接按 Enter,它会将密钥保存在默认位置(通常是~/.ssh/id_ed25519
)。 - 接着,系统会询问你输入一个密码短语(passphrase),用于进一步保护私钥。你可以选择留空,但建议设置一个密码来增强安全性。
- 当你运行
-
生成的文件:
- 生成后,会得到两个文件:
~/.ssh/id_ed25519
—— 私钥。~/.ssh/id_ed25519.pub
—— 公钥。可以安全地分享给其他人,或将其添加到 SSH 服务器的~/.ssh/authorized_keys
文件中,以实现无密码 SSH 登录。
- 生成后,会得到两个文件:
8、批量修改服务器用户密码
Linux主机SSH连接信息:旧密码 # cat old_pass.txt 192.168.18.217 root 123456 22 192.168.18.218 root 123456 22 内容格式:IP User Password Port SSH远程修改密码脚本:新密码随机生成 #!/bin/bash OLD_INFO=old_pass.txt NEW_INFO=new_pass.txt for IP in $(awk '/^[^#]/{print $1}' $OLD_INFO); do USER=$(awk -v I=$IP 'I==$1{print $2}' $OLD_INFO) PASS=$(awk -v I=$IP 'I==$1{print $3}' $OLD_INFO) PORT=$(awk -v I=$IP 'I==$1{print $4}' $OLD_INFO) NEW_PASS=$(mkpasswd -l 8) # 随机密码 echo "$IP $USER $NEW_PASS $PORT" >> $NEW_INFO expect -c " spawn ssh -p$PORT $USER@$IP set timeout 2 expect { \"(yes/no)\" {send \"yes\r\";exp_continue} \"password:\" {send \"$PASS\r\";exp_continue} \"$USER@*\" {send \"echo \'$NEW_PASS\' |passwd --stdin $USER\r exit\r\";exp_continue} }" done 生成新密码文件: # cat new_pass.txt 192.168.18.217 root n8wX3mU% 22 192.168.18.218 root c87;ZnnL 22
9、getopts工具完善脚本命令行参数
getopts是一个解析脚本选项参数的工具。
命令格式:getopts optstring name [arg]
初次使用你要注意这几点:
脚本位置参数会与optstring中的单个字母逐个匹配,如果匹配到就赋值给name,否则赋值name为问号;
optstring中单个字母是一个选项,如果字母后面加冒号,表示该选项后面带参数,参数值并会赋值给OPTARG变量;
optstring中第一个是冒号,表示屏蔽系统错误(test.sh: illegal option -- h);
允许把选项放一起,例如-ab
下面写一个打印文件指定行的简单例子,引导你思路:
#!/bin/bash while getopts :f:n: option; do case $option in f) FILE=$OPTARG [ ! -f $FILE ] && echo "$FILE File not exist!" && exit ;;
n) sed -n "${OPTARG}p" $FILE ;; ?) echo "Usage: $0 -f -n " echo "-f, --file specified file" echo "-n, --line-number print specified line" exit 1 ;; esac done
10、测试 192.168.4.0/24 整个网段主机的开关机状态
多进程版
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #!/bin/bash # 编写脚本测试 192.168.4.0/24 整个网段中哪些主机处于开机状态,哪些主机处于关机 # 状态(多进程版) #定义一个函数,ping 某一台主机,并检测主机的存活状态 myping(){ ping ‐c 2 ‐i 0.3 ‐W 1 $1 &>/dev/null if [ $? -eq 0 ];then echo "$1 is up" else echo "$1 is down" fi } for i in {1..254} do myping 192.168.4.$i & done # 使用&符号,将执行的函数放入后台执行 # 这样做的好处是不需要等待ping第一台主机的回应,就可以继续并发ping第二台主机,依次类推 |
在线和离线主机输出到文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | #!/bin/bash ping_success_status() { if ping -c 1 $IP >> /dev/ null ; then echo "$IP is on" >> /root/success-host.txt continue fi } success=/root/success-host.txt failure=/root/failure-host.txt rm -rf $success rm -rf $failure if [[ ! -f $success ]];then touch /root/success-host.txt && chmod 777 /root/success-host.txt echo "$success 文件创建成功" else echo "$success 文件已经存在" fi if [[ ! -f $failure ]];then touch /root/failure-host.txt && chmod 777 /root/failure-host.txt echo "$failure 文件创建成功" else echo "$failure 文件已经存在" fi for IP in `echo 10.1.1.{1..254}` do { ping_success_status echo "$IP is off!" >> /root/failure-host.txt } & done wait echo "在线主机数如下:" && cat /root/success-host.txt | wc -l #cat /root/success-host.txt echo "离线主机数如下:" && cat /root/failure-host.txt | wc -l #cat /root/failure-host.txt |
while版
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #!/bin/bash # 编写脚本测试 192.168.4.0/24 整个网段中哪些主机处于开机状态,哪些主机处于关机 # 状态(while 版本) i=1 while [ $i -le 254 ] do ping ‐c 2 ‐i 0.3 ‐W 1 192.168.4.$i &>/dev/null if [ $? -eq 0 ];then echo "192.168.4.$i is up" else echo "192.168.4.$i is down" fi let i++ done |