shell 第几行_100个非常实用的Shell拿来就用脚本实例(超详细超全)二

02a456d92f58584f1fa602df9be7ae42.png

shell脚本是帮助程序员和系统管理员完成费时费力的枯燥工作的利器,是与计算机交互并管理文件和系统操作的有效方式。区区几行代码,就可以让计算机接近按照你的意图行事。
博智互联为大家整理了100个实例,通过100个实战经典脚本实例,展示了shell脚本编程的实用技术和常见工具用法。大家只需根据自己的需求,将文中这些常见任务和可移植自动化脚本推广应用到其他类似问题上,能解决那些三天两头碰上的麻烦事。

判断用户输入的是否为数字

方法1:#!/bin/bashif [[ $1 =~ ^[0-9]+$ ]]; then    echo "Is Number."else    echo "No Number."fi方法2:#!/bin/bashif [ $1 -gt 0 ] 2>/dev/null; then    echo "Is Number."else    echo "No Number."fi方法3:#!/bin/bashecho $1 |awk '{print $0~/^[0-9]+$/?"Is Number.":"No Number."}'  #三目运算符12.14 找出包含关键字的文件DIR=$1KEY=$2for FILE in $(find $DIR -type f); do    if grep $KEY $FILE &>/dev/null; then        echo "--> $FILE"    fidone

监控目录,将新创建的文件名追加到日志中

场景:记录目录下文件操作。需先安装inotify-tools软件包。#!/bin/bashMON_DIR=/optinotifywait -mq --format %f -e create $MON_DIR |while read files; do  echo $files >> test.logdone

给用户提供多个网卡选择

场景:服务器多个网卡时,获取指定网卡,例如网卡流量#!/bin/bashfunction local_nic() {    local NUM ARRAY_LENGTH    NUM=0    for NIC_NAME in $(ls /sys/class/net|grep -vE "lo|docker0"); do        NIC_IP=$(ifconfig $NIC_NAME |awk -F'[: ]+' '/inet addr/{print $4}')        if [ -n "$NIC_IP" ]; then            NIC_IP_ARRAY[$NUM]="$NIC_NAME:$NIC_IP"    #将网卡名和对应IP放到数组            let NUM++        fi    done    ARRAY_LENGTH=${#NIC_IP_ARRAY[*]}    if [ $ARRAY_LENGTH -eq 1 ]; then     #如果数组里面只有一条记录说明就一个网卡        NIC=${NIC_IP_ARRAY[0]%:*}        return 0    elif [ $ARRAY_LENGTH -eq 0 ]; then   #如果没有记录说明没有网卡        echo "No available network card!"        exit 1    else        #如果有多条记录则提醒输入选择        for NIC in ${NIC_IP_ARRAY[*]}; do            echo $NIC        done        while true; do            read -p "Please enter local use to network card name: " INPUT_NIC_NAME            COUNT=0            for NIC in ${NIC_IP_ARRAY[*]}; do                NIC_NAME=${NIC%:*}                if [ $NIC_NAME == "$INPUT_NIC_NAME" ]; then                    NIC=${NIC_IP_ARRAY[$COUNT]%:*}                    return 0                else                   COUNT+=1                fi            done            echo "Not match! Please input again."        done    fi}local_nic

MySQL数据库备份

#!/bin/bashDATE=$(date +%F_%H-%M-%S)HOST=192.168.1.120DB=testUSER=bakPASS=123456MAIL="zhangsan@example.com lisi@example.com"BACKUP_DIR=/data/db_backupSQL_FILE=${DB}_full_$DATE.sqlBAK_FILE=${DB}_full_$DATE.zipcd $BACKUP_DIRif mysqldump -h$HOST -u$USER -p$PASS --single-transaction --routines --triggers -B $DB > $SQL_FILE; then    zip $BAK_FILE $SQL_FILE && rm -f $SQL_FILE    if [ ! -s $BAK_FILE ]; then            echo "$DATE 内容" | mail -s "主题" $MAIL    fielse    echo "$DATE 内容" | mail -s "主题" $MAILfifind $BACKUP_DIR -name '*.zip' -ctime +14 -exec rm {} ;

