最近一直在研究shell脚本,整理了些比较有用的以备不时之需。。


1.获取字符串长度

# var=1234567890

# echo ${#var}


2.识别当前shell版本

# echo $SHELL

# echo $0


3.检查是否为超级用户

-------------------------

#!/bin/bash

if [ $UID -ne 0 ];then

echo Non root user .Please run as root.

else

echo "Root user"

fi

-------------------------


4.修改Bash提示字符串

# cat /etc/bashrc | grep PS1


5.重定向脚本内部的文本块

-------------------------

#!/bin/bash

cat <<EOF>>log.txt

LOG FILE HEADER

This is a test log file

Function: System statistions

EOF

-------------------------


6.删除空白行

# cat file.txt | tr -s '\n'

# cat file.txt | sed '/^$/d'


7.find忽略大小写

# find . -iname "example" -print


8.find 匹配多个条件

# find . \( -name "*.txt" -o -name "*.pdf" \) -print


9.否定参数

# find . ! -name "*.txt" -print


10.结合find使用xargs

# find . -type f -name "*.txt" -print0 | xargs -0 rm -f

注:这里xargs -0将\0作为输入定界符,防止搜索到带空格的字符后被find识别成2个文件


11.生成一个大小为100K的测试文件

# dd if=/dev/zero bs=100k count=1 of=date.file


12.用特定格式重命名当前目录下的图像文件、

-------------------------------

#!/bin/bash

count=1

for img in *.jpg *.png

do

  new=p_w_picpath-$count.${img##*.}

  mv "$img" "$new" 2> /dev/null

if [ $? -eq 0 ];

  then

  echo "Renaming $img to $new"

  let count++

fi

done


-------------------------------


13.URL="www.google.com"

# echo ${URL%.*} # 移除 .*所匹配的最右边的内容

www.google


# echo ${URL%%.*} # 将从右边开始一直匹配到最左边的*.移除(贪婪操作符)

www


# echo ${URL#*.} # 移除*.所匹配的最左边的内容

google.com


# echo ${URL##*.} # 将从左边开始一直匹配到最右边的*.移除(贪婪操作符)

com


14.将一个文件设置为不可修改:

# chattr +i file

恢复:

# chattr -i file


15.生成不同的空白文件:

----------------

for name in (1...100).txt

do

touch $name

done

----------------


16.移除空白行

# sed '/^$/d' file


17.打印可用的网络接口

# ifconfig | cut -c-10 |tr -d ' ' |tr -s '\n'

注:cut -c-10为提取每行前10个字符,也可以这么写 cut -c1-10,tr -d ' '为删除每行所有空格,tr -s  '\n'为用单独的换行替换每一序列的一个或多个换行。

# ifconfig | grep '^[a-z].*' |cut -c-5


18.提取IP地址:

# ifconfig eth0 | grep 'inet addr:[0-9].*'|awk -F' ' '{print $2}'|awk -F':' '{print $2}'

子网掩码:

# ifconfig eth0 |grep  '.*Mask:[0-9].*$' |awk -F':' '{print $4}'

网关:

# route |grep "^default" |awk -F' ' '{print $2}'

MAC:

# ifconfig eth0 |grep '^.*HWaddr.*$'| awk -F' ' '{print $5}'


19.添加DNS

# echo "nameserver 61.134.1.4" >> /etc/resolv.conf


20.添加临时网关

# route add default gw 192.168.7.1 eth0


21.查看网内主机活动状态:

-------------------

#!/bin/bash


PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin

export PATH


NET_NUM=$(ifconfig eth0 | grep 'inet addr:[0-9].*'|awk -F' ' '{print $2}'|awk -F':' '{print $2}'|awk -F'.' '{print $1"."$2"."$3}')


for IP in $NET_NUM.{1..254};

do

  ping $IP -c2 &> /dev/null ;


  if [ $? -eq 0 ];

  then

     echo $IP is alive

  fi

done


-------------------


22.配置IP地址

-----------------------

#!/bin/bash


PATH=/bin:/sbin:/usr/bin:/usr/sbin/:/usr/local/bin:/usr/local/sbin:~/bin

export PATH


IFACE=eth0

IP_ADDR=192.168.7.74

NET_MASK=255.255.255.0

GW=192.168.7.1


# 判断是否为root权限

if [ $UID -ne 0 ];

then

  echo "Run as root"

  exit 1


# 关闭eth0

ifconfig $IFACE down


#配置IP和掩码

ifconfig $IFACE $IP_ADDR netmask $NET_MASK


#配置网关

route add default gw $GW $IFACE


# 开启eth0

ifconfig $IFACE up


echo "Successfully configured $IFACE"

-----------------------------


23.收集远程主机运行时间(先做加密认证)

-----------------------

#!/bin/bash


IP_LIST="192.168.0.[1..254]"

USER="test"


for IP in $IP_LIST;

do

  UPTIME=$(ssh $USER@$IP uptime |awk '{print $3}')

  echo "$IP uptime: $UPTIME"

done

------------------------


24.列出本地当前开放的端口

# netstat -ntulp |grep LISTEN |awk -F' ' '{print $4}'|sed 's/^0.0.0.0://g'|sed 's/^127.0.0.1://g'|sed 's/^::://g'|sed 's/^::1://g'|sort -n|uniq -c|awk -F' ' '{print $2}'

# yum install nmap -y && nmap -p1-65535 localhost


25.找出指定目录中最大的十个文件

# du -ak . |sort -nrk 1 | head -n 10

注:-a指定了所有目录和文件,-k输出第一列以KB为单位的文件大小,sort对第一列依数值逆序排序,head用来显示前10行输出

# find . -type f -exec du -k {} \; |sort -nrk 1 |head -n 10

或(推荐,效率最高)

# find . -type f -print0 |xargs -0 du -k |sort -nrk 1 |head -n 10


26.计算命令执行时间

# time find . -type f -exec du -k {} \; |sort -nrk 1 |head -n 10

# time find . -type f -print0 |xargs -0 du -k |sort -nrk 1 |head -n 10


27.打印出10条最常用的命令

------------------------------

#!/bin/bash


printf "COMMAND\tCOUNT\n";


cat ~/.bash_history | awk '{ list[$1]++; } \

END{

for(i in list)

{

printf("%s\t%d\n",i,list[i]); }

}'| sort -nrk 2 | head

------------------------------

注:

   在上面的脚本中,用~/.bash_history作为源文件,通过管道将源输入传递给awk,在awk中,我们使用了一个关联数组,这个数组将命令作为索引,将命令的出现的次数作为数组元素值。命令每出现一次,计数值增加1(list[$1]++).$1是输入文本行的第一个单词,如果使用$0,则包含输入文本行中所有的单词。

   比如说,如果ssh 192.168.0.4是.bash_history其中的一行,那么$0中包含ssh 192.168.0.4,$1中包含ssh.

   一旦对命令历史文件中的所有行遍历完毕,我们就得到了一个数组,其中数组索引是命令名称,数组元素值是命令出现的次数,因此出现次数最多的命令名称就是使用最频繁的命令。

   在awk的END{}语句块中,我们遍历关联数组,打印出所有的命令名及其对应的出现次数,sort -nrk 2 对第2列(COUNT)按照数值逆序排序,最后用head 命令从列表中提取出前10条命令,你可以用head -n NUMBER将前10条命令改为前5条或者是其他任意数量。



30.列出1小时内占用CPU最多的10个进程:

-----------------------

#!/bin/bash


PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin

export PATH


SECS=3600

UNIT_TIME=60


#secs为需要进行监视的总秒数

#UNIT_TIME是取样的时间间隔,单位是秒


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",i, process[i]) ;

   }


   }' | sort -nrk 2 | head

rm /tmp/cpu_usage.$$

#删除临时日志文件

-----------------------

注:在上面的脚本中,主要的输入源是ps -eo comm,pcpu,其中comm表示命令名(command name),pcpu表示CPU使用率(CPU usage in percent)。该命令输出所有进程名及CPU使用率,每个进程对应一行输出。因为需要监视一个小时内CPU的使用情况,所以我们得在一个每次迭代时间为60秒的for循环中不停的用ps -eo comm,pcpu |tail -n +2来获取CPU的使用统计数据,并将这些数据添加到文件/tmp/cpu_usage.$$中,60秒的迭代时间通过sleep 60来提供,这就使得每一分钟执行一次ps

   tail -n +2用来将ps 输出中的头部和COMMAND %CPU剥离.

   cpu_usage.$$中的$$表示当前脚本的进程ID,假设进程ID为1345,那么在脚本执行时,他会被替换成/tmp/cpu_usage.1345,因为这是一个临时文件,所以我们把它放在/tmp中。

   统计文件在1小时后就准备妥当了,文件中包含了60项,分别对应每分钟的进程状态,然后用awk求出每个进程中的CPU使用情况,我们用了一个关联数组来统计CPU的使用情况,其中进程名为数组索引,最后根据总的CPU使用情况依数值逆序排序,并通过head获得前10项。


31.利用watch监控命令查看输出

# watch -n 5 ls

注:利用此命令可以查看该目录的文件变化, -n 5 为间隔5秒更新一次



32.扫描secure日志文件并收集所需信息,生成入侵检测报告

方法一.扫描他人利用系统认证用户进行暴力破解。

---------------------------

#!/bin/bash


PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin

export PATH


AUTHLOG=/var/log/secure


if [ [ -n $1] ];

then

  AUTHLOG=$1

  echo Using Default 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|%-13s|%-33s|%s\n" "No#" "User" "Attepts" "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);

  #显示从1970年到该时刻所经历的秒数

  start=$(date -d "$tstart" "+%s");

  #显示登出时间

  tend=$(tail -1 $$.time);

  #显示从1970年到该时刻所经历的秒数

  end=$(date -d "$tend" "+%s")

  #算出登录时间

  limit=$(( $end - $start ))

  if [ $limit -gt 1 ];

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|%-13s|%-13s|%-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


---------------------------


方法二.扫描他人利用系统认证用户或非系统用户进行暴力破解。

---------------------------

#!/bin/bash


PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin

export PATH


AUTHLOG=/var/log/secure


if [[ -n $1 ]];

then

  AUTHLOG=$1

  echo Using Log file : $AUTHLOG

else

  echo Using Default Log file : $AUTHLOG

fi

LOG=/tmp/valid.$$.log

grep "Failed password" $AUTHLOG > $LOG

users=$(cat $LOG | awk '{ print $(NF-5) }'| sort | uniq)



printf "%-5s|%-10s|%-10s|%-13s|%-13s|%-33s|%s\n" "No#" "User" "Attepts" "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);

  #显示从1970年到该时刻所经历的秒数

  start=$(date -d "$tstart" "+%s");

  #显示登出时间

  tend=$(tail -1 $$.time);

  #显示从1970年到该时刻所经历的秒数

  end=$(date -d "$tend" "+%s")

  #算出登录时间

  limit=$(( $end - $start ))

  if [ $limit -ge 0 ];

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|%-13s|%-13s|%-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

---------------------------


33.监视远程磁盘的健康情况


----------------------------

#!/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" "Data" "IP address" "Device" "Capacity" "Used" "Free" "Percent" "Status" > $logfile

fi


IP_LIST="192.168.7.74"

{

for ip in $IP_LIST;

do

  ssh $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]+%")

    # 参见man bash 找${parameter/pattern/string}

    # .${parameter/pattern/string} ${parameter//pattern/string}

    # 在这里pattern也是一个模式,parameter展开后最长匹配的部分被string替换。      # 第一种情况只替换首次匹配,第二种情况替换所有匹配。

    pusg=${pusg/\%/};


    if [ $pusg -lt 80 ];

    then

       echo SAFE

    else

       echo ALERT

    fi

    done < /tmp/$$.df

   done

   } >> $logfile


----------------------------


34.创建数据库及数据表脚本


-------------------------------

#!/bin/bash


USER="root"

PASS="123456"

DB="test1"

TABLE="test1"


mysql -u $USER -p$PASS <<EOF 2> /dev/null

CREATE DATABASE $DB;

EOF


[ $? -eq 0 ] && echo Created $DB || echo $DB already exist


mysql -u $USER -p$PASS $DB <<EOF 2> /dev/null

CREATE TABLE $TABLE(

id int,

name varchar(100),

mark int,

dept varchar(4)

);

EOF


[ $? -eq 0 ] && echo Created table $TABLE || echo Table $TABLE already exist


-------------------------------

或(传参)

------------------------------

#!/bin/bash


USER="root"

PASS="123456"

DB="$1"

TABLE="$2"



if [ $# -ne 2 ]; # if传参的个数不等于2

then

  echo "please input the db and table name.exp: {sh db table}" && exit 0

elif [ "$1" -gt 0 -o "$2" -gt 0 ] 2>/dev/null ;

then

  echo "please input the right name(not number).exp: {sh db table}" && exit 0

fi



mysql -u $USER -p$PASS <<EOF 2> /dev/null

CREATE DATABASE $DB;

EOF


[ $? -eq 0 ] && echo Created $DB || echo $DB already exist


mysql -u $USER -p$PASS $DB <<EOF 2> /dev/null

CREATE TABLE $TABLE(

id int,

name varchar(100),

mark int,

dept varchar(4)

);

EOF


[ $? -eq 0 ] && echo Created table $TABLE || echo Table $TABLE already exist


------------------------------


35.将数据插入数据表:

-------------------------------

#!/bin/bash


USER="root"

PASS="123456"


if [ $# -ne 1 ];

then

  echo $0 DATAFILE

  echo

  exit 2

fi

data=$1


while read line;

do

 oldIFS=$IFS

 IFS=.

 values=($line)

 values[1]="\"`echo ${values[1]} | tr ' ' '#' `\""

 values[3]="\"`echo ${values[3]}`\""


 query=`echo $(values[@]) | tr ' #' ', ' `

 IFS=$oldIFS

 mysql -u $USER -p$PASS students <<EOF

INSERT INTO students VALUES($query);

EOF


done < $data

echo Wrote data into DB


-------------------------------