Linux Shell 脚本攻略

2017-07-04  本文已影响0人  巴喬書摘

第1章 小试牛刀

#!/bin/bash
cat << EOF > log.txt
hi
hello
EOF

运行 . out,log.txt 的内容为:

hi
hello
#!/bin/bash
echo -e "Enter password: "
stty -echo
read password
stty echo
echo
echo Password read.
#!/bin/bash
echo -n count:
tput sc
count=11
while true
do
    if [ $count -gt 0 ]
    then
        let count--
        sleep 1
        tput rc
        tput ed
        echo -n $count
        else exit 0
    fi
done
#!/bin/bash
for i in {1..6}
do
    set -x
    echo $i
    set +x
done
echo "Script executed."

执行时显示:-x。读取时显示:-v
#!/bin/bash改为#!/bin/bash -xv,则直接运行即可。
自定义调试信息:

#!/bin/bash
function DEBUG()
{
    [ "$_DEBUG" == "on" ] && $@ || :
}
for i in {1..10}
do
    DEBUG echo $i
done

此处echo $i即为调试信息。

:(){ :|:& }; :

:()
{
    : | : &
}
:

: 为函数名。可通过ulimit -u 128(暂时)或修改配置文件 /etc/security/limits.conf 来限制可生成的最大进程数来避开。

pwd
(cd /bin; ls)
pwd

子 shell 中的命令对当前 shell 没有影响。

repeat()
{
    while true
    do
        $@ && return
        sleep 30
    done
}

更快的做法:repeat() { while :; do $@ && return; sleep 30; done}
:是内建命令,总返回0

data="name,sex,rollno,location"
oldIFS=$IFS
IFS=,
for item in $data
do
    echo Item: $item
done
IFS=$oldIFS
#!/bin/bash
line="root:x:0:0:root:/root:/bin/bash"
oldIFS=$IFS
IFS=:
count=0
for item in $line
do
    [ $count -eq 0 ] && user=$item
    [ $count -eq 6 ] && shell=$item
    let count++
done
IFS=$oldIFS
echo $user\'s shell is $shell

第2章 命令之乐

file="sample.jpg"
name=${file%.*}
extension=${file#*.}

%从右向左找最短匹配并删除,%%找最长匹配并删除。###则从左向右找。

#!/bin/bash
# 将当前目录下的png和jpg文件重命名
count=1
for img in `find . -iname '*.png' -o -iname '*.jpg' -type f -maxdepth 1`
do
    new=image-$count.${img##*.}

    echo "Renaming $img to $new"
    mv "$img" "$new"
    let count++
done

C 版本renamerename .JPG .jpg *.JPG,即把所有.JPG文件从.JPG改为.jpg
Perl 版本renamerename *.JPG *.jpg。所有文件的空格全部替换为下划线rename 's/ /_/g' *。大写转小写rename 'y/A-Z/a-z/' *

#!/bin/bash
word=$1
grep "^$1$" /usr/share/dict/words -q
if [ $? -eq 0 ]; then
    echo $word is a dictionary word.
else
    echo $word is not a dictionary word.
fi

其中,^$标记单词的开始和结束。-q禁止任何输出。或者

#!/bin/bash
word=$1
output=`echo \"$word\" | aspell list`
if [ -z $output ]; then
    echo $word is a dictionary word.
else
    echo $word is not a dictionary word.
fi
#!/bin/bash
PIDARRAY=()
for file in File1.iso File2.iso
do
    md5sum $file &
    PIDARRAY+=("$!")
done
wait ${PIDARRAY[@]}

&将命令置于后台运行。$!获得最近一个后台进程 PID。wait等待进程结束。

第3章 以文件之名

#!/bin/bash
# ls -lS --time-style=long-iso | awk 'BEGIN {
#     getline; getline
ls -lS --time-style=long-iso | grep ^- | awk 'BEGIN {
    getline
    name1=$8; size=$5
}
{
    name2=$8
    if ( size==$5 )
    {
        "md5sum " name2 | getline; csum2=$1;
        "md5sum " name1 | getline; csum1=$1;
        if ( csum1==csum2 )
        {
            print name1; print name2
        }
    }
    else
    {
        size=$5
    }
   name1=name2
}' | sort -u > duplicate_files
cat duplicate_files | xargs -I {} md5sum {} | sort | uniq -w 32 | awk '{print $2}' | sort -u > duplicate_sample
echo Removing...
comm duplicate_files duplicate_sample -2 -3 | tee /dev/stderr | xargs rm
rm duplicate_files duplicate_sample
echo Removed duplicates files successfully.

若含csum2=$1csum1=$1的两行交换位置,则运行结果错误,原因不明。

!/bin/bash
if [ $# -ne 1 ]
then
    echo "Usage is $0 basepath"
    exit
fi
path=$1
declare -A statarray
while read line
do
    ftype=`file -b "$line" | cut -d , -f 1`
    let statarray["$ftype"]++
done < <(find $path -type f -print)
echo ======== File types and counts ========
for ftype in "${!statarray[@]}"
do
    echo $ftype : ${statarray["$ftype"]}
done

其中,$#是传递给脚本的参数个数,$0是脚本自己的名字,$1是传给脚本的第一个参数,file -b只打印文件类型,cut -d , -f 1选取以逗号分隔的第一列数据,<(find $path -type f -print)获取子进程输出数据流。Bash 3.0 及更高版本中,亦可用done <<< "`find $path -type f -print`"

dd if=/dev/zero of=loopbackfile.img bs=1G count=1
mkfs.ext4 loopbackfile.img
mkdir /mnt/loopback
mount -o loop loopbackfile.img /mnt/loopback
umount /mnt/loopback

分区:

losetup /dev/loop1 loopbackfile.img
fdisk /dev/loop1
losetup -o 32256 /dev/loop2 loopbackfile.img

或使用:

kpartx -v -a loopbackfile.img
mount /dev/mapper/loop0p1 /mnt/loopback1
kpartx -d loopbackfile.img

将对挂载设备的更改即刻写入物理设备:sync

第4章 让文本飞

#!/bin/bash
if [ $# -ne 1 ]
then
    echo "Usage is $0 filename"
    exit -1
fi
filename=$1
egrep -o "\b[[:alpha:]]+\b" $filename | \
awk '{ count[$0]++ }
END { printf("%-14s%s\n", "Word", "Count");
for( ind in count )
{ printf("%-14s%d\n", ind, count[ind]) }
}'
awk '{ lifo[NR]=$0 }
END { for ( lno=NR; lno > 0; lno-- ) { print lifo[lno] } }' file

第5章 一团乱麻?没这回事

第6章 B 计划

第7章 无网不利

#!/bin/bash
for ip in 172.17.110.{1..255}
do
(
    ping $ip -c 2 &> /dev/null

    if [ $? -eq 0 ]
    then
        echo $ip is alive.
    fi
)&
done
wait

或者使用fping -a 172.17.110.1/24 -g 2> /dev/nullfping -a 172.17.110.0.1 172.17.110.255 -g

#!/bin/bash
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -A FORWARD -i $1 -o $2 -s 10.99.0.0/16 -m conntrack --ctstate NEW -j ACCEPT
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A POSTROUTING -t nat -j MASQUERADE

运行./netsharing.sh eth0 wlan0

第8章 当个好管家

#!/bin/bash
SECS=3600
UNIT_TIME=60
STEPS=$(( $SECS / $UNIT_TIME ))
echo Watching CPU usage...
for (( i=0; i<STEPS; i++ ))
do
    ps -eo comm,pcpu | tail -n +2 >> /tmp/cpu_usage.$$
    sleep $UNIT_TIME
done
echo
echo CPU eaters :
cat /tmp/cpu_usage.$$ | \
awk '{process[$1] += $2 }
END{
    for ( i in process )
    {
        printf("%-20s %s\n", i, process[i])
    }
}' | sort -nrk 2 | head
rm /tmp/cpu_usage.$$

comm表示命令名,pcpu表示 CPU 使用率,$$是脚本的进程 ID。

#!/bin/bash
path=$1
inotifywait -m -r -e create,move,delete $path -q

持续监视变化-m,递归-r,指定需用监视的事件-e

#!/bin/bash
AUTHLOG=/var/log/secure
if [[ -n $1 ]];
then
    AUTHLOG=$1
    echo Using Log file : $AUTHLOG
fi
LOG=/tmp/valid.$$.log
grep -v "invalid" $AUTHLOG > $LOG
users=$(grep "Failed password" $LOG | awk '{ print $(NF-5) }' | sort | uniq)
printf "%-5s|%-10s|%-10s|%-13s|%-33s|%s\n" "Sr#" "User" "Attempts" "IP address" "Host_Mapping" "Time range"
ucount=0
ip_list="$(egrep -o "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" $LOG | sort | uniq)"
for ip in $ip_list
do
    grep $ip $LOG > /tmp/temp.$$.log
    for user in $users
    do
        grep $user /tmp/temp.$$.log > /tmp/$$.log
        cut -c -16 /tmp/$$.log > $$.time
        tstart=$(head -1 $$.time)
        start=$(date -d "$tstart" "+%s")
        tend=$(tail -1 $$.time)
        end=$(date -d "$tend" "+%s")
        limit=$(( $end - $start ))
        if [ $limit -gt 120 ]
        then
            let ucount++
            IP=$(egrep -o "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" /tmp/$$.log | head -1)
            TIME_RANGE="$tstart-->$tend"
            ATTEMPTS=$(cat /tmp/$$.log | wc -l)
            HOST=$(host $IP | awk '{ print $NF }')
            printf "%-5s|%-10s|%-10s|%-10s|%-33s|%-s\n" "$ucount" "$user" "$ATTEMPTS" "$IP" "$HOST" "$TIME_RANGE"
        fi
    done
done
rm /tmp/valid.$$.log /tmp/$$.log $$.time /tmp/temp.$$.log 2> /dev/null

排除不存在的用户名grep -v "invalid"

#!/bin/bash
logfile="diskusage.log"
if [[ -n $1 ]];
then
    logfile=$1
fi
if [ ! -e $logfile ]
then
    printf "%-8s %-14s %-9s %-8s %-6s %-6s %-6s %s\n" "Date" "IP address" "Device" "Capacity" "Used" "Free" "Percent" "Status" > $logfile
fi
ip_list="10.0.0.1 10.0.0.2"
(
for ip in $ip_list
do
    ssh kangk@$ip 'df -H' | grep ^/dev/ > /tmp/$$.df
    while read line
    do
        cur_date=$(date +%D)
        printf "%-8s %-14s " $cur_date $ip
        echo $line | awk '{ printf("%-9s %-8s %-6s %-6s %-8s", $1,$2,$3,$4,$5) }'
        pusg=$(echo $line | egrep -o "[0-9]+%")
        pusg=${pusg/\%/}
        if [ $pusg -lt 80 ]
        then
            echo SAFE
        else
            echo ALERT
        fi
    done < /tmp/$$.df
done
echo
) >> $logfile

第9章 管理重任

上一篇下一篇

猜你喜欢

热点阅读