shell 编程

Bash脚本比我们想象中的都要强大,通过Bash脚本,大多数任务都可以让你在无任何其它语言或第三方依赖的安装环境下,快速写出脚本程序。 

在Bash中调用外部进程是非常繁琐的,过度调用会导致明显的减速,通过内置方法编写的脚本和程序会更快,所需的依赖也会更少,并且帮助你更好的理解编程语言。

有位澳大利亚工程师在Github上开源了一本书——《pure bash bible》

目前,这本书已经在Github上获得 13148 个Star,905 个Fork(Github地址:https://github.com/dylanaraps/pure-bash-bible) 

本书收集汇总了编写 bash 脚本经常会使用到的一些代码片段,无论是常见和不太常见的方法都可以在这书里找到,通过书中的代码片段,可以删除脚本中的依赖项,并且在大多数情况下可以让程序运行的更快。 

书中依照字符串、数组、正则表达式、文件处理、变量等脚本程序的常用功能进行分类,每个分类下都提供了具体 bash 代码实现。

 

http://jackyrong.iteye.com/blog/1378736

 

1  假如知道一个应用运行,想知道其进程id,可以用: 
   pgrep xxxx获得其进程id 
  再通过 
   cat /proc/进程id号/environ 
获得其环境变量 


2  获得字符串长度 
   var=1233333 
    length=${#var} 

3 判断当前脚本是否超级管理员执行 
    if [ $UID -ne 0]; then 
    ....... 

  root用户的uid为0 

4 sort排序 
    sork -nrk 1 data.txt  //按第1列逆序排列 
  其中-k 指定按哪个键进行排序,-r说明是逆序排列,-n表示按数字排序 
  sort -k 2 data.txt  按data.txt的第2列排序 

5 uniq,消除重复的内容 
     sort data.txt |uniq 
    输出data.txt中不重复的内容 
  找出文件中重复的行 
      sort data.txt |uniq -d 
6 根据扩展名切分文件名,比如从sample.jpg中提取文件名 
     file_jpg="sample.jpg" 
      name=${file_jpg%.*} 
      echo $name  //输出sample 

    extension=${file_jpg#*.} 
    输出jpg 

   其中,${var%.*}作用为从右到左,删除位于%右侧的字符 ${var%%.*},则右向左匹配最长的字符 
   var=asd.sdsdf.fdfdf.txt 
   echo ${var%.*} 输出 asd.sdsdf.fdfdf 
   echo ${var%%.*} 输出asd 
   而#*.则是从左到右,删除#找到的通配符的左测的字符,##则是找最长的 
   则echo ${var#*.}输出sdsdf.fdfdf.txt  echo ${var##*.} 输出 txt 

7 pushd和popd 
    这两个命令可以将目录压入栈中,而不用复制粘贴 
   pushd /var/www 
   则栈中压入了/var/www ,再压入 
    pushd /usr/src 
   再dirs 
   当要切换到某个目录时,则pushd +3 //则切换到目录第3层,从0开始编号 
  移除  popd 

8 grep检索 
    1) 正则表达式  grep -E "[a-z]+" // 使用E选项 
    2) 递归检索文件 
         grep "xxxx" . -R -n  //当前目录下多级递归检索目录 
     3)grep -i "HELLO" -i选项,忽略大小写 
   
     4)grep 搜索中包括和排除某些文件 
        grep 'test" . -r --include *.{c,txt}  只搜索后缀为c,txt的文件 
       不包括: 
        grep "test" . -r --exclude "readme" 

9 sed 
    可以替换给定文本中的字符串 
   sed 'xxxxxxx'  file 
   移除空白行 
      sed '/^$d' file 

10 AWK 
   1)AWK 'BEGIN 语句块'  pattern 语句块   end  语句块’ 
    先执行begin语句块中的语句,然后从文件或者stdin中读取一行,再执行pattern,重复这个过程,直到 
文件被完全读完;当读到输入流未尾时,执行end语句块结束 
    echo -e "line1\nline2" |awk 'BEGIN {print "start"} {print} end {print "end"}}' 
   则输出 Start 
          line1 
          line2 
          end 
   2)打印每一行的第2个字段和第3个字段 
      awk '{print $2,$3}' file 
    3) 统计文件中的行数 
        awk 'end {print NR}' file 


11 wget -c url //断点续传 
   限制速度: wget --limit-rate 20k http://xxxx/xxxx.iso 
  curl -C url  //断点续传 
   curl http://xxxxx/index.html -O 将输出写到同名的文件中去 
12 使用curl查找网页上的无效链接的bash脚本 
    f [ $# -eq 2 ]; 
then 
echo -e "$Usage $0 URL\n" 
exit -1; 
fi 


echo Broken links: 

mkdir /tmp/$$.lynx 


cd /tmp/$$.lynx 

lynx -traversal $1 > /dev/null 
count=0; 

sort -u reject.dat > links.txt 

while read link; 
do 
output=`curl -I $link -s | grep "HTTP/.*OK"`; 
if [[ -z $output ]]; 
then 
echo $link; 
let count++ 
fi 

done < links.txt 

[ $count -eq 0 ] && echo No broken links found. 


  首先lynx -traversal url会在工作目录下生成数个文件,其中包括reject.dat,这个文件 
中保存网站的所有链接,sort -u用来建立不重复的列表,每次循环则用curl 去检测HTTP 头部 

13  tar的几个用法 
   1)添加文件 
     tar -rvf xxx.tar abc.txt 
  2) 列出其中内容 
     tar -tf aaa.tar 
  3)只解压缩指定的文件 
       tar -xf aaa.tar file1 file3 
  4)删除tar中的某些文件 
    tar --delete --file xxx.tar 要删除的文件 

14 查看磁盘空间 
    du -h  xxx.txt 
    du -c -h  xxxx(目录名) 

15 列出1小时内占用CPU最多的10个进程 
   #!/bin/bash 
#Name: pcpu_usage.sh 
#Description: Script to calculate cpu usage by processes for 1 hour 

SECS=3600 
#Change the SECS to custom seconds 

STEPS=$(( $SECS / 60 )) 

echo Watching CPU usage... ; 

for((i=0;i<STEPS;i++)) 
do 
ps -eo comm,pcpu | tail -n +2 >> /tmp/cpu_usage.$$ 
sleep 60 
done 

echo 
echo CPU eaters : 

cat /tmp/cpu_usage.$$ | \ 
awk ' 
{ process[$1]+=$2; } 
END{ 
for(i in process) 
{ 
print i, process[i] ; 
} 

   }' | sort -nrk 2 | head | cut -d" " -f1 

   其中:ps -eo comm,pcpu | tail -n +2 >> /tmp/cpu_usage.$$的tail -n +2 去掉输出的头部command 和CPU 
cpu_usage.$$中的$$表示当前脚本进程的id. 


16  编写一个检测入侵检测的脚本 
#!/bin/bash 
#Filename: intruder_detect.sh 
#Description: Intruder reporting tool with auth.log input 
AUTHLOG=/var/log.auth.log 

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)" 

forip in $ip_list; 
do 
  grep $ip $LOG > /tmp/temp.$$.log 


foruser 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 
    letucount++; 


    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 
   其中是默认以/var/log/auth.log来进行检验,检验得出登陆失败,尝试次数,IP地址,时间范围的用户 
   

17 找出系统用户的活跃活动时段 
   #!/bin/bash 
#Filename: active_users.sh 
#Description: Reporting tool to find out active users 
log=/var/log/wtmp 
if [[ -n $1 ]]; 
then 
log=$1 
fi 
printf "%-4s %-10s %-10s %-6s %-8s\n" "Rank" "User" "Start" "Logins" 
"Usage hours" 
last -f $log | head -n -2 > /tmp/ulog.$$ 
cat /tmp/ulog.$$ | cut -d' ' -f1 | sort | uniq> /tmp/users.$$ 
( 
while read user; 
do 
grep ^$user /tmp/ulog.$$ > /tmp/user.$$ 
seconds=0 
while read t 
do 
   s=$(date -d $t +%s 2> /dev/null) 
let seconds=seconds+s 
done< <(cat /tmp/user.$$ | awk '{ print $NF }' | tr -d ')(') 
firstlog=$(tail -n 1 /tmp/user.$$ | awk '{ print $5,$6 }') 
nlogins=$(cat /tmp/user.$$ | wc -l) 
hours=$(echo "$seconds / 60.0" | bc) 
printf "%-10s %-10s %-6s %-8s\n" $user "$firstlog" $nlogins $hours 
done< /tmp/users.$$ 
) | sort -nrk 4 | awk '{ printf("%-4s %s\n", NR, $0) }' 
rm /tmp/users.$$ /tmp/user.$$ /tmp/ulog.$$ 


18 tr 
   tr option  set1 set2 
    将来自stdin的输入字符从set1映射到set2,比如将输入字符由大写转换为小写 
   $echo "HELLO" |tr 'A-Z','a-z' 
  tr  删除字符 
    echo "heelo  1234 " |tr -d '0-9'  //将其中的数字删除并打印出来 

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

对文件某列求和:

-F,用,号分隔,求第3行的和

awk -F,  '{sum += $3};END {print sum}' test

 

posted @ 2015-04-24 17:26  milkty  阅读(232)  评论(0)    收藏  举报