Nginx服务管理脚本

场景:使用源码包安装Nginx不含带服务管理脚本,也就是不能使用"service nginx start"或"/etc/init.d/nginx start",所以写了以下的服务管理脚本。#!/bin/bash# Description: Only support RedHat system. /etc/init.d/functionsWORD_DIR=/usr/local/nginxDAEMON=$WORD_DIR/sbin/nginxCONF=$WORD_DIR/conf/nginx.confNAME=nginxPID=$(awk -F'[; ]+' '/^[^#]/{if($0~/pid;/)print $2}' $CONF)if [ -z "$PID" ]; then    PID=$WORD_DIR/logs/nginx.pidelse    PID=$WORD_DIR/$PIDfistop() {    $DAEMON -s stop    sleep 1    [ ! -f $PID ] && action "* Stopping $NAME"  /bin/true || action "* Stopping $NAME" /bin/false}start() {    $DAEMON    sleep 1    [ -f $PID ] && action "* Starting $NAME"  /bin/true || action "* Starting $NAME" /bin/false}reload() {    $DAEMON -s reload}test_config() {    $DAEMON -t}case "$1" in    start)        if [ ! -f $PID ]; then            start        else            echo "$NAME is running..."            exit 0        fi        ;;    stop)        if [ -f $PID ]; then            stop        else            echo "$NAME not running!"            exit 0        fi        ;;    restart)        if [ ! -f $PID ]; then            echo "$NAME not running!"             start        else            stop            start        fi        ;;    reload)        reload        ;;    testconfig)        test_config        ;;    status)        [ -f $PID ] && echo "$NAME is running..." || echo "$NAME not running!"        ;;    *)        echo "Usage: $0 {start|stop|restart|reload|testconfig|status}"        exit 3        ;;esac

用户根据菜单选择要连接的Linux主机

Linux主机SSH连接信息:# cat host.txtWeb 192.168.1.10 root 22DB 192.168.1.11 root 22内容格式:主机名 IP User Port#!/bin/bashPS3="Please input number: "HOST_FILE=host.txtwhile true; do    select NAME in $(awk '{print $1}' $HOST_FILE) quit; do        [ ${NAME:=empty} == "quit" ] && exit 0        IP=$(awk -v NAME=${NAME} '$1==NAME{print $2}' $HOST_FILE)        USER=$(awk -v NAME=${NAME} '$1==NAME{print $3}' $HOST_FILE)        PORT=$(awk -v NAME=${NAME} '$1==NAME{print $4}' $HOST_FILE)        if [ $IP ]; then            echo "Name: $NAME, IP: $IP"            ssh -o StrictHostKeyChecking=no -p $PORT -i id_rsa $USER@$IP  # 密钥免交互登录            break        else            echo "Input error, Please enter again!"            break        fi    donedone

将结果分别赋值给变量

应用场景:希望将执行结果或者位置参数赋值给变量,以便后续使用。方法1:for i in $(echo "4 5 6"); do   eval a$i=$idoneecho $a4 $a5 $a6方法2:将位置参数192.168.1.1{1,2}拆分为到每个变量num=0for i in $(eval echo $*);do   #eval将{1,2}分解为1 2   let num+=1   eval node${num}="$i"doneecho $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]})

读取list.txt文件中的账号密码批量创建用户

#!/bin/bash#提前准备账号密码文件list.txt#文件内每行一个账号密码组,使用逗号分隔(username,password)for line in `cat list.txt`do  echo $line | awk -F, '{cmd="useradd "$1"; echo "$2" | passwd --stdin "$1; system(cmd)}'   #awk中调用系统命令done

显示当前计算机中所有账户的用户名

#!/bin/bashecho "方法①,指定以:为分隔符,打印/etc/passwd文件的第1列"awk -F: '{print $1}' /etc/passwdecho "方法②,指定以:为分隔符,打印/etc/passwd文件的第1列"cut -d: -f1 /etc/passwdecho "方法③使用sed的替换功能,将/etc/passwd文件中第1个:后面的所有内容替换为空(仅显示用户名)"sed "s/:.*//" /etc/passwd

