跳转至

企业面试题之shell脚本

1. 批量生成随机字符文件名

使用for循环在/oldboy目录下批量创建10个html文件,其中每个文件需要包含10个随机小写字母加固定字符串oldboy。

思路分析

核心是:创建10个随机小写字母

#7种方法
1.echo $RANDOM
2.openssl rand -base64 100
3.date +%s%N
4.head /dev/urandom|cksum
5.uuidgen
6.cat /proc/sys/kernel/random/uuid
7.mkpasswd(yum install expect -y)
mkpasswd参数
-l  长度
-d  数字
-c  小写字母
-C  大写字母
-s  特殊字符

例1:

mkpasswd -l 20 -d 10 -C 5 -c 3 -s 2
[root@cp ~]# mkpasswd -l 20 -d 10 -C 5 -c 3 -s 2
810Q,hl46#B76C46b1CV

例2:

echo OLDBOY$RANDOM|md5sum|tr "0-9" "a-z"|cut -c 2-11
[root@cp ~]# echo OLDBOY$RANDOM|md5sum|tr "0-9" "a-z"|cut -c 2-11
gicdfhjaag

脚本

#!/bin/bash
path=/oldboy
[ -d $path ] || mkdir $path
for n in {1..10}
do
    random=`echo "OLDBOY$RANDOM"|md5sum|tr "0-9" "m-z"|cut -c 2-11`
    touch $path/${random}_oldboy.html
done

2. 批量改名

将面试题1种的oldboy改为oldgirl(最好用for循环实现),并且将扩展名html改成大写

思路分析

1.要改所有,先缩小改一个
2.修改所有,用for循环
#!/bin/bash
for file in `ls /oldboy/*.html`
do
    mv $file `echo ${file/oldboy.html/oldgirl.HTML}`
done

3. 批量创建特殊要求用户

批量创建10个系统账号oldboy01-10并设置密码(密码要求字符数字等混合)

此题重点:必须要,经常考,要给出2种以上方法

思路分析

1) 01..10产生方法
    echo {01..10}
    seq -w 10
2) 随机数
    openssl rand -base64 100
3) 创建用户
    useradd oldboy01
4) 设置密码
    echo 密码|passwd --stdin
方法2:
    chpasswd oldboy01:passwd

脚本

#!/bin/bash
for n in {01..10}
do
    pass=`openssl rand -base64 10`
    useradd oldboy$n
    echo $pass|passwd --stdin oldboy$n
    echo -e "oldboy$n\t$pass" >>/tmp/user.list
done

方法2

#!/bin/bash
for n in `seq -w 1 10`
do
    pass=`openssl rand -base64 10`
    useradd oldboy$n
    echo "oldboy$n:$pass" >> /tmp/chpasswd.log
done
chpasswd < /tmp/chpasswd.log

改进:加上root用户验证

#!/bin/bash
. /etc/init.d/functions

if [ $UID -ne 0 ];then
    echo "必须使用root用户执行本脚本!!!"
    exit 1
fi

for n in {20..30}
do
    pass=`openssl rand -base64 10`
    if [ `grep -w "oldboy$n" /etc/passwd|wc -l` -eq 0 ];then
        useradd oldboy$n &>/dev/null
        echo $pass|passwd --stdin oldboy$n &>/dev/null && \
        echo -e "oldboy$n\t$pass" >>/tmp/user.list && \
        action "oldboy$n is ok." /bin/true
    else
        action "oldboy$n is fail." /bin/false
    fi
done

3.1 批量创建10个用户stu01-stu10,设置随机8为密码,要求只能用linux命令及管道实现,不能用循环

方法1:(以下方法都未验证。。。)

echo stu{01..10}|tr " " "\n" |sed -r 's#(.*)#useradd \1;
pass=$((RANDOM+10000000));echo "$pass|passwd --stdin \1;echo -e "\1\t`echo "$pass"`">>/tmp/lodboy.log#g'|bash

拆解如下

useradd stu01;
pass=$((RANDOM+10000000));
echo "$pass"|passwd --stdin stu01;
echo -e "stu01 `echo "$pass"`">>/tmp/oldboy.log

方法2

echo stu{11..12}|xargs -n1 useradd;echo stu{11..12}:`cat /dev/urandom|tr -dc 0-9|fold -w8|head -1`|xargs -n1 |tee -a pass.txt|chpasswd

方法3

