shell递归一例
用递归写的一个光标旋转的小脚本 [root@maint-app-108 recurse]# cat cursor.sh
1 2 3 4 5 6 7 8 9 10 11 12 |
cursor () { #{{{ message="$1" count="$2" for item in "|" "/" "-" "\\" do printf "\r${item} ${message} $count" usleep 50000 done cursor waiting $((count+1)) } cursor waiting 1 |
[root@maint-app-108 cursor]# 用递归做这种无限循环最后脚本会退出,下面这个while :不会退出。 [root@maint-app-108 cursor]# cat cursor.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 |
cursor () { #{{{ message="$1" for item in "|" "/" "-" "\\" do printf "\r${item} ${message}" usleep 50000 done } while : do cursor waiting done |
数字的格式化打印
数字的格式化打印 有人问我一个产生”01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20″这样一种字符串的方法,当时我随意的写了一个
1 2 3 4 5 6 7 8 9 10 |
for ((x=1;x<=20;x++)) do if [ ${#x} -eq 1 ]; then echo -n "0$x " else echo -n "$x " fi done 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 |
我当时觉得有点土,之后人家问了如果打印的结果是从0到100怎么办呢? 因为最近买了本python的书,在复习pyhon的基础知识,恰好在看格式胡print的时候看到print%0是用0替换空格来占位,当时看书的时候感到有点怪,不知道数字前面加0有什么用,所以还有点印象。 所以像下面的python语句那么写好看多了。
1 2 3 4 5 6 7 8 |
Python 2.6.2 (r262:71600, Jul 2 2009, 16:30:16) [GCC 3.4.4 20050721 (Red Hat 3.4.4-2)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> for x in range(20): print "%02d" %x, ... 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 >>> |
之前printf用的很少,但是也清楚shell的格式化打印也是C的printf like的,今天到公司后试了下printf,确实可以work。
1 2 |
for ((x=1;x<=20;x++)); do printf "%02d " $x; done 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 |
bash 4的新功能
1 2 3 4 5 6 7 8 |
[4aiur@FreeBSD ~]$ bash --version GNU bash, version 4.0.33(0)-release (i386-portbld-freebsd8.0) Copyright (C) 2009 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gp... This is free software; you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. [4aiur@FreeBSD ~]$ echo {01..10} 01 02 03 04 05 06 07 08 09 10 |
C
1 2 3 4 5 6 7 8 |
#include <stdio.h> int main(void){ int x; for (x = 0; x <=20 ; x++) { printf("%02d\n", x); } return 0; } |
shell
1 2 |
seq -w 1 20 seq -f '%02g' 1 20 |
统计squid下分频道cache文件总量
统计squid下分频道cache文件总量 今天有个朋友问我怎么查看squid下分频道的cache文件总量 想了想用下面的命令实现起来方便又快捷,^_^
1 2 |
strings swap.state | \ awk -F"/" /^http/'{if ($3 in host) host[$3]++; else host[$3]=1}END{for (item in host) print item,host[item] | "sort -k2 -nr"}' |
同一个url是否压缩和编码的区别的话,会计算成多个。
rsync模式匹配
rsync模式匹配 今天有一个同步数据的小问题,需要把一些符合特定日期的文件保存到另外一个目录,使用shell也很容易实现,之前没用rsync做过,今天顺便研究了一下rsync的实现方式,rsync是使用排除和取消排除的方法(诡异)。 为了实现递归,先写一个不排除的规则–include=”*/” 再写一个希望保存文件的规则–include=”2009022[78]“ 最后写上排除所有的规则–exclude=”*” 组合以上3个选项实现了对特定文件的同步。
1 2 3 4 5 6 7 8 9 10 11 |
rsync -aruv --include="*/" --include="*2009022[78]*" --include="*2009030[12]*" --exclude="*" /source /destination # aruv比较常用 -a, --archive archive mode, equivalent to -rlptgoD -r, --recursive recurse into directories -u, --update update only (don't overwrite newer files) -v, --verbose increase verbosity |
设置JAVA时区
设置JAVA时区 RadHat上面运JDK,其获取时区的配置文件是/etc/sysconfig/clock。
1 2 3 4 |
# cat /etc/sysconfig/clock ZONE="Asia/Shanghai" UTC=false ARC=false |
昨天遇到了一个很怪异的现象。 现象是java程序输出的时间和系统时间相差了13个小时,与http://www.javaeye.com/topic/173077现象相同。 使用data命令查看系统时区是CST,但是执行java程序输出的取是”America/New_York” 使用timeconfig重新设置系统时区后,java获取到的时区恢复正常。 看了下timeconfig的manual,发现这个命令配置两个文件,分别是/etc/sysconfig/clock、/etc/localtime。 data命令输出的时区与java时区有差异就是因为它们读取的配置文件不同。
排除Apache access log乱序日志
排除Apache access log乱序日志 由于Apache的访问日志时间记录的是访问开始时间,所以会有时间不是顺序排列的情况产生。 由于有一个特殊需求,需要把乱序的日志排除掉,今天写了个小脚本处理了一下。 转换Apache accesslog时间为时间戳,进行处理 把乱序日志打印到了badlog文件中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
[root@4Aiur ~]# cat foo 58.59.23.18 - - [26/Nov/2008:11:04:05 +0800] "GET /test.html HTTP/1.1" 200 8228 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)" 58.59.23.18 - - [26/Nov/2008:11:03:05 +0800] "GET /test.html HTTP/1.1" 200 8228 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)" 58.59.23.18 - - [26/Nov/2008:11:05:05 +0800] "GET /test.html HTTP/1.1" 200 8228 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)" [root@4Aiur ~]# cat foo.awk #!/bin/awk function date2unixstamp(date) { sub(/\[/,"",date) split(date,array,/[/:]/) if (array[2]=="Nov") array[2]="11" else if (array[2]=="Jan") array[2]="01" else if (array[2]=="Feb") array[2]="02" else if (array[2]=="Mar") array[2]="03" else if (array[2]=="Apr") array[2]="04" else if (array[2]=="May") array[2]="05" else if (array[2]=="Jun") array[2]="06" else if (array[2]=="Jul") array[2]="07" else if (array[2]=="Aug") array[2]="08" else if (array[2]=="Sep") array[2]="09" else if (array[2]=="Oct") array[2]="10" #else if (array[2]=="Nov") array[2]="11" else if (array[2]=="Dec") array[2]="12" Time=array[3]" "array[2]" "array[1]" "array[4]" "array[5]" "array[6]" "array[7] Timestamp=mktime(Time) return Timestamp } { date=$4 date2unixstamp(date) #print date,Timestamp,temp,Time if (Timestamp<temp) print $0 > "badlog" else { print $0 > "accesslog" temp=Timestamp } } [root@4Aiur ~]# awk -f foo.awk foo [root@4Aiur ~]# cat accesslog 58.59.23.18 - - [26/Nov/2008:11:04:05 +0800] "GET /test.html HTTP/1.1" 200 8228 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)" 58.59.23.18 - - [26/Nov/2008:11:05:05 +0800] "GET /test.html HTTP/1.1" 200 8228 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)" [root@4Aiur ~]# cat badlog 58.59.23.18 - - [26/Nov/2008:11:03:05 +0800] "GET /test.html HTTP/1.1" 200 8228 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)" |
带特殊字符文件的删除方法
带特殊字符文件的删除方法 list文件列表的时候发现有个”?”文件,直接删除?是删不掉的。
1 2 3 4 5 6 7 8 9 10 11 12 |
~]# ll total 75040 -rw-r--r-- 1 root root 0 Nov 7 14:46 ? # 使用cat -A 查看这个文件是带有特殊字符的文件 ~]# ll | cat -A total 75040$ -rw-r--r-- 1 root root 0 Nov 7 14:46 M-<$ ~]# ls | head -1 ¼ [ # 使用下面的方法将其删除 # ls | head -1 | xargs rm |
磁盘空间满故障排除
磁盘空间满故障排除 磁盘空间满一般情况下使用du可以快速定位到那个目录占用了大量的磁盘空间。 这里主要讲两个使用du无法查看的情况。 现象/mnt分区磁盘使用率达到100%
1 2 3 4 5 6 7 8 9 |
# df -h Filesystem Size Used Avail Use% Mounted on /dev/sda2 97G 1.5G 90G 2% / /dev/sda1 190M 12M 169M 7% /boot none 2.0G 0 2.0G 0% /dev/shm /dev/sda3 97G 6.3G 85G 7% /usr /dev/sda6 191G 408M 181G 1% /var tmpfs 300M 300M 0 100% /mnt /dev/loop0 190M 106M 74M 60% /mnt/foo |
进入/mnt目录使用du查看/mnt下的磁盘使用率
1 2 3 4 |
# cd /mnt # du -sh * 101M bar 101M foo |
troubleshooting 解决思路 有两种情况会干扰du查看磁盘空间使用率 删除的文件使用du无法查看 磁盘分区的某一个目录挂载了另外一个分区时,du查看到的磁盘空间为挂载分区后的目录空间。 在了解上面两种情况后,解决这个问题会比较简单。 在生产环境中某一程序的日志文件被删除这一情况发生的几率会大些。 故障排除
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# 1、查找被删除文件 # 被删除文件,在写程序未退出的情况下,被删除文件同样会占用磁盘空间。 # lsof -n | head -1 COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME # lsof -n /mnt | grep deleted foo.sh 32593 root 1w REG 0,18 104538112 981982 /mnt/test.out (deleted) foo.sh 32593 root 2w REG 0,18 104538112 981982 /mnt/test.out (deleted) # 杀掉写文件的程序,磁盘空间会自然释放 # kill 32593 # df -h /mnt Filesystem Size Used Avail Use% Mounted on tmpfs 300M 201M 100M 67% /mnt # 2、查看分区挂载情况 # 因为分区的目录下挂载有其它分区,被挂载分区的目录本身容量无法被查看,所以umount掉挂载分区的目录后将可正常查看此目录下文件所占用的容量。 # cd /mnt # du -sh * 101M bar 101M foo #此容量为目录挂载分区后的新分区容量 # umount /mnt/foo # du -sh * 21M bar 201M foo #此容量为目录所占用磁盘满分区的容量 |
测试环境搭建过程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# 挂载300M的内存tmpfs到/mnt目录 # mount -t tmpfs -o size=300m tmpfs /mnt # cd /mnt && mkdir foo bar # 先生成两个文件到foo bar下,占用一定的磁盘空间 # dd if=/dev/zero of=foo/file.out bs=1M count=100 # dd if=/dev/zero of=bar/file.out bs=1M count=100 # 查看磁盘当时的使用情况 # df -h Filesystem Size Used Avail Use% Mounted on /dev/sda2 97G 1.5G 90G 2% / /dev/sda1 190M 12M 169M 7% /boot none 2.0G 0 2.0G 0% /dev/shm /dev/sda3 97G 6.3G 85G 7% /usr /dev/sda6 191G 408M 181G 1% /var tmpfs 300M 201M 100M 67% /mnt # 使用空文件建立一个文件系统 # cd /root/shell # 生成200M的空文件 # dd if=/dev/zero of=foo.img bs=1M count=200 # 建立一个loop devices # losetup /dev/loop0 foo.img # 在loop devices上创建一个ext3文件系统 # mke2fs -j -c /dev/loop0 200000 # 使用/mnt/foo目录挂载/dev/loop0 # mount -t ext3 /dev/loop0 /mnt/foo # 在/mnt/foo/目录产生一个测试文件file.out # dd if=/dev/zero of=/mnt/foo/file.out bs=1M count=100 # df -h Filesystem Size Used Avail Use% Mounted on /dev/sda2 97G 1.5G 90G 2% / /dev/sda1 190M 12M 169M 7% /boot none 2.0G 0 2.0G 0% /dev/shm /dev/sda3 97G 6.3G 85G 7% /usr /dev/sda6 191G 408M 181G 1% /var tmpfs 300M 201M 100M 67% /mnt /dev/loop0 190M 106M 74M 60% /mnt/foo # /mnt/foo目录挂载方式伪装已经完成 # 删除文件伪装 # 编写一个死循环产生测试文件 # cat /root/shell/foo.sh #!/bin/bash # set -x foo=$(seq 1 500) while : do echo $foo done # 生成一个测试文件test.out占用/mnt目录的空间 # nohup /root/shell/foo.sh >/mnt/test.out 2>&1 & # 删除测试文件 # \rm /mnt/test.out # df -h Filesystem Size Used Avail Use% Mounted on /dev/sda2 97G 1.5G 90G 2% / /dev/sda1 190M 12M 169M 7% /boot none 2.0G 0 2.0G 0% /dev/shm /dev/sda3 97G 6.3G 85G 7% /usr /dev/sda6 191G 408M 181G 1% /var tmpfs 300M 300M 0 100% /mnt /dev/loop0 190M 106M 74M 60% /mnt/foo |
自动修改crontab配置
自动修改crontab配置 方法1:使用crontab -l把crontab内容导出到文件中,使用编辑器或脚本修改导出的文件,之后使用新的配置文件覆盖掉现有的配置。
1 2 |
[4Aur@4Aiur ~]$ crontab -l > cron[4Aur@4Aiur ~]$ sed -i 's/ls/dir/' cron [4Aur@4Aiur ~]$ crontab cron |
方法2:使用here文档的方式更新crontab的配置。
1 2 3 4 5 6 7 8 9 10 11 |
[4Aur@4Aiur ~]$ crontab -l0 * * * * ls [4Aur@4Aiur ~]$ sh cron_modify.sh [4Aur@4Aiur ~]$ crontab -l 0 * * * * dir [4Aur@4Aiur ~]$ cat cron_modify.sh crontab -e <<\EOF &>/dev/null :%s/ls/dir/g :wq EOF [4Aur@4Aiur ~]$ |
被用于保留(reserved meanings)的退出状态码
Exit Codes With Special Meanings Reserved Exit Codes Exit Code Number Meaning Example Comments 1 Catchall for general errors let "var1 = 1/0" Miscellaneous errors, such as "divide by zero" 2 Misuse of shell builtins (according to Bash documentation) ? Seldom seen, usually defaults to exit code 1 126 Command invoked cannot execute ? […]