2023年7月10日发(作者:)
100个⾮常实⽤的Shell拿来就⽤脚本实例转载/i69287107/?wid=162shell脚本是帮助程序员和系统管理员完成费时费⼒的枯燥⼯作的利器,是与计算机交互并管理⽂件和系统操作的有效⽅式。区区⼏⾏代码,就可以让计算机接近按照你的意图⾏事。博智互联为⼤家整理了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 >> e给⽤户提供多个⽹卡选择场景:服务器多个⽹卡时,获取指定⽹卡,例如⽹卡流量#!/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_nicMySQL数据库备份#!/bin/bashDATE=$(date +%F_%H-%M-%S)HOST=192.168.1.120DB=testUSER=bakPASS=123456MAIL="zhangsan@ lisi@"BACKUP_DIR=/data/db_backupSQL_FILE=${DB}_full_$_FILE=${DB}_full_$ $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/ME=nginxPID=$(awk -F'[; ]+' '/^[^#]/{if($0~/pid;/)print $2}' $CONF)if [ -z "$PID" ]; then PID=$WORD_DIR/logs/e 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 " 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 " || echo "$NAME not running!" ;; *) echo "Usage: $0 {start|stop|restart|reload|testconfig|status}" exit 3 ;;esac⽤户根据菜单选择要连接的Linux主机Linux主机SSH连接信息:# cat 192.168.1.10 root 22DB 192.168.1.11 root 22内容格式:主机名 IP User Port#!/bin/bashPS3="Please input number: "HOST_FILE=le 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 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]})读取⽂件中的账号密码批量创建⽤户#!/bin/bash#提前准备账号密码⽂件#⽂件内每⾏⼀个账号密码组,使⽤逗号分隔(username,password)for line in `cat `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#本脚本进⾏有序的⽹络资料批量下载操作(如,,)url=""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_ article_ article_⽬的:把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/ << -max=_timestamps = _synack_retries = _syn_retries = _tw_recycle = _tw_reuse = _fin_timeout = 30#_keepalive_time = _local_port_range = 1024 = = = = 5010 641280 5010 _default=262144
_max=262144
_default=4194304
_max=4194304
_fin_timeout = 10
_keepalive_time = 30
_window_scaling = 0
_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==192.168.1.120expect << EOFset timeout 30spawn ssh $USER@$IP
expect { "(yes/no)" {send "yesr"; exp_continue} "password:" {send "$PASSr"}}expect "$USER@*" {send "$1r"}expect "$USER@*" {send "exitr"}expect eofEOF⽅法2:#!/bin/bashUSER=rootPASS==192.168.1.120expect -c " spawn ssh $USER@$IP expect { "(yes/no)" {send "yesr"; exp_continue} "password:" {send "$PASSr"; exp_continue} "$USER@*" {send "df -hr exitr"; exp_continue} }"⽅法3:将expect脚本独⽴出来登录脚本:# cat #!/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 ip user passwd"exit 1}set timeout 30spawn ssh $user@$ipexpect { "(yes/no)" {send "yesr"; exp_continue} "password:" {send "$passwdr"}}expect "$user@*" {send "$cmdr"}expect "$user@*" {send "exitr"}expect eof执⾏命令脚本:写个循环可以批量操作多台服务器#!/bin/bashHOST_INFO=user_ 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 $ip $user $pass $1doneLinux主机SSH连接信息:# cat user_192.168.1.120 root 123456批量修改服务器⽤户密码Linux主机SSH连接信息:旧密码# cat old_
192.168.18.217 root 123456 22192.168.18.218 root 123456 22内容格式:IP User Password PortSSH远程修改密码脚本:新密码随机⽣成/books#!/bin/bashOLD_INFO=old__INFO=new_ 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 "yesr";exp_continue} "password:" {send "$PASSr";exp_continue} "$USER@*" {send "echo '$NEW_PASS' |passwd --stdin $USERr exitr";exp_continue} }"done⽣成新密码⽂件:# cat new_
192.168.18.217 root n8wX3mU% 22192.168.18.218 root c87;ZnnL 22while循环检测所处⽹段主机的开关机状态#!/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服务器的配置⽂件#!/bin/bash#man #可查看更多选项[ ! -d /home/ftp ] && mkdir /home/ftpecho 'uid = nobody
gid = nobodyuse chroot = yesmax connections = 4pid file = /var/run/lude = lost+found/transfer logging = yestimeout = 900ignore nonreadable = yesdont compress = *.gz *.tgz *.zip *.z *.Z *.rpm *.deb *.bz2[ftp] path = /home/ftp comment = share' > /etc/⼀键配置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 rfbportfdisk命令⾃动对磁盘分区、格式化、挂载#!/bin/bash#对虚拟机的vdb磁盘进⾏分区格式化,使⽤<<将需要的分区指令导⼊给程序fdisk#n(新建分区),p(创建主分区),1(分区编号为1),#两个空⽩⾏(两个回车,相当于将整个磁盘分⼀个区)。#注意:1后⾯的两个回车(空⽩⾏)是必须的!fdisk /dev/vdb << EOFnp1wqEOF#格式化刚刚创建好的分区 /dev/vdb1#创建挂载点⽬录if [ -e /data ] ;then exit
fimkdir /data#⾃动挂载刚刚创建的分区,并设置开机⾃动挂载该分区echo "/dev/vdb1 /data xfs defaults 1 2" >> /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
发布者:admin,转转请注明出处:http://www.yc00.com/web/1688985837a191755.html
评论列表(0条)