统计当前Linux系统中可以登陆计算机的账户数量

#!/bin/bash#方法1grep:grep "bash$" /etc/passwd | wc -l         #一般默认解释器是bash#方法2awk:awk -F: '/bash$/{x++} END{print x}' /etc/passwd#方法3,更为准确for shell in `awk -F: '{print $7}' /etc/passwd`         #取出账号文件中各账号的解释器do    if [[ "`cat /etc/shells`" =~ "$shell" ]]; then      #检测取出的解释器是否包含在可登录解释器中        let n++    fidoneecho $n

找出/etc/passwd中能登录的用户,并将对应在/etc/shadow中第二列密码提出处理

#!/bin/bashshells=`awk -F: '$7!~"nologin"{print $1","$7}' /etc/passwd`for shell in $shellsdo    if [[ "`grep -v '^#' /etc/shells`" =~ "`echo $shell | cut -d, -f2`" ]]; then        users="$users `echo $shell | cut -d, -f1`"    fidonefor user in $usersdo    awk -F: -v u=$user '$1~u{print $1,$2}' /etc/shadowdone

自动修改计划任务配置文件

#!/bin/bashread -p "请输入分钟信息(00-59):" minread -p "请输入小时信息(00-24):" hourread -p "请输入日期信息(01-31):" dateread -p "请输入月份信息(01-12):" monthread -p "请输入周几信息(00-06):" weakread -p "请输入计划任务需要执行的命令或脚本:" programecho "$min $hour $date $month $weak $USER $program" >> /etc/crontab

实时监视本机内存、/分区剩余空间,当剩余空间达到阈值发送报警邮件给root管理员

#!/bin/bashdisk_value=1000                                 #设置/分区监测空间mem_value=500                                   #设置内存监测空间disk_size=`df -m / | awk '///{print $4}'`      #获取/的剩余硬盘空间,单位Mmem_size=`free -m | awk '/Mem/{print $4}'`      #获取剩余内存空间,单位Mwhile :do    if [ $disk_size -le $disk_value -o $mem_size -le $mem_value ]; then     #判断条件        echo "Insufficient resources,资源不足" | mail -s "Warning" root     #达到阈值发送邮件给root    fidone

批量下载有序文件(pdf、图片、视频等)

#!/bin/bash#本脚本进行有序的网络资料批量下载操作(如01.jpg,02.jpg,03.jpg)url="http://www.test.com"type=jpgDpath=/mnt                                                                                         echo "开始下载..."for num in `seq 10`do    echo -n "正在下载$num.$type"    curl -s ${url}/${num}.${type} -o $Dpath/${num}.$type     #-o选项,curl指定下载文件另存为    if [ $? -eq 0 ]; then        echo -e  "          [e[32mOKe[0m]"    else        echo -e "           [e[31mERRORe[0m]"    fi    sleep 1done

批量修改文件名

示例:# touch article_{1..3}.html# lsarticle_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/.*(_.*)/bbs1/')    # 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

统计当前目录中以.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))doneecho $sum

扫描主机端口状态

#!/bin/bashHOST=$1PORT="22 25 80 8080"for PORT in $PORT; do    if echo &>/dev/null > /dev/tcp/$HOST/$PORT; then        echo "$PORT open"    else        echo "$PORT close"    fidone

自动优化Linux内核参数

#!/bin/bash#此脚本针对RHEL7系列cat >> /usr/lib/sysctl.d/00-system.conf << EOFfs.file-max=65535net.ipv4.tcp_timestamps = 0net.ipv4.tcp_synack_retries = 5net.ipv4.tcp_syn_retries = 5net.ipv4.tcp_tw_recycle = 1net.ipv4.tcp_tw_reuse = 1net.ipv4.tcp_fin_timeout = 30#net.ipv4.tcp_keepalive_time = 120net.ipv4.ip_local_port_range = 1024 65535kernel.shmall = 2097152kernel.shmmax = 2147483648kernek.shmmin = 4096kernel.sem = 5010 641280 5010 128net.core.wmem_default=262144 net.core.wmem_max=262144 net.core.rmem_default=4194304 net.core.rmem_max=4194304 net.ipv4.tcp_fin_timeout = 10 net.ipv4.tcp_keepalive_time = 30 net.ipv4.tcp_window_scaling = 0 net.ipv4.tcp_sack = 0 EOF 

统计/var/log有多少个文件,并显示这些文件名

#!/bin/bash#方法1sum=0                           #用于统计数量for i in `ls /var/log/`do    if [ -f $i ];then        let sum++        echo "文件名:$i"    fidoneecho "文件总量为:$sum"#方法2echo "文件总量为:"`find /var/log -maxdepth 1 -type f | wc -l`

查找Linux系统中的僵尸进程

#!/bin/bash#awk判断ps命令输出的第8列为z时,显示该进程的PID和进程命令ps aux | awk '{if($8 == "Z" ){print $2,$11}}'

Expect实现SSH免交互执行命令

Expect是一个自动交互式应用程序的工具,如telnet,ftp,passwd等。需先安装expect软件包。方法1:EOF标准输出作为expect标准输入#!/bin/bashUSER=rootPASS=123.comIP=192.168.1.120expect << EOFset timeout 30spawn ssh $USER@$IP   expect {    "(yes/no)" {send "yes"; exp_continue}    "password:" {send "$PASS"}}expect "$USER@*"  {send "$1"}expect "$USER@*"  {send "exit"}expect eofEOF方法2:#!/bin/bashUSER=rootPASS=123.comIP=192.168.1.120expect -c "    spawn ssh $USER@$IP    expect {        "(yes/no)" {send "yes"; exp_continue}        "password:" {send "$PASS"; exp_continue}        "$USER@*" {send "df -h exit"; exp_continue}    }"方法3:将expect脚本独立出来登录脚本:# cat login.exp#!/usr/bin/expectset ip [lindex $argv 0]set user [lindex $argv 1]set passwd [lindex $argv 2]set cmd [lindex $argv 3]if { $argc != 4 } {puts "Usage: expect login.exp ip user passwd"exit 1}set timeout 30spawn ssh $user@$ipexpect {    "(yes/no)" {send "yes"; exp_continue}    "password:" {send "$passwd"}}expect "$user@*"  {send "$cmd"}expect "$user@*"  {send "exit"}expect eof执行命令脚本:写个循环可以批量操作多台服务器#!/bin/bashHOST_INFO=user_info.txtfor ip in $(awk '{print $1}' $HOST_INFO)do    user=$(awk -v I="$ip" 'I==$1{print $2}' $HOST_INFO)    pass=$(awk -v I="$ip" 'I==$1{print $3}' $HOST_INFO)    expect login.exp $ip $user $pass $1doneLinux主机SSH连接信息:# cat user_info.txt192.168.1.120 root 123456

批量修改服务器用户密码

Linux主机SSH连接信息:旧密码# cat old_pass.txt 192.168.18.217  root    123456     22192.168.18.218  root    123456     22内容格式:IP User Password PortSSH远程修改密码脚本:新密码随机生成https://www.linuxprobe.com/books#!/bin/bashOLD_INFO=old_pass.txtNEW_INFO=new_pass.txtfor 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";exp_continue}        "password:" {send "$PASS";exp_continue}        "$USER@*" {send "echo '$NEW_PASS' |passwd --stdin $USER exit";exp_continue}    }"done生成新密码文件:# cat new_pass.txt 192.168.18.217  root    n8wX3mU%      22192.168.18.218  root    c87;ZnnL      22

while循环检测所处网段主机的开关机状态

#!/bin/bashi=1while [ $i -le 254 ]do    ping -c2 -i0.2 -W1 192.168.4.$i &>/dev/null    if [ $? -eq 0 ] ;then        echo -e "e[32;1m192.168.4.$i is up[0m"    else        echo "192.168.4.$i is down"    fi    let i++done

循环关闭局域网中所有主机

#!/bin/bash#假设本机为192.168.4.100,编写脚本关闭除自己外的其他所有主机#脚本执行,需要提前给所有其他主机传递ssh密钥,满足无密码连接for i in {1..254}do    [ $i -eq 100 ] && continue    echo "正在关闭192.168.4.$i..."    ssh 192.168.4.$i poweroffdone

自动添加防火墙规则(开启服务或端口

#!/bin/bash#适用于RHEL7系列#firewall-cmd --get-services        #可以查看firewall支持哪些服务#cat /etc/services                  #可以查看服务、端口的对应表services="ssh http nfs"      #设置服务ports="22 80 2049"         #设置端口号 ssh、http 、 nfs#循环将每个服务添加到防火墙规则中for service in $servicesdo    echo "添加 $service 服务到 防火墙"    firewall-cmd --add-service=${service}done#循环将每个端口添加到防火墙规则中for port in $portsdo    echo "添加 $port 端口到 防火墙"    firewall-cmd --add-port=${port}/tcpdone#将以上设置的临时防火墙规则,转换为永久有效的规则(确保重启后有效)firewall-cmd --runtime-to-permanent

自动配置rsyncd服务器的配置文件rsyncd.conf

#!/bin/bash#man rsyncd.conf                            #可查看更多选项[ ! -d /home/ftp ] && mkdir /home/ftpecho 'uid = nobody                                                                                 gid = nobodyuse chroot = yesmax connections = 4pid file = /var/run/rsyncd.pidexclude = lost+found/transfer logging = yestimeout = 900ignore nonreadable = yesdont compress = *.gz  *.tgz  *.zip  *.z  *.Z  *.rpm  *.deb  *.bz2[ftp]    path = /home/ftp    comment = share' > /etc/rsyncd.conf

一键配置VNC远程桌面服务器(无密码仅查看版本)

#!/bin/bash##脚本配置的VNC服务器,客户端无需密码即可连接#客户端仅有查看远程桌面的权限,没有鼠标、键盘的操作权限rpm --quiet -q tigervnc-server            #--quiet安静,-q查询,vnc的安装情况if [ $? -ne 0 ];then  yum -y install tigervnc-serverfix0vncserver AcceptKeyEvents=0 AlwaysShared=1 AcceptPointerEvents=0 SecurityTypes=None rfbport

fdisk命令自动对磁盘分区、格式化、挂载

#!/bin/bash#对虚拟机的vdb磁盘进行分区格式化,使用<> /etc/fstabmount -a

自动创建逻辑卷

#!/bin/bash#清屏,显示警告信息,创建将磁盘转换为逻辑卷会删除数据clearecho -e "033[33m           !!!!!!警告(Warning)!!!!!!033[0m"echoecho "+++++++++++++++++++++++++++++++++++++++++++++++++" echo "脚本会将整个磁盘转换为 PV,并删除磁盘上所有数据!!!" echo "This Script will destroy all data on the Disk" echo "+++++++++++++++++++++++++++++++++++++++++++++++++" lsblk       #显示当前的块设备echoread -p "请问是否继续 y/n?:" sure[ $sure != y ] && exit          #测试用户输入的是否为y,若不是则退出脚本#提示用户输入相关参数(磁盘、卷组名等数据),并测试用户是否输入了这些值,#若没输入,则脚本退出read -p "请输入磁盘名称,如/dev/vdb:" disk[ -z $disk ] && echo "没有输入磁盘名称" && exit     #-z后边的字符串长度为0则为真read -p "请输入卷组名称:" vg_name[ -z $vg_name ] && echo "没有输入卷组名称" && exitread -p "请输入逻辑卷名称:" lv_name[ -z $lv_name ] && echo "没有输入逻辑卷名称" && exitread -p "请输入逻辑卷大小:" lv_size[ -z $lv_size ] && echo "没有输入逻辑卷大小" && exit#使用命令创建逻辑卷pvcreate $diskvgcreate $vg_name $disklvcreate  -L ${lv_size}M  -n ${lv_name}  ${vg_name}#                                                                                                  lsblk $disk
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值