当前位置:   article > 正文

shell经典实例

shell经典实例

1 列目录树的shell
  1. #!/bin/sh
  2.   # dtree: Usage: dtree [any directory]
  3.   dir=${1:-.}
  4.   (cd $dir; pwd)
  5. find $dir -type d -print | sort -f | sed -e "s,^$1,," -e "/^$/d" -e "s,[^/]*/([^/]*)$,`----1," -e "s,[^/]*/,| ,g"

2 while中使用read (file是一个文件)

  1. cat file | while read line
  2. do
  3. echo $line
  4. echo " :: Please input any key(s):c"
  5. str4read=""
  6. while true
  7. do
  8. chr4read=`dd if=/dev/tty bs=1 count=1 2>/dev/null`
  9. str4read=$str4read$chr4read
  10. if [ "$chr4read" = "" ] ;then break; fi
  11. done
  12. echo " :: |$str4read|"
  13. done

3 将多个空格替换为字符

  1. sed 's/[ ][ ]*/ /g'
  2. 如果空格与tab共存时用
  3. sed -e 's/[[:space:]][[:space:]]*/ /g' filename

4用脚本实现分割文件

  1. #!/bin/bash
  2. if [ $# -ne 2 ]; then
  3. echo 'Usage: split file size(in bytes)'
  4. exit
  5. fi
  6. file=$1
  7. size=$2
  8. if [ ! -f $file ]; then
  9. echo "$file doesn't exist"
  10. exit
  11. fi
  12. #TODO: test if $size is a valid integer
  13. filesize=`/bin/ls -l $file | awk '{print $5}'`
  14. echo filesize: $filesize
  15. let pieces=$filesize/$size
  16. let remain=$filesize-$pieces*$size
  17. if [ $remain -gt 0 ]; then
  18. let pieces=$pieces+1
  19. fi
  20. echo pieces: $pieces
  21. i=0
  22. while [ $i -lt $pieces ];
  23. do
  24. echo split: $file.$i:
  25. dd if=$file of=$file.$i bs=$size count=1 skip=$i
  26. let i=$i+1
  27. done
  28. echo "#!/bin/bash" > merge
  29. echo "i=0" >> merge
  30. echo "while [ $i -lt $pieces ];" >> merge
  31. echo "do" >> merge
  32. echo " echo merge: $file.$i" >> merge
  33. echo " if [ ! -f $file.$i ]; then" >> merge
  34. echo " echo merge: $file.$i missed" >> merge
  35. echo " rm -f $file.merged" >> merge
  36. echo " exit" >> merge
  37. echo " fi" >> merge
  38. echo " dd if=$file.$i of=$file.merged bs=$size count=1 seek=$i" >> merge
  39. echo " let i=$i+1" >> merge
  40. echo "done" >> merge
  41. chmod u+x merge'

5得到上月未日期,格式为YYYYMMDD

  1. get_lastday_of_lastmonth()
  2. {
  3. yy=`date +%Y`
  4. mm=`date +%m-1|bc`
  5. [ $mm -lt 1 ] && mm=12;yy=`expr $yy - 1`
  6. aaa=`cal $mm $yy`
  7. dd=`echo $aaa|awk '{print $NF}'`
  8. echo $yy$mm$dd
  9. }
  10. print $NF的$NF是打印最后一个列。因为awk的内置变量NF是列的总数,而$NF就代表着最后一列

6 实现用backuptar命令来做目录备份

  1. 需要保持两个目录当中的文件以及属组关系不变。子目录结构不变,通过管道控制tar和backup命令,不需要中间的archive,(考虑到速度以及空间的关系)
  2. (cd /source && tar cf - .) |(cd /dest && tar zxfp -)
  3. 偶没有 backup 命令,但是 tar 用管道可以,
  4. tar -cf - dir1 | ( cd dir2; tar -xvf - )
  5. 搬移大法
  6. more aaa.sh
  7. #计算两个日期间有多少天
  8. #date1,date2:yyyymmdd
  9. #Usage:command date1 date2
  10. str=$1
  11. yy1=`echo $str|cut -c 1-4`
  12. mm1=`echo $str|cut -c 5-6`
  13. dd1=`echo $str|cut -c 7-8`
  14. str=$2
  15. yy2=`echo $str|cut -c 1-4`
  16. mm2=`echo $str|cut -c 5-6`
  17. dd2=`echo $str|cut -c 7-8`
  18. count_day=`expr $dd2 - $dd1`
  19. while [ $yy2 -ne $yy1 -o $mm2 -ne $mm1 ]
  20. do
  21. mm2=`expr $mm2 - 1`
  22. [ $mm2 -eq 0 ] && mm2=12 && yy2=`expr $yy2 - 1`
  23. aaa=`cal $mm2 $yy2`
  24. bbb=`echo $aaa|awk '{print $NF}'`
  25. count_day=`expr $count_day + $bbb`
  26. done
  27. echo $count_day

7 编写一个只允许用户执行telnetshell

  1. 为了监视用户网络操作行为,指定unxi主机给设备管理员登陆,然后用shell控制他。只可以使用telnet命令,其他一概不许,包括cd,ls等。就是一个用来远程登陆的管理平台。我对shell不熟,请指导。
  2. .profile中加入:
  3. read addr
  4. telnet $addr
  5. exit

8 判断文件的访问权限是不是600

  1. ls -l filename | awk '{ if($1 ~ "-rw-------") ..... }'
  2. ls -l filename | grep "^-rw------" -c
  3. #!/usr/bin/bash
  4. #showmod
  5. [ $# -eq 0 ] && { echo "Usage: $0 filelist ... "; exit ;}
  6. show()
  7. {
  8. { [ -d $1 ] && ls -ld $1 ; [ -f $1 ] && ls -la $1 ;} | awk '{
  9. umask=0
  10. umask_=""
  11. for(i=1;i<length($1);i++)
  12. {
  13. if(substr($1,i+1,1)=="r")
  14. umask+=4;
  15. if(substr($1,i+1,1)=="w")
  16. umask+=2;
  17. if(substr($1,i+1,1)=="x")
  18. umask+=1;
  19. if(i%3==0)
  20. {
  21. umask_=sprintf("%s%d",umask_,umask);
  22. umask=0;
  23. }
  24. }
  25. printf("%-20.20s: %-10.10s --> %s ",$9,$1,umask_);
  26. }';
  27. }
  28. for file_dir in $*
  29. do
  30. show $file_dir
  31. done

9 算青蛙的脚本

  1. maxcount=$1;
  2. count=1;
  3. if [ $# -eq 1 ]
  4. then
  5. while [ $count -le $maxcount ]
  6. do echo $count 只青蛙 $count 张嘴, `expr $count * 2`只眼睛,`expr $count * 4`条腿;
  7. count=`expr $count + 1`;
  8. done;
  9. else
  10. echo "usage: sendos count"
  11. fi

10 SHELL程序中实现‘按任意键继续’

 

在写一个SHELL程序,可是遇到了一个难题,在READ接受输入时,必须按回车键才能确认,而我需要只要按一个键就能得到用户的输入,无须按回车键!有什么好办法呢

  1. #!/bin/sh
  2. get_char()
  3. {
  4. SAVEDSTTY=`stty -g`
  5. stty -echo
  6. stty raw
  7. dd if=/dev/tty bs=1 count=1 2> /dev/null
  8. stty -raw
  9. stty echo
  10. stty $SAVEDSTTY
  11. }
  12. echo "Press any key to continue..."
  13. char=`get_char`
  14. 如果你的机器上不认stty raw那么把函数中两处出现的raw换成cbreak。

11 linux环境下启动时打开numlock

 

 想在系统启动时自动打开NumLock,可以在/etc/rc.d/rc.local中加入以下内容:

  1. for t in 1 2 3 4 5 6 7 8
  2.   do
  3.    setleds +num
  4.    $t>/dev/null
  5.   done

12 shell里如何限制输入的长度

 

举个例子,比如用户输入用户名时只能给他输入8个字符,如果超过了8个字符光标就停止在第八个字符那儿,不继续,一直等待回车只怕要自己来另写一个SHELL了。

 

我现在可以实现到如果输入超出的话光标就停在最后一个字符,但是对于那些输入小于规定位数的那些就没折了,举个例子,比如用户域最长不能超过8位,我输入了6位然后回车,就不会结束,一定要输入完8位按回车才可以结束

 

文件名: input.sh 用法:input.sh 限制的长度

 

例:input.sh 8 即限制输入8位。

  1. #!/bin/ksh
  2. # Program Name : input.sh
  3. trap '' 1 2 3 5 7 9 15 13
  4. getcon(){
  5. stty raw -echo
  6. conchar=`dd if=/dev/tty bs=1 count=1 2>/dev/null`
  7. stty sane
  8. echo "$conchar"
  9. }
  10. while
  11. i=0;clear >/dev/tty
  12. echo "

13 双机(多机)自动互备份方案

问 题:

  公司有两台LINUX服务器,每个服务器只有一个硬盘。所以备份的问题就显得特别重要。我们装有MySQL数据库。当然同时也要解决MySQL备份的问题。

目 的:

  host 机器最终所有备份都在其上留备份,ship机器保存host机器备份

方 法:

  通过shell脚本,打包相关要备份的文件。然后通过ftp操作下载,上载完成解决方案。

  两台机器root 通过crontab 让脚本在各自机器定时执行。

  建议host 每天早上3点执行。

  建议ship 每天早上6点执行。

注意点:

  两台服务器系统时间最好相差不要超过1小时。

  此脚本是每周礼拜6执行备份的。当然你也可以修改成每月或每天备份。

  当然也可以修改成一个增量备份脚本。

具体脚本:

以下为host机器脚本

  1. #//host机器脚本///
  2. #! /bin/sh
  3. HOST="abc.com"
  4. USER="backup_use" #ship机器backup_use用户
  5. PASSWORD="backup_use" #ship机器对应用户密码
  6. BACKUPDIR="/home/backup_use/ship" #host机器backup_use用户目录
  7. BACKUPDIR2="/home/backup_use/host" #host机器backup_use用户目录
  8. MYSQLPASS="abc" #ship 机器MySQL root 用户密码
  9. PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/nusphere/MySQL/bin
  10. DOW=`date +%a`
  11. DM=`date +%Y%b%d`
  12. FILE1=ship-virtual-$DM.tar.gz
  13. FILE2=ship-MySQLdata-$DM.tar.gz
  14. FILE3=ship-szeasy-$DM.tar.gz
  15. FILE4=ship-other-$DM.tar.gz
  16. #
  17. FIL1=$BACKUPDIR2/host-main-$DM.tar.gz
  18. FIL2=$BACKUPDIR2/host-MySQLdata-$DM.tar.gz
  19. FIL3=$BACKUPDIR2/host-other-$DM.tar.gz
  20. #
  21. DIRECTORIE1="/www /home/jjd" # 要备份的目录1
  22. DIRECTORIE2="/etc /var/named /usr/local/nusphere/apache/conf" # 要备份的目录2
  23. #
  24. if [ $DOW = "Sat" ]; then # 每个礼拜六完全备份
  25. tar -zcpf $FIL1 $DIRECTORIE1
  26. tar -zcpf $FIL3 $DIRECTORIE2
  27. MySQLdump --all-databases -q -uroot -p$MYSQLPASS |gzip > $FIL2
  28. ftp -i -n < $BACKUPDIR/$COMPUTER-MySQLdata-$DM.tar.gz
  29. fi

14 文件序列a1,a2,a3...a11,a12...a1000改成a0001,a0002...a1000?

  1. $cat test
  2. ls a* > tempfile1
  3. sed 's/a//' tempfile1 > tempfile2
  4. awk '{printf("mv a%s a%04s ", $0, $0)}' tempfile2 > tempfile3
  5. chmod 700 tempfile3
  6. ./tempfile3
  7. rm tempfile*
  8. $chmod test
  9. ----------------------------------------------------------------
  10. ls a*|awk '{
  11. num=substr($1,2,length($1)-1);
  12. printf "mv %s a%04d ",$1,num
  13. }'>rename.sh
  14. sh rename.sh
  15. ----------------------------------------------------------------
  16. for file in a*
  17. do
  18. newfile=`echo $file | awk '{printf "a%04d", substr($1, 2, length($1)-1)}'`
  19. mv $file $newfile
  20. done
  21. 给个不用awk的,效率会低一点
  22. ls -1 a*|while read j
  23. do
  24. num=`echo $j|cut -b 2-`
  25. num=`printf a%04s $num`
  26. mv $j $num
  27. done
  28. -----------------------------------------------------------------
  29. 稍微缩减一下:
  30. for file in a*
  31. do
  32. mv $file `echo $file|awk '{printf "a%04d", substr($1,2,length($1)-1)}'`
  33. done
  34. 如果a1,a2,a3...等文件是各自有不同的扩展名呢?就像a1.pxx,a2,baa,a3.tga...
  35. 这样是不是可以呢:
  36. for file in a*
  37. do
  38. nam=`echo $file|cut -d. -f1`
  39. exe=`echo $file|cut -d. -f2`
  40. mv $file `echo $nam|awk '{printf "a%04d", substr($1,2,length($1)-1)}'`.$exe
  41. done

15 禁止从一个IP登录的shell 

解决方案0

shell完全可以解决,如果有tcpwrapper的系统,可以直接加/etc/hosts.deny

解决方案1

/etc/profile里加一段shell就可以了(sco openserver)

这是我写的只要求本C段登陆的shell,改改就可以了.

  1. who=`who am i|awk '{print $1}'`
  2. myterm=`who am i|awk '{print substr($2,4,2)}'`
  3. if [ "x"$who = "xroot" ]
  4. then
  5. subnet=`finger|grep $myterm|awk '{print substr($8,1,8)}'`
  6. else
  7. subnet=`finger|grep $myterm|awk '{print substr($7,1,8)}'`
  8. fi
  9. test x$subnet != x && test x$who != xroot && test "x"$subnet != "x46.8.44." &&
  10. echo " Please login from local network " && exit

16 eval用法三例

  1. ## shell:/bin/sh ##
  2. #例一:
  3. #寻找符合条件的变量名,然后将该变量的值赋予另一变量
  4. v1=aaa
  5. v2=bbb
  6. c=1
  7. if [ $c -eq 1 ]
  8. then
  9. vname=v$c #找到符合条件的变量名为v1
  10. eval vvv="$"$vname ; echo vvv: $vvv #将变量v1的值赋予vvv,即,使vvv=aaa
  11. eval vvv='$'$vname ; echo vvv: $vvv #将变量v1的值赋予vvv,即,使vvv=aaa
  12. #eval vvv=$$vname ; echo vvv: $vvv #错误用法
  13. fi

  1. #例二:#以变量v1的值aaa作为变量名,将变量vaaa的值赋予这一新定义的变量aaa
  2. v1=aaa ; vaaa="This is aaa"
  3. #eval $v1=$vaaa ; echo aaa: $aaa #错误用法
  4. #eval $v1="$vaaa" ; echo aaa: $aaa #错误用法
  5. eval $v1='$vaaa' ; echo aaa: $aaa

  1. #例三:
  2. #以变量v1的值aaa作为变量名,并将变量名字串作为值赋予自身
  3. v1=aaa ; vaaa="This is aaa"
  4. eval $v1=$v1 ; echo aaa: $aaa #与例二的错误用法不同,这一用法是正确的
  5. eval $v1="$v1" ; echo aaa: $aaa #与例二的错误用法不同,这一用法是正确的
  6. #区别在于,例二中的vaaa的值中间有空格
  7. eval $v1='$v1' ; echo aaa: $aaa

17 改变UNIX终端颜色

a. echo"<ctrl-v><escape>[31m测试<ctrl-v><escape>[37m"

echo "^[[Xm YourChar"

(X=30,31...36?)

请注意这个转义系列的敲法是,<ctrl-v><escape>[30m

echo "<ctrl-v><escape>[<代码>;<代码>;<代码>m"

注意,语句必须要在""之间,属性分隔符为";",如闪烁红色

echo "<ctrl-v><escape>[31;5m测试"

 

b. 前景 背景 颜色

 

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

30 40 黑色

31 41 紅色

32 42 綠色

33 43 黃色

34 44 藍色

35 45 紫紅色

36 46 青藍色

37 47 白色

代码 意义

 

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

0 OFF

1 高亮显示

4 underline

5 闪烁

7 反白显示

8 不可见

c. 产生颜色(黑色背景加绿色前景色)

sco: setcolor red; echo "abcd"; setcolorwhite

linux/BSD: /usr/bin/echo -e"

18 恢复缺省bash提示符

export PS1="[u@h W]$ "

保险起见,在~/.bashrc~/.bash_profile

19 grep/awk/sed的多条件查询

  1. # cat gt
  2. one two three
  3. four five six
  4. one two
  5. one seven three
  6. # grep one three gt
  7. grep: three: No such file or directory
  8. gt:one two three
  9. gt:one two
  10. gt:one seven three
  11. 截取同时出现one和three的行,结果应该是:
  12. one two three
  13. one seven three
  14. a. 用grep
  15. cat gt | grep one | grep three
  16. b. 用awk
  17. awk '/one/&&/three/' gt
  18. c. 用sed
  19. sed -ne '/one/{/three/p}' gt
完!!!!
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/250347
推荐阅读
相关标签
  

闽ICP备14008679号