echo stu{21..30}|tr "" "\n"|sed -e 's/^/useradd /' -e 's/\(stu[0-9]\{2\}\)$/\1 \&\& echo "\1:`echo $[$RANDOM**3]|cut -c1-8`"|tee -a userinfo.txt|cut -d: -f2|passwd --stdin \1/' |bash

方法4

echo stu{01..10}|tr ' ' '\n'|sed -rn 's@^(.*)$@useradd\1;echo $RANDOM |md5sum|cut -c 1-8 >/data/\1;cut /data/\1|passwd --stdin \1@gp'|bash

4. 扫描网络内的存活主机

写一个脚本,判断10.0.0.0/24网络里,当前在线的IP有哪些

思路分析

1.如何判断主机存活
ping -c 2 -i 1 -w 3 10.0.0.7
nmap -sP 10.0.0.0/24
root@4c16g:/shell-scripts# nmap -sP 10.0.8.0
Starting Nmap 7.80 ( https://nmap.org ) at 2022-01-05 15:39 CST
Note: Host seems down. If it is really up, but blocking our ping probes, try -Pn
Nmap done: 1 IP address (0 hosts up) scanned in 3.10 seconds
root@4c16g:/shell-scripts# nmap -sP 10.0.8.1
Starting Nmap 7.80 ( https://nmap.org ) at 2022-01-05 15:39 CST
Nmap scan report for 10.0.8.1
Host is up (0.012s latency).
Nmap done: 1 IP address (1 host up) scanned in 0.15 seconds

脚本

for n in {1..254}
do
    if `ping -c 1 -w 3 10.0.0.$n &>/dev/null`
    then
        echo "10.0.0.$n is up."
    else
        echo "10.0.0.$n is down."
    fi
done

以上速度比较慢,可以批量ping,提高速度

for n in {1..254}
do
    {
        if `ping -c 1 -w 3 10.0.0.$n &>/dev/null`
        then
            echo "10.0.0.$n is up."
        else
            ehco "10.0.0.$n is down."
        fi
    } &
done

5. mysql数据库分库备份

思路分析:

常规方法
mysqldump -B oldboy oldgirl test | gzip >bak.sql.gz
分库备份
mysqldump -B oldboy | gzip >bak.sql.gz
mysqldump -B oldgirl | gzip >bak.sql.gz
mysqldump -B test | gzip >bak.sql.gz

脚本

#!/bin/bash
[ -d /backup ] || mkdir /backup -p

for dname in `mysql -uroot -p123456 -e "show databases;" 2>/dev/null |grep -v _schema|sed 1d`
do
    mysqldump -uroot -p123456 -B $dbname|gzip >/backup/${dbname}.sql.gz
done

优化

#!/bin/bash
mysql="mysql -uroot -p123456"
mysqldump="mysqldump -uroot -p123456"
path="/backup"
[ -d $path ] ||mkdir $path -p
for dbname in `$mysql -e "show databases;" 2>/dev/null|grep -v _schema|sed 1d`
do
    $mysqldump -B $dbname|gzip >$path/${dbname}_$(date +%F).sql.gz
done

6. mysql数据库分库分表备份

思路分析

mysqldump oldboy test test1 |gzip >bak.sql.gz
1.oldboy 数据库名
2.test、test1 表名

方法2

mysqldump -B oldboy |gzip >bak.sql.gz
mysqldump oldboy test1
mysqldump oldboy test2
mysqldump oldboy test3

脚本

#!/bin/bash
path=/backup
mysql="mysql -uroot -p123456"
mysqldump="mysqldump -uroot -p123456"
[ -d $path ] || mkdir $path -p
for dbname in `$mysql -e "show databases;" 2>/dev/null |grep -v _schema|sed 1d`
do
    for tname in `$mysql -e "show tables from $dbname;" 2>/dev/nulll |sed 1d`
    do
        $mysqldump $dbname $tname |gzip >$path/${dbname}_${tname}.sql.gz 2>/dev/null
    done
done

也可以修改配置文件,加入如下参数,防止在脚本中加入密码

vim /etc/my.cnf

[client]
user=root
password=123456

则,脚本中可以省略密码

#!/bin/bash
path=/backup
[ -d $path ] || mkdir $path -p

for dbname in `mysql -e "show databases;" 2>/dev/null |grep -v _schema|sed 1d`
do
    for tname in `mysql -e "show tables from $dbname;" 2>/dev/nulll |sed 1d`
    do
        mysqldump $dbname $tname |gzip >$path/${dbname}_${tname}.sql.gz 2>/dev/null
    done
done

改造,跳过报错数据库

#!/bin/bash
path=/backup
[ -d $path ] || mkdir $path -p

for dbname in `mysql -e "show databases;" 2>/dev/null |grep -v _schema|sed 1d`
do      
    for tname in `mysql -e "show tables from $dbname;" 2>/dev/nulll |sed 1d`
    do
        if [ "$dbname" = "mysql" ];then
            mysqldump --skip-lock-tables $dbname $tname |gzip >$path/${dbname}_${tname}.sql.gz 2>/dev/null
        else
            mysqldump $dbname $tname |gzip >$path/${dbname}_${tname}.sql.gz 2>/dev/null
        fi
    done
done

7. ssh免密钥批量分发文件专业脚本

有3台机器(m01,backup,nfs01),采用ssh免密钥实现从m01到其他两台机器无密码登录后,请写脚本实现从m01批量分发任意文件到其他两台机器的任意目录下

思路分析

1.生成密钥
ssh-keygen

2.分发密钥
ssh-copy-id -i id_rsa.pub 10.0.0.8
ssh-copy-id -i id_rsa.pub 10.0.0.41

3.测试
ssh 10.0.0.8  free -m
ssh 10.0.0.41 free -m

测试脚本

vim ssh_test.sh
#!/bin/bash
if [ $# -ne 1 ];then
    echo "usage: $0 cmd"
    exit 1
fi

for n in 8 41
do
    echo "-----------10.0.0.$n--------------"
    ssh 10.0.0.$n $1
done
bash ssh_test.sh "df -h"

分发文件脚本

#!/bin/bash
for n in 8 41
do
    echo "-----------10.0.0.$n---------"
    scp -rp /oldboy 10.0.0.$n:/opt
done

改造

#!/bin/bash
if [ $# -ne 2 ];then
    echo "usage:$0 localdir remotedir"
    exit 1
fi

for n in 8 41
do
    echo "-----10.0.0.$n--------"
    scp -rp $1 10.0.0.$n:$2
done

优化

#!/bin/bash
. /etc/init.d/functions
if [ $# -ne 2 ];then
    echo "usage:$0 localdir remotedir"
    exit 1
fi

for n in 8 41 42 43
do
    scp -rp $1 10.0.0.$n:$2 &>/dev/null
    if [ $? -eq 0 ];then
        action "10.0.0.$n is ok" /bin/true
    else
        action "10.0.0.$n is fail" /bin/false
    fi
done

8. 破解random随机数

已知下面的字符串,请破解对应的使用MD5sum处理前的数字

21029299

00205d1c

a3da1677

1f6d12dd

890684b

思路分析

grep "1f6d12dd" md5.log |wc -l 

脚本

array=(
21029299
00205d1c
a3da1677
1f6d12dd
890684b
)

Funmd5(){
    for n in {0..32767}
    do
        echo -e "$n\t`echo $n|md5sum`" >>/tmp/md5sum.log 
    done
}

FunJudge(){
    for n in ${array[*]}
        do
            find=`grep $n /tmp/md5sum.log`
            if [ `echo $find|wc -l` -eq 1 ];then
                echo $find
            fi
        done
}

main(){
    Funmd5
    FunJudge
}
main    

方法2

array=(
21029299
00205d1c
a3da1677
1f6d12dd
890684b
)

Funmd5(){
    for n in {0..32767}
    do
        echo -e "$n\t`echo $n|md5sum`" >>/tmp/md5sum.log &
    done
}

FunJudge(){
    char=`echo ${array[*]} |tr " " "|"`
    egrep "$char" /tmp/md5sum1.log
}

main(){
    Funmd5
    FunJudge
}
main    

9. 批量检查多个网站地址是否正确

要求:

1.使用shell数组方法实现,检测策略尽量模拟用户访问

2.每10秒做一次所有的检测,无法访问的输出报警

3.待检测网址如下

http://blog.oldboyedu.com

http://blog.etiantian.org

http://www.luffycity.com

http://10.0.0.7

#!/bin/bash
. /etc/init.d/functions
URL=(
http://blog.oldboyedu.com
http://blog.etiantian.org
http://www.luffycity.com
http://10.0.0.7
)

CheckUrl(){
    wget -t 2 -T 5 -o /dev/null -q $1
    if [ $? -eq 0 ];then
        action "$1 is ok" /bin/true
    lese
        action "$1 is fail" /bin/false
    fi
}

DealUrl(){
    for((i=0;i<${#URL[*]};i++))
    do
        CheckUrl ${URL[i]}
    done
}

main(){
    while true
    do
        DealUrl
        sleep 10
        echo "--------------------------------"
    done
}
main

方法2

vim url.log
http://blog.oldboyedu.com
http://blog.etiantian.org
http://www.luffycity.com
http://10.0.0.7
#!/bin/bash
. /etc/init.d/functions

CheckUrl(){
    wget -t 2 -T 5 -o /dev/null -q $1
    if [ $? -eq 0 ];then
        action "$1 is ok" /bin/true
    lese
        action "$1 is fail" /bin/false
    fi
}

DealUrl(){
    while read line
    do
        CheckUrl $line
    done <./url.log
}

main(){
    while true
    do
        DealUrl
        sleep 10
        echo "--------------------------------"
    done
}
main

10. 解决DOS攻击

请根据web日志或者网络连接数,监控当某个IP并发链接数或者短时间内PV达到100,即调用防火墙命令封掉对应的IP。

防火墙命令为:iptables -I INPUT -s IP -j DROP

思路分析

1.封IP命令
iptables -I INPUT -s IP -j DROP

2.web日志活网络链接数
netstat -an|grep -i est

3.判断pv或者链接数大于100,取出IP封掉

脚本

#!/bin/bash
awk '{S[$1]++}END{for(key in S) print S[key],key}' access.log |sort -rn |head >/tmp/ip.log
while read line
do
    if [ `echo $line |awk '{print $1}'` -gt 100 ];then
        iptables -I INPUT -s `echo $line|awk '{print $2}'` -j DROP && \
        echo "echo $line |awk '{print $2}'" >>/tmp/drop.log
    else
        echo "echo $line|awk '{print $2}'" >>/tmp/accept.log
    fi
done </tmp/ip.log

改造

#!/bin/bash
awk '{S[$1]++}END{for(key in S) print S[key],key}' access.log |sort -rn |head >/tmp/ip.log
while read line
do
    ip=`echo $line |awk '{print $2}'`
    count=`echo $line |awk '{print $1}'`
    if [ $count -gt 35 -a `grep "$ip" /tmp/drop.log|wc -l` -lt 1 ];then
        iptables -I INPUT -s $ip -j DROP && \
        echo "$ip" >>/tmp/drop.log
    else
        echo "$ip" >>/tmp/accept.log
    fi
done </tmp/ip.log

方法2

#!/bin/bash
awk '/ESTAB/{print $0}' netstat.log |awk -F "[ :]+" '{print $(NF-3)}' |sort |uniq -c |sort -rn |head >/tmp/ip.log
while read line
do
    ip=`echo $line|awk '{print $2}'`
    count=`echo $line|awk '{print $1}'`
    if [ $count -gt 100 -a `grep "$ip" /tmp/drop.log |wc -l` -lt 1 ];then
        iptables -I INPUT -s $ip -j DROP
        echo $ip >>/tmp/drop.log
    else
        echo $ip >>/tmp/accept.log
    fi
done</tmp/ip.log

11.开发MySQL服务启停脚本(与rsync启停脚本类似)

lsof -i :3306

思路分析

1.实现效果
/et/init.d/mysqld {start|stop|restart}
2.启动
mysqld_safe --user=mysql &
3.停止
killall,pkill
kill pid

脚本

#!/bin/bash
lockfile=/var/lock/subsys/mysqld
. /etc/init.d/functions
mysqld_pid_file_path="/appliacation/mysql/data/`uname -n`.pid"
mysqld_safe=/application/mysql/bin/mysqld_safe

start(){
    /bin/sh $mysqld_safe --datadir=/application/mysql/data --pid-file=$mysqld_pid_file_path &>/dev/null &
    retval=$?
    if [ $retval -eq 0 ];then
        action "mysql startup ok" /bin/true
        touch $lockfile
        return $retval
    else
        action "mysql startup fail" /bin/false
        return $retval
    fi
}

stop(){
    if test -s "$mysqld_pid_file_path"
    then
        mysqld_pid=`cat $mysqld_pid_file_path`
        if (kill -0 $mysqld_pid &>/dev/null)
        then
            kill $mysqld_pid
            retval=$?
            if [ $retval -eq 0 ];then
                action "mysql stop ok" /bin/true
                rm $lockfile
                return $retval
            else
                action "mysql stop fail" /bin/false
                return $retval
            fi
        else
            echo "mysqld process is not exist."
            return 2
        fi
    else
        echo "$mysqld_pid_file_path is not exist,or mysqld does not startup."
    fi
}

case "$1" in
    start)
        start
        retval=$?
        ;;
    stop)
        stop
        retval=$?
        ;;
    restart)
        stop
        sleep2
        start
        retval=$?
        ;;
    *)
        echo "usage: $0 {start|stop|restart}"
        exit 1
esac
exit $retval

12. 单词及字母去重排序(排序去重面试非常常见!!!)

1.按单词出现频率降序排序

2.按字母出现频率降序排序

the squid project provides a number of resources to assist users design,implement and support squid installations. Please browse the documentation and support sections for more infomation,by oldboy training.

思路分析

1.tr " ," "\n" <12.log |sort |uniq -c |sort -rn
2.tr " ," "\n" <12.log |awk '{S[$1]++}END{for(k in S) print S[k],k}'|sort -rn
3.xargs -n1 <12.log
[root@k8s-master tmp]# tr " ," "\n" <12.log |sort |uniq -c |sort -rn                         2 the
      2 support
      2 squid
      2 and
      1 users
      1 training.
      1 to
      1 sections
      1 resources
      1 provides
      1 project
      1 Please
      1 oldboy
      1 of
      1 number
      1 more
      1 installations.
      1 infomation
      1 implement
      1 for
      1 documentation
      1 design
      1 by
      1 browse
      1 assist
      1 a
[root@k8s-master tmp]# tr " ," "\n" <12.log |awk '{S[$1]++}END{for(k in S) print S[k],k}'|sort -rn
2 the
2 support
2 squid
2 and
1 users
1 training.
1 to
1 sections
1 resources
1 provides
1 project
1 Please
1 oldboy
1 of
1 number
1 more
1 installations.
1 infomation
1 implement
1 for
1 documentation
1 design
1 by
1 browse
1 assist
1 a
[root@k8s-master tmp]# xargs -n1 <12.log|sort|uniq -c |sort -rn
      2 the
      2 support
      2 squid
      2 and
      1 users
      1 training.
      1 to
      1 sections
      1 resources
      1 provides
      1 project
      1 Please
      1 oldboy
      1 of
      1 number
      1 more
      1 installations.
      1 infomation,by
      1 for
      1 documentation
      1 design,implement
      1 browse
      1 assist
      1 a
sed 's# ##g' 12.log
[root@k8s-master tmp]# sed 's# ##g' 12.log
thesquidprojectprovidesanumberofresourcestoassistusersdesign,implementandsupportsquidinstallations.Pleasebrowsethedocumentationandsupportsectionsformoreinfomation,byoldboytraining.
grep -o "." 12.log|sort|uniq -c |sort -rn
[root@k8s-master tmp]# grep -o "." 12.log|sort|uniq -c |sort -rn
     27
     19 s
     18 o
     17 e
     15 t
     14 n
     14 i
     12 r
     10 a
      8 u
      8 d
      7 p
      6 m
      5 l
      4 c
      4 b
      3 f
      2 y
      2 q
      2 h
      2 g
      2 .
      2 ,
      1 w
      1 v
      1 P
      1 j
grep -o "[^ ]" 12.log |sort | uniq -c |sort -rn
[root@k8s-master tmp]# grep -o "[^ ]" 12.log |sort | uniq -c |sort -rn
     19 s
     18 o
     17 e
     15 t
     14 n
     14 i
     12 r
     10 a
      8 u
      8 d
      7 p
      6 m
      5 l
      4 c
      4 b
      3 f
      2 y
      2 q
      2 h
      2 g
      2 .
      2 ,
      1 w
      1 v
      1 P
      1 j
grep -o "[^ ]" 12.log|awk '{S[$1]++}END{for(k in S) print S[k],k}'|sort -rn
[root@k8s-master tmp]# grep -o "[^ ]" 12.log|awk '{S[$1]++}END{for(k in S) print S[k],k}'|sort -rn
19 s
18 o
17 e
15 t
14 n
14 i
12 r
10 a
8 u
8 d
7 p
6 m
5 l
4 c
4 b
3 f
2 y
2 q
2 h
2 g
2 .
2 ,
1 w
1 v
1 P
1 j

最后更新: 2022-02-19 13:59:07