100個非常實用的Shell拿來就用腳本實例


轉載https://www.toutiao.com/i6921165421349487107/?wid=1620965217918

shell腳本是幫助程序員和系統管理員完成費時費力的枯燥工作的利器,是與計算機交互並管理文件和系統操作的有效方式。區區幾行代碼,就可以讓計算機接近按照你的意圖行事。
博智互聯為大家整理了100個實例,通過100個實戰經典腳本實例,展示了shell腳本編程的實用技術和常見工具用法。大家只需根據自己的需求,將文中這些常見任務和可移植自動化腳本推廣應用到其他類似問題上,能解決那些三天兩頭碰上的麻煩事。

判斷用戶輸入的是否為數字

方法1:

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

監控目錄,將新創建的文件名追加到日志中

場景:記錄目錄下文件操作。

需先安裝inotify-tools軟件包。

#!/bin/bash MON_DIR=/opt inotifywait -mq --format %f -e create $MON_DIR |\ while read files; do echo $files >> test.log done

給用戶提供多個網卡選擇

場景:服務器多個網卡時,獲取指定網卡,例如網卡流量

#!/bin/bash function 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/bash DATE=$(date +%F_%H-%M-%S) HOST=192.168.1.120 DB=test USER=bak PASS=123456 MAIL="zhangsan@example.com lisi@example.com" BACKUP_DIR=/data/db_backup SQL_FILE=${DB}_full_$DATE.sql BAK_FILE=${DB}_full_$DATE.zip cd $BACKUP_DIR if 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 fi else echo "$DATE 內容" | mail -s "主題" $MAIL fi find $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/functions WORD_DIR=/usr/local/nginx DAEMON=$WORD_DIR/sbin/nginx CONF=$WORD_DIR/conf/nginx.conf NAME=nginx PID=$(awk -F'[; ]+' '/^[^#]/{if($0~/pid;/)print $2}' $CONF) if [ -z "$PID" ]; then PID=$WORD_DIR/logs/nginx.pid else PID=$WORD_DIR/$PID fi stop() { $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.txt Web 192.168.1.10 root 22 DB 192.168.1.11 root 22 內容格式:主機名 IP User Port #!/bin/bash PS3="Please input number: " HOST_FILE=host.txt while 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 done done

將結果分別賦值給變量

應用場景:希望將執行結果或者位置參數賦值給變量,以便后續使用。

方法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]})

讀取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/bash echo "方法①,指定以:為分隔符,打印/etc/passwd文件的第1列" awk -F: '{print $1}' /etc/passwd echo "方法②,指定以:為分隔符,打印/etc/passwd文件的第1列" cut -d: -f1 /etc/passwd echo "方法③使用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++ fi done echo $n

找出/etc/passwd中能登錄的用戶,並將對應在/etc/shadow中第二列密碼提出處理

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

自動修改計划任務配置文件

#!/bin/bash read -p "請輸入分鍾信息(00-59):" min read -p "請輸入小時信息(00-24):" hour read -p "請輸入日期信息(01-31):" date read -p "請輸入月份信息(01-12):" month read -p "請輸入周幾信息(00-06):" weak read -p "請輸入計划任務需要執行的命令或腳本:" program echo "$min $hour $date $month $weak $USER $program" >> /etc/crontab

實時監視本機內存、/分區剩余空間,當剩余空間達到閾值發送報警郵件給root管理員

#!/bin/bash disk_value=1000 #設置/分區監測空間 mem_value=500 #設置內存監測空間 disk_size=`df -m / | awk '/\//{print $4}'` #獲取/的剩余硬盤空間,單位M mem_size=`free -m | awk '/Mem/{print $4}'` #獲取剩余內存空間,單位M while : do if [ $disk_size -le $disk_value -o $mem_size -le $mem_value ]; then #判斷條件 echo "Insufficient resources,資源不足" | mail -s "Warning" root #達到閾值發送郵件給root fi done

批量下載有序文件(pdf、圖片、視頻等)

#!/bin/bash #本腳本進行有序的網絡資料批量下載操作(如01.jpg,02.jpg,03.jpg) url="http://www.test.com" type=jpg Dpath=/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[32mOK\e[0m]" else echo -e " [\e[31mERROR\e[0m]" fi sleep 1 done

批量修改文件名

示例:

# 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

統計當前目錄中以.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

掃描主機端口狀態

#!/bin/bash HOST=$1 PORT="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" fi done

自動優化Linux內核參數

#!/bin/bash #此腳本針對RHEL7系列 cat >> /usr/lib/sysctl.d/00-system.conf << EOF fs.file-max=65535 net.ipv4.tcp_timestamps = 0 net.ipv4.tcp_synack_retries = 5 net.ipv4.tcp_syn_retries = 5 net.ipv4.tcp_tw_recycle = 1 net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_fin_timeout = 30 #net.ipv4.tcp_keepalive_time = 120 net.ipv4.ip_local_port_range = 1024 65535 kernel.shmall = 2097152 kernel.shmmax = 2147483648 kernek.shmmin = 4096 kernel.sem = 5010 641280 5010 128 net.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 #方法1 sum=0 #用於統計數量 for i in `ls /var/log/` do if [ -f $i ];then let sum++ echo "文件名:$i" fi done echo "文件總量為:$sum" #方法2 echo "文件總量為:"`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/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腳本獨立出來 登錄腳本: # cat login.exp #!/usr/bin/expect set 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 30 spawn ssh $user@$ip expect { "(yes/no)" {send "yes\r"; exp_continue} "password:" {send "$passwd\r"} } expect "$user@*" {send "$cmd\r"} expect "$user@*" {send "exit\r"} expect eof 執行命令腳本:寫個循環可以批量操作多台服務器 #!/bin/bash HOST_INFO=user_info.txt for 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 $1 done Linux主機SSH連接信息: # cat user_info.txt 192.168.1.120 root 123456

批量修改服務器用戶密碼

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遠程修改密碼腳本:新密碼隨機生成 https://www.linuxprobe.com/books #!/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

while循環檢測所處網段主機的開關機狀態

#!/bin/bash i=1 while [ $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 poweroff done

自動添加防火牆規則(開啟服務或端口

#!/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 $services do echo "添加 $service 服務到 防火牆" firewall-cmd --add-service=${service} done #循環將每個端口添加到防火牆規則中 for port in $ports do echo "添加 $port 端口到 防火牆" firewall-cmd --add-port=${port}/tcp done #將以上設置的臨時防火牆規則,轉換為永久有效的規則(確保重啟后有效) firewall-cmd --runtime-to-permanent

自動配置rsyncd服務器的配置文件rsyncd.conf

#!/bin/bash #man rsyncd.conf #可查看更多選項 [ ! -d /home/ftp ] && mkdir /home/ftp echo 'uid = nobody gid = nobody use chroot = yes max connections = 4 pid file = /var/run/rsyncd.pid exclude = lost+found/ transfer logging = yes timeout = 900 ignore nonreadable = yes dont 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-server fi x0vncserver AcceptKeyEvents=0 AlwaysShared=1 AcceptPointerEvents=0 SecurityTypes=None rfbport

fdisk命令自動對磁盤分區、格式化、掛載

#!/bin/bash #對虛擬機的vdb磁盤進行分區格式化,使用<<將需要的分區指令導入給程序fdisk #n(新建分區),p(創建主分區),1(分區編號為1), #兩個空白行(兩個回車,相當於將整個磁盤分一個區)。 #注意:1后面的兩個回車(空白行)是必須的! fdisk /dev/vdb << EOF n p 1 wq EOF #格式化剛剛創建好的分區 mkfs.xfs /dev/vdb1 #創建掛載點目錄 if [ -e /data ] ;then exit fi mkdir /data #自動掛載剛剛創建的分區,並設置開機自動掛載該分區 echo "/dev/vdb1 /data xfs defaults 1 2" >> /etc/fstab mount -a

自動創建邏輯卷

#!/bin/bash #清屏,顯示警告信息,創建將磁盤轉換為邏輯卷會刪除數據 clear echo -e "\033[33m !!!!!!警告(Warning)!!!!!!\033[0m" echo echo "+++++++++++++++++++++++++++++++++++++++++++++++++" echo "腳本會將整個磁盤轉換為 PV,並刪除磁盤上所有數據!!!" echo "This Script will destroy all data on the Disk" echo "+++++++++++++++++++++++++++++++++++++++++++++++++" lsblk #顯示當前的塊設備 echo read -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 "沒有輸入卷組名稱" && exit read -p "請輸入邏輯卷名稱:" lv_name [ -z $lv_name ] && echo "沒有輸入邏輯卷名稱" && exit read -p "請輸入邏輯卷大小:" lv_size [ -z $lv_size ] && echo "沒有輸入邏輯卷大小" && exit #使用命令創建邏輯卷 pvcreate $disk vgcreate $vg_name $disk lvcreate -L ${lv_size}M -n ${lv_name} ${vg_name} # lsblk $disk


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM