最近一直在研究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
-------------------------------