bash代码:
#!/bin/bash MySQLSTARTUP="/data/3306/mysql" DbProcessCount=`ps -ef|grep mysql|grep -v grep|wc -l` DbPortCount=`netstat -lnt|grep 3306|wc -l` if [ $DbProcessCount -eq 2 ] && [ $DbPortCount -eq 1 ] then echo "mysql is running! " else $MySQLSTARTUP start >/tmp/mysql.log sleep 20; if [ $DbProcessCount -ne 2 ] || [ $DbPortCount -ne 1 ] then killall mysqld >/dev/null 2>&1 sleep 5 killall mysqld >/dev/null 2>&1 sleep 5 [ $DbPortCount -eq 0 ] && $MySQLSTARTUP start >>/tmp/mysql.log [ $? -eq 0 ] && echo "mysql is started" fi mail -s "mysql restarted" [email protected] < /tmp/mysql.logfi
2) 通过连接mysql 执行命令来判断
bash代码:
#!/bin/bash MySQLSTARTUP="/data/3306/mysql" mysql -uroot -p'oldboy' -S /data/3306/mysql.sock -e "select version();" >/dev/null 2>&1 if [ $? -eq 0 ] then echo "mysql is running! " else $MySQLSTARTUP start >/tmp/mysql.log sleep 10; mysql -uroot -p'oldboy' -S /data/3306/mysql.sock -e "select version();" >/dev/null 2>&1 if [ $? -ne 0 ] then killall mysqld >/dev/null 2>&1 killall mysqld >/dev/null 2>&1 sleep 10 $MySQLSTARTUP start >>/tmp/mysql.log fi mail -s "mysql restarted" [email protected] < /tmp/mysql.log fi
3) 较专业的写法:
bash代码:
#!/bin/bash MYUSER=root MYPASS="" MYSOCK=/data/3306/mysql.sock MySQL_STARTUP="/data/3306/mysql" LOG_PATH=/tmp LOG_FILE=${LOG_PATH}/mysqllogs_`date +%F`.log MYSQL_PATH=/usr/local/mysql/bin MYSQL_CMD="$MYSQL_PATH/mysql -u$MYUSER -p$MYPASS -S $MYSOCK" $MYSQL_CMD -e "select version();" >/dev/null 2>&1 if [ $? -eq 0 ] then echo "MySQL is running! " exit 0 else $MySQL_STARTUP start >$LOG_FILE sleep 5; $MYSQL_CMD -e "select version();" >/dev/null 2>&1 if [ $? -ne 0 ] then for num in `seq 5` do killall mysqld >/dev/null 2>&1 [ $? -ne 0 ] && break; sleep 1 done $MySQL_STARTUP start >>$LOG_FILE fi $MYSQL_CMD -e "select version();" >/dev/null 2>&1 && Status="restarted" || Status="unknown" mail -s "MySQL status is $Status" @qq.com < $LOG_FILE fi exit
例3 监控apache
1) 对端口、进程和url同时监测。
bash代码:
#!/bin/bash . /etc/init.d/functions LOG_FILE=/tmp/httpd.log apachectl="/application/apache/bin/apachectl"HTTPPORTNUM=`netstat -lnt|grep 80|grep -v grep|wc -l` HTTPPRONUM=`ps -ef|grep http|grep -v grep|wc -l`wget --quiet --spider http://10.0.0.179:8000 && RETVAL=$? [ ! -f $LOG_FILE ] && touch $LOG_FILE if [ "$RETVAL" != "0" -o "$HTTPPORTNUM" -lt "1" -o "$HTTPPRONUM" \< "1" ] ;then action "httpd is not running" /bin/false echo -e "httpd is not running\n" >$LOG_FILE echo "Preparing start apache..." for num in `seq 10` do killall httpd >/dev/null 2>&1 [ $? -ne 0 ] && { echo "httpd is killed" >$LOG_FILE break; } sleep 2 done $apachectl start >/dev/null 2>&1 && Status="started" || Status="unknown" [ "$Status" = "started" ] && action "httpd is started" /bin/true||\ action "httpd is started" /bin/false mail -s "`uname -n`'s httpd status is $Status" [email protected] <$LOG_FILE exit else action "httpd is running" /bin/true exit 0 fi
2) 使用nmap检测
bash代码:
#!/bin/bash ip_add="$1" port="$2" print_usage(){ echo -e "$0 ip port" exit 1 } #judge para num if [ $# -ne 2 ] then print_usage fi PORT_COUNT=`nmap $ip_add -p $port|grep open|wc -l` #echo -e "\n" |telnet $ip_add $port||grep Connected #echo -e "\n"|telnet 10.0.0.179 8000|grep Connected [[ $PORT_COUNT -ge 1 ]] && echo "$ip_add $port is ok." || echo "$ip_add $port is unknown."
No. 文件安全与权限 . umask 决定了新建文件的权限 . 软链接(符号链接) ln -s source_path target_path No. find和xargs . find pathname -options [-print -exec -ok] 其中exec参数的命令格式: 'command-' {} \; 注意必须包含【{} \;】 -perm 按权限来查找 ex. find . -perm -print -mtime 按修改时间来查找 ex. find / -mtime - -print 更改时间5天以内 find / -mtime + -print 更改时间5天以前 . xargs与-exec和-ok类似,但是限制更少,也更快 3种参数的命令:find . -name "*.c" -exec wc -l {} \; find . -name "*.c" -ok wc -l {} \; 每次执行命令前有提示 find . -name "*.c" | xargs wc -l No. 后台执行命令 . [crontab] [at] [&] [nohup]四种 No. 文件名置换 . 列出隐藏文件 ex. ls .* No. shell输入与输出 . echo输出时加上 -n 参数不换行, ex. echo -n "aaaa" . tee 命令可以同时输出到屏幕和文件中 ex. ls | tee file.out . 标准输入 标准输出 标准错误 . 将标准输出和标准错误输入到一个文件 ex. command >file.>& No. 命令执行顺序 . 命令1 && 命令2 命令1执行成功后才会执行命令2 . 命令1 || 命令2 命令1执行失败后才会执行命令2 No. 正则表达式 . 正则表达式元字符及含义 ^ 只匹配行首 $ 只匹配行尾 * 匹配0次或多次 [] 匹配[]内字符 \ 转义符 . 匹配任意一个字符 pattern\{n\} 匹配pattern出现的次数,n次 pattern\{n, \} 同上,最少n次 pattern\{n, m\} 同上,次数在n与m之间 No. grep . grep 主要选项及其含义 -c 只输出匹配行的行数 -i 不区分大小写 -h 查询多文件时不显示文件名 -l 查询多文件时只输出包含匹配字符的文件名 -n 显示匹配行及行号 -s 不显示不存在或无匹配文本的错误信息 -v 显示不包含匹配文本的所有行 . 查询空行 grep '^$' filename . 类名及等价的正则表达式 [[:upper:]] = [A-Z] [[:lower:]] = [a-z] [[:digit:]] = [-] [[:alnum:]] = [-9a-zA-Z] [[:space:]] = 空格或tab键 [[:alpha:]] = [a-zA-Z] No. AWK # awk的主要作用在于将文本分成各个区域,便于分别进行处理 . awk -F指定分隔符,-f指定awk脚本 ex. awk -F: 'commands' input-file(s) ex. awk -f awk-script input-file(s) . awk 分隔出的域用$,$...$n来表示,其中$0表示所有域 . awk 条件操作符 <, <=, >=, ==, != ~ 匹配正则表达式 !~ 不匹配正则表达式 . awk 内置变量 ARGC 命令行参数个数 ARGV 命令行参数排列 ENVIRON 支持队列中系统环境变量的使用 FILENAME awk浏览的文件名 FNR 浏览文件的记录数 FS 设置输入域分隔符,等价于命令行-F选项 NF 记录的域个数 NR 已读的记录数 OFS 输出域分隔符 ORS 输出记录分隔符 RS 控制记录分隔符 ex. awk '{print NF,NR,$0} END{print FILENAME}' input-file . awk 字符串函数 gsub, index, length, match, split, sprint, sub, substr, substr . awk 中的printf函数可以控制格式化输出 . awk 的循环结构 For (element in array) print array[element] No. sed # sed的主要作用在于过滤和查找文本中的特定内容 . sed 命令格式: sed [options] sed-command input-file sed [options] -f sed-script input-file No. 合并和分隔文件 . sort, uniq, join, cut, paste, split No. tr的用法 . 去除oops.txt中的重复字符 tr -s "[a-z]" < oops.txt . 去除oops.txt中的空行 tr -s "[\n]" < oops.txt . oops.txt中小写转大写 tr -s "[a-z]" "[A-Z]" < oops.txt No. 登录环境 . /etc/passwd 保存所有账号的基本信息(不包括密码) . /etc/profile 基本的配置信息,登录时读取此文件 . $HOME/*profile 各个用户的profile文件,会覆盖系统的profile文件 4. $HOME/*logout logout(键入命令exit时)是执行的脚本 No.014 环境和shell变量 1. shell变量的设置方式 Variable-name=value 设置实际值到variable-name Variable-name+value 如果设置了variable-name,则重设其值 Variable-name:?value 如果未设置variable-name,显示未定义用户错误信息 Variable-name?value 如果未设置variable-name,显示系统错误信息 Variable-name:=value 如果未设置variable-name,设置其值 Variable-name:-value 如果未设置variable-name,就用value,但是不设置variable-name 2. 设置只读变量 readonly variable-name 3. export variable-name 可以将变量导入到子shell中 4. shell脚本的参数 $0表示脚本名字,$1表示第一个参数......$9表示第九个参数 5. 特定shell变量 $# 参数个数 $* 用一个字符串显示所有参数 $$ 脚本运行的当前进程ID $! 后台运行的最后一个进程的进程ID $@ 与$*相同,每个参数作为独立的字符串 $- 显示shell的当前选项,与set命令相同 $? 显示shell命令的退出状态,0表示无错误,其他表示有错 No.015 引号 1. 双引号("") 其中引用的变量会替换为变量值。比如: [wangyb@localhost bash]$ STR="Hello world" [wangyb@localhost bash]$ echo "$STR" Hello world 2. 单引号('') 忽略变量和其他特殊字符,单引号内任何内容都当成字符串显示。比如: [wangyb@localhost bash]$ STR="Hello world" [wangyb@localhost bash]$ echo '$STR' $STR 3. 单引号和双引号同时使用时,谁在外面谁起作用。比如 [wangyb@localhost bash]$ echo "'$STR'" 'Hello world' [wangyb@localhost bash]$ echo '"$STR"' "$STR" 4. 反引号(``) 反引号中的内容被当做命令来执行。比如 [wangyb@localhost bash]$ VAR=`date` [wangyb@localhos bash]$ echo $VAR Thu Dec 22 22:08:07 JST 2011 5. 转义符(\) No.016 Shell脚本介绍 1. 脚本的第一行一般以 #!/bin/bash 开始 2. 给脚本加入执行权限后就可以运行脚本了 #No.017 条件测试 1. 测试语法 test condition 或者 [ condition ] 使用方括号是注意在condition两边加上空格 2. 文件状态测试 -d 目录 -s 文件长度大于0 -f 正规文件 -w 可写 -L 符号连接 -u 文件有suid位设置 -r 可读 -x 可执行 例子如下:测试是否为目录,也可以用 test -d bash.sh 来代替方括号 [root@localhost bash]# [ -d bash.sh ] [root@localhost bash]# echo $? 1 [root@localhost bash]# [ -d . ] [root@localhost bash]# echo $? 0 3. 逻辑与 -a 逻辑或 -o 逻辑否 ! 例子如下: [root@localhost bash]# [ -d bash.sh -a -d . ] [root@localhost bash]# echo $? 1 [root@localhost bash]# [ -d bash.sh -o -d . ] [root@localhost bash]# echo $? 0 [root@localhost bash]# [ ! -d bash.sh -a -d . ] [root@localhost bash]# echo $? 0 [root@localhost bash]# [ ! -d bash.sh -a ! -d . ] [root@localhost bash]# echo $? 1 4. 字符串测试 [ string1 string_operator string2 ] 或者 [ string_operator string ] string_operator可为:= 两个字符串相等 != 两个字符串不等 -z 空串 -n 非空串 5. 数值测试 [ "number1" num_operator "number2" ] num_operator可为: -eq 数值相等 -ne 数值不等 -gt number1 > number2 -lt number1 < number2 -le number1 <= number2 -ge number1 >= number2 例子: [root@localhost bash]# [ "100" -gt "101" ] [root@localhost bash]# echo $? 1 [root@localhost bash]# [ "100" -lt "101" ] [root@localhost bash]# echo $? 0 6. expr语法 expr arg1 operator arg2 例子:变量自增 [root@localhost bash]# COUNT=1 [root@localhost bash]# echo $COUNT 1 [root@localhost bash]# COUNT=`expr $COUNT + 1` [root@localhost bash]# echo $COUNT 2 No.018 控制流结构 1. if语句格式 if 条件1 then 执行命令1 elif 条件2 then 执行命令2 else 执行命令3 fi 2. case语句格式 case 值 in 模式1) 命令1 ;; 模式2) 命令2 ;; ...... easc 其中的“模式”可以是 *(任意字符), ?(任意单字符), [..](范围内任意字符) “模式”中还可以是使用 | (比如 str1|str2 表示str1和str2都可以) 3. for语句格式 for 变量名 in 列表 do 命令1 命令2 ...... done 4. until语句格式 until 条件 命令1 ...... done 一直执行至条件为真时才结束,至少执行一次 5. while语句格式 while 条件 命令1 ...... done 6. 利用IFS来改变读取内容的分隔符 7. 利用break和continue控制循环的执行 No.019 Shell函数 1. shell函数格式 函数名 () { 命令1 ...... } 或者 function 函数名 () { 命令1 ...... } 2. 引用其他脚本中函数 . /pathname/funcfile (<点><空格><斜线><文件完整路径名>或者<点><空格><文件相对路径名>) 3. 函数中通过 $1, $2,......$9来获取参数 No.020 向脚本传递参数 1. 使用shift依次获取各个参数,比如 while [ $# -ne 0 ] do echo $1 # 通过shift,$1将依次表示各个参数 shift done 2. getopts语法格式 getopts operation-string variable。 No.021 屏幕输出 1. tput 控制屏幕上的字符输出,比如加粗字符,隐藏光标等等 2. 改变字符颜色的方法,比如 echo "<CTRL-V><ESCAPE>[40;32m" 设置背景黑色(40), 字符绿色(32) No.022 屏幕输入 1. 输入时进行validation check “送进的是垃圾,出来的肯定是垃圾” No.023 调试脚本 1. shell不会对错误进行精确定位,当shell打印错误后,需要观察报错的整个代码段 2. 在脚本中利用set命令辅助调试 set -n 读命令但不执行 set -v 显示读取的所有行 set -x 显示所有命令及参数 - 表示打开; + 表示关闭;set +x 表示关闭显示所有命令及参数 No.024 shell 嵌入命令 1. set 命令在脚本中设置脚本的运行参数 2. times命令打印shell消耗时间和运行命令消耗时间 ??? 3. type 命令查询命令是否有效及命令类型 4. ulimit 命令设置运行在shell上的显示限制 5. wait 命令是父进程等待子进程完成 No.025 深入讨论<< 1. 创建文本 ex. cat >> file <<end > (输入内容) > end (输入内容)将被追加到file中 No.026 shell工具 1. 用日期做文件名,ex. $ Myfile=`date +%Y%m%d%H%M%S` $ touch $Myfile 2. 脚本中的临时文件名中加入进程号,可以保证文件名唯一,并在脚本结束时删掉文件 ex. TmpFile1=/tmp/tempfile1.$$ TmpFile2=/tmp/tempfile2.$$ rm /tmp/*.$$ 3. 常用信号 信号 信号名 含义 1 SIGHUP 挂起或父进程被杀死 2 SIGINT 来自键盘的中断信号,通常是<CTRL-C> 3 SIGQUIT 从键盘退出 9 SIGKILL 无条件终止 11 SIGSEGV 段(内存)冲突 15 SIGTERM 软件终止(缺省杀进程信号) 4. trap 捕获信号 语法 trap "do-something" signal(s) ex. trap "" 2 3 忽略信号2和信号3,用户不能终止该脚本 trap "commands" 2 3 如果捕捉到信号2和信号3,就执行相应的commands trap 2 3 复位信号2和3,用户可以终止该脚本 5. eval 对变量进行2次扫描 比如: [wangyb@localhost bash]$ VAR1="cat a.sh" [wangyb@localhost bash]$ echo $VAR1 cat a.sh [wangyb@localhost bash]$ eval echo $VAR1 cat a.sh [wangyb@localhost bash]$ eval $VAR1 #!/bin/bash TMP='HELLO' sleep 2 times 6. 获取命令行的最后一个参数: ex. $(eval echo \$$#) 7. logger 命令记录日志 No.027 几个脚本例子 # 作者常用的几个脚本 No.028 运行级别脚本 1. 确定当前的运行级别:who -r 2. 运行级别含义 运行级别0 启动和停止整个系统 运行级别1 单用户或管理模式 运行级别2 多用户模式;部分网络服务被启动。 运行级别3 正常操作运行模式,启动所有的网络服务 运行级别4 用户定义的模式,可以使用该级别来定制所需要运行的服务 运行级别5 有些Unix操作系统变体叫起作为缺省X-windows模式 运行级别6 重启动 No.029 cgi脚本 # 感觉现在应该不会有人用bash来开发web程序了吧 No.030 常用shell命令 1. basename : basename path 2. cat : cat optiones file -v 显示控制字符 3. compress : compress options files -v 显示压缩结果 4. cp : cp options file1 file2 -i 覆盖文件之前提示用户确认 -p 保留权限模式和更改时间 -r 拷贝相应的目录及其子目录 5. diff : diff options file1 file2 -c 按照标准个数输出 -I 忽略大小写 6. dircmp : dircmp options directory1 directory2 -s 不显示相同的文件 7. dirname : dirname pathname 8. du : du options directory -a 显示每个文件的大小,不仅是整个目录所占用的空间 -s 只显示总计 9. file : file filename 10. fuser : fuser options file -k 杀死所有访问该文件或文件系统的进程 -u 显示访问该文件或文件系统的进程 11. head : head -number files 12. logname : logname (显示当前使用的登陆用户名) 13. mkdir : mkdir options directory -m 在创建目录时按照该选项的值设置访问权限 14. more : more options files -c 不滚屏,而是通过覆盖来换页 -d 在分页处显示提示 -n 每屏显示n行 15. nl : nl options file -I 行号每次增加n;缺省为1 -p 在新的一页不重新计数 16. printf : printf format arguments 17. pwd : pwd 18. rm : rm options files -i 在删除文件之前给出提示(安全模式) -r 删除目录 19. rmdir : rmdir options directory -p 如果相应的目录为空目录,则删除该目录 20. script : script option file -a 将输出附加在文件末尾 21. shutdown : shutdown now 22. sleep : sleep number(秒数) 23. strings : strings filename (查看二进制文件中的文本) 24. touch : touch options filename -t MMDDhhmm 创建一个具有相应月,日,时分时间戳的文件 25. tty : tty 显示所连接的设备或终端 26. uname : uname options -a 显示所有信息 -s 系统名 -v 只显示操作系统版本或其发布日期 27. uncompress : uncompress files 28. wait : wait processID 29. wc : wc options files -c 显示字符数 -l 显示行数 -w 显示单词数 30. whereis : whereis command_name 31. who : who options -a 显示所有的结果 -r 显示当前的运行级别 -s 列出用户名及时间域
AWK学习笔记: ================================================== 、匹配第4列包含"Brown"的行 awk '{if($4~/Brown/) print $0}' grade.dat 、匹配第1列包含 Brown 或 Yellow的 行 awk '{if($1 ~ /Brown/ || $1 ~ /Yellow/) print $0}' grade.dat 、匹配第3列等于"的行 awk '$3!="48"{print $0}' grade.dat 、内置变量的用法: 3.1、NR: 已读的记录数: awk '{print $0}END{print NR}' grade.dat 3.2、NF: 浏览记录的域个数: awk '{print NF" "NR" "$0}END{print FILENAME" has counts: "NF}' grade.dat NF还有一个强大的功能是将变量$pwd的值传入awk并显示其目录,如:echo "bossapp/lele/into" | awk -F/ '{print $0}' 、awk操作符 设置域变量名: awk '{name=$1;belts=$4; if(belts ~ /Yellow/) print name " is belt "belts}' grade.dat awk 'BEGIN{scolor="Yellow"}{name=$1;belts=$4; if(belts == scolor) print name " is belt "belts}' grade.dat 修改域的值:awk '{if($4 ~ /Brown/) {$4="new Brown";$6 -= 1};print $0}' grade.dat 创建新的域:awk 'BEGIN{newfield=0}{newfield=$6+$7; print $0 "\t" newfield; OFS="----"}' grade.dat 求某列值总和: awk '{total += $6;}END{print "Club student total points : "total}' grade.dat 打印某个目录下所有文件名及其大小: ls -l | awk ' /^[^d]/ {print $8"\t"$5; total += $5} END{print "all files size is : " total}' 、awk内置字符串函数 gsub(s,t): awk ' gsub(/48311/, a) {print $0}' grade.dat index(s,t): awk '{print index($1,"M.")}' grade.dat length(s): awk '{print length($3)}' grade.dat match(str,reg): awk '{print match($1,/^J/)}' grade.dat split(str,arr,fx): awk '{split("a/b/c/d", arr, "/"); print arr[1]}' grade.dat sub(reg, str): awk '{str="poped popo kell"; sub(/op/, "OP", str); print str}' grade.dat substr(str, i, len): awk 'BEGIN{str="poped popo kell"}END{print substr(str, 1, 5)}' grade.dat $str = "poped popo kell" echo $str | awk '{print substr($0,1,7)}' 、awk的printf函数 echo " | awk '{printf "%x\n",$0}' awk '{printf "%-15s %s\n",$1,$2}' grade.dat awk '{AGE = 29; if($7 < AGE) print $0}' grade.dat df | awk '{print $3}' ================================================== sed学习笔记: ================================================== 、匹配指定行 sed -n '2p' quote.dat 、匹配指定范围的行 sed -n '1,3p' quote.dat 、匹配包含某单词的行 sed -n '/honeysuckle/p' quote.dat 、匹配以ing结尾的某单词的行 sed -n '/.*ing/p' quote.dat sed -n '/.*ing/=' -e '/.*ing/p' quote.dat 、替换文本 sed 's/night/NIGHT/' quote.dat 只替换第一次出现的night sed 's/night/NIGHT/g' quote.dat 替换全局所有的night sed 's/night/NIGHT/w sed.out' quote.dat 将修改结果输出到文件sed.out 、插入 sed -n 's/night/light &/p' quote.dat 在night前插入light sed 's/The/& addword/' quote.dat 在The后插入addword 、将sed结果写入文件 sed '1,2 w sed.out' quote.dat 将quote.dat的第1、2行写入到sed.out文件中 、在指定行的下一行,附加另外一个文件的内容 sed '/night/r sed.out' quote.dat 、首次匹配到某单词后退出 sed '/music/q' quote.dat sed 's/^M//q' quote.dat 、例:去掉路径前的/ , 在最后加一个/ echo $PWD | sed 's/\///' | awk -F/ '{print $0"\/"}' 小结:sed 命令主要用于文本过滤及处理 ================================================== sort、uniq学习笔记 ================================================== sort: 、按逆序排序 sort -r vid.dat 、按指定域排序 sort -t: + vid.dat 、对于数值列排序 sort -t: + vid.dat 先按第一个数字进行排列,再按第二个数字排列,依此类推。和字符排列一样 sort -t: +2n vid.dat 按数值大小排序 、从某域的第n个字符开始排序 sort -t: +.2n vid.dat 、指定域从1开始计数 sort -t: -k1 vid.dat 、删除重复的行 sort -u + vid.dat uniq: 、只显示不重复行 uniq -u a1.c 、只显示重复的一行 uniq -d a1.c 、显示复重的行数 uniq -c a1.c 、只按某个域进行重复排序 uniq -f2 ab.c join: 、连接join join ab.c abc.c 、左连接 join -a1 ab.c abc.c 、右连接 join -a2 ab.c abc.c 、显示指定的域 join -o 1.1,1.2,2.1,2.2 ab.c abc.c 、指定匹配域连接 join -j1 -j2 ab.c abc.c cut: 、以":"为分隔符,剪切域1 cut -d: -f1 vid.dat 、以 cut -d: -f1, vid.dat 、以":"为分隔符,剪切域1至3 cut -d: -f1- vid.dat 、以空格为分隔符,剪切域1 cut -d" " -f1 grade.dat paste: 、粘贴两个域,以@为分隔符 paste -d@ ab.c abc.c 、把列变成行来粘贴 paste -s ab.c abc.c 、管道输入,"-"接受变量输入 ls | paste a1.c - split: 、默认按1000行分割,保存为x[aa]--x[zz] split grade.dat 、指定行数进行分割 split - grade.dat ================================================== tr学习笔记 ================================================== 、消除重复的字符串序列 tr -s "[a-z]" < oo.dat : 消除重复的小写字母 tr -s "[0-9]" < oo.dat : 消除重复的数字 、删除空行 tr -s "[\n]" < oo.dat 、从大字转换成小写 tr "[A-Z]" "[a-z]" < oo.dat 、删除末行的控制字符 "^M" tr -s "[\r]" "[\n]" < data.f | cat -v 小结:常用于删除空行,大小字替换,删除控制字符 ==================================================Shell变量学习笔记 ==================================================、若变量定义,则使用默认值 echo ${variable-name:-defaultValue} 、若变量定义,则输出错误信息 echo ${variable-name:?} 输出系统错误信息 echo ${variable-name:?"my error message"} 输出自定义错误信息 、将变量设置成只读 readonly variable-name 、查看所有系统变量 env 、系统变量必须用export命令导出 、设置传入变量 $0为脚本名 $ 为第1个参数 例如: 脚本myScript find . -name $ -print 调用:myScript myparam 其中myparam当作参数($)传给脚本中的find命令 、一些特定参数变量 $? : 显示最后一个命令退出状态,0为成功,其他值表明的错误 $# : 传递到脚本的参数的个数 $$ : 显示脚本运行的当前进程ID号 $* : 以一个字符串显示所有参数 $@ : 在引号中返回各个参数 ==================================================条件测试 test 学习笔记 ==================================================、文件测试 有如下参数 -r : 可读 -w : 可写 -x :可执行 -d :目录 -f :正规文件 -u :文件有suid设置 例: test -x wow [ -x wow ] 可以将两个测试结果进行与或操作 -a : 与 [ -w wow -a -w wow ] -o :或 [ -w wow -o -w wow ] 、字符串测试 有五种格式 test "string" test operator "string" test "string" operator "string" [ operator "string" ] [ "string" operator "string" ] 其中,operator可以为: = :两个字符串相等 != :两个字符串不等 -z : 空串 -n : 非空串 、数值测试 格式: test "number1" operator "number2" [ "number1" operator "number2" ] 其中,operator可以为: -eq :两数相等 -ne :两数不相等 -gt :> -lt :< -ge :>= -le :<= 、expr的用法 4.1 expr用于数值计算 如:expr + expr \* expr / : 结果为1,不保留小数位 4.2 用例:用于循环计数 loop= loop=`expr $loop + ` 4.3 expr用于字符串 expr "a" = "a" : 特别需要注意的是,如果成功返回1,返回其它值为错误 4.4 expr用于模式匹配 value="accounts.doc" expr $value : ".*" 统计任意字符出现的次数,也就说统计单词的个数 expr $value : ".c" 统计c出现的 ==================================================控制结构(while、for、until loop、if then else) ==================================================一、if then else 结构 格式: if 条件1; then 语句1; elif 条件2; then 语句2; fi 例1:名字为空,则输出信息 #!/bin/sh echo -n "Please Enter your name:"; read NAME; if [ "$NAME" = "" ]; then echo "you havn't Enter your name!"; fi 例2、用户输入名字列表,脚本判断是否包含peter #!/bin/sh echo -n "Please Enter your name:"; read NAMELIST >& then echo "peter is here"; else echo "peter is not here"; fi 例3、文件复制输出检查。自定义错误信息 #!/bin/sh >& then echo "复制成功!"; rm wow_copy; else echo "脚本`basename $0`发生错误,原因为: cp命令发生错误"; fi 例4、当前目录测试 #!/bin/sh DIRNOW=`pwd` if [ "$DIRNOW" != "/" ] then echo exit fi 例5、测试传递到脚本的参数 #!/bin/sh ] then echo exit fi echo "arg1: $1" echo "arg2: $2" echo "arg3: $3" 例6、登陆测试脚本,用户名和密码必须是peter/hellen-- #!/bin/sh #设置登陆标志 INVAIL_USER=yes INVAIL_PWD=yes #保存当前stty设置 SAVESTTY=`stty -g` echo "welcome to XX System for unix, now you will login to the system" echo "please Enter your username:" read USERNAME #设置输入密码时不可见 stty -echo echo "please Enter your password:" read USERPWD #恢复之前stty设置 stty echo if [ "$USERNAME" = "peter" -o "$USERNAME" = "hellen" ] then INVAIL_USER=no fi " ] then INVAIL_PWD=no fi if [ "$INVAIL_USER" = "no" -a "$INVAIL_PWD" = "no" ] then echo "now you have login into System" else echo "username or password is invaild, please check them and login next time" exit fi 二、case 例7、一个简单的case例子,其中配置部份可以用"|"来作为或命令 #!/bin/sh echo "please Enter your choose:" read ANS case $ANS in ) echo "you have selected 1" ;; ) echo "you have selected 2" ;; ) echo "you have selected 3" ;; ) echo "you have selected 4" ;; ) echo "you have selected 5" ;; *) echo esac 三、for 格式: for 变量 in 列表 do 程序体 done 其中,列表可以是Shell命令 例8、一个最简单的for循环 #!/bin/sh do echo $loop done 例9、将ls的结果打印出来 #!/bin/sh for loop in `ls` do echo $loop done 例10、将参数打印出来 #!/bin/sh for loop in $* do echo $loop done 例11、在for程序体中使用find,实现多文件查找 for loop do find . -name $loop -print done 例12、统计当前目录下的文件数目 #!/bin/sh count= for loop in * do count=`expr $count + ` done echo "there is $count files" 其实用ls | wc -l 也能统计出当前目录下文件的个数 四、until 例13、查看root用户是否登陆,登陆则给其发个邮件 #!/bin/sh IS_ROOT=`who | grep root` until [ "$IS_ROOT" ] do sleep echo "no login" done 五、while 例14、输出1- #!/bin/sh i= ] do echo $i i=`expr $i + ` done 例15、从键盘读字符串,按ctrl+D结束读入 #!/bin/sh echo -n "Enter: " while read name do echo "output: $name" done 例16、用while循环读取文件的每一行 #!/bin/sh while read FLINE do echo $FLINE done < data.f 例17、以:为分隔符,依次读取域信息 #!/bin/sh SAVEIFS=$IFS IFS=: while read NAME DEPT do echo "$NAME\t $DEPT\t" done < name.txt IFS=$SAVEIFS 例18、默认以空格为域分隔符 #!/bin/sh while read f1 f2 do echo "$f1-----------$f2" done < name.txt 说明下:无论是以什么作为分隔符,read后面的变量个数要与域的个数相同,这样就可以用变量一一对应域了 例19、每回读两行 #!/bin/sh while read rline1 do read rline2 echo $rline1 echo $rline2 echo "--------------------------" done < name.txt 例20、while循环和文件描述符 做文件备份,按行读取,写到另一个文件 #!/bin/sh FNAME=wow FNAME_BAK=wow.bak if [ -s $FNAME ]; then #将wow描述为输入文件 exec <$FNAME #将wow描述为输出文件 exec >$FNAME_BAK while : do read LINE " ]; then #关闭输入和输出 exec <&- exec <&- exit fi echo $LINE >& done <& else echo "文件不存在!" fi 六、break、continue 可以跳出两重循环 例21、用break(continue)跳出两重循环 #!/bin/sh while : do echo "这是第一重循环" while : do echo "这是第二重循环" done done ==================================================自定义函数 ==================================================、定位文件: . 文件名 这样就可以把文件中包含的函数当成系统函数了,直接调用即可,但只能在本终端运行,离开本终端就不行了 例22、自定义查找函数,可查找多个文件 #!/bin/sh myfind() { ]; then echo "至少有一个参数" fi for loop in "$@" do find . -name $loop -print done } 例23、检查名字是否全是英文 #!/bin/sh #定义检查函数 check_name() { _PARAM_NAME=$ _PARAM_NAME=`echo $ | awk '{if($0 ~ /^[a-zA-Z]+$/) print "1"}'` if [ "$_PARAM_NAME" != "" ]; then else fi } #定义错误提示函数 name_error() { echo "$@ 包含非法字符,请确保全部是英文字母" } #开始调用 while : do echo "请输入你的姓氏:" read FIRST_NAME if check_name $FIRST_NAME; then break else name_error $FIRST_NAME fi done while : do echo "请输入你的名字:" read SEC_NAME if check_name $SEC_NAME; then break else name_error $SEC_NAME fi done echo "你的名字为:$FIRST_NAME $SEC_NAME" ==================================================向脚本传递参数 ==================================================一、shift的作用:指向参数的位置偏移一位,从1开始 例24、用shift实现参数位置偏移 #!/bin/sh ] do echo $ shift done 例25、自定义大小写转换命令 #!/bin/sh #文件内容的大小写转换命令 FNAME="" OPT="no" CASEOPT="" #自定义错误函数 error_msg() { echo exit } #大小写转换 l_u_case() { for LOOP in $FNAME do case $CASEOPT in lower)cat $LOOP | tr "[a-z]" "[A-Z]" >>l_rslt.dat ;; upper)cat $LOOP | tr "[a-z]" "[A-Z]" >>u_rslt.dat ;; esac done } #若不输入参数,则报错 ] then error_msg fi #循环遍历参数,进行处理 ] do in -l)OPT="yes" CASEOPT="lower" shift ;; -u)OPT="yes" CASEOPT="upper" shift ;; -help)echo "this is help" exit ;; -*) error_msg ;; *) FNAME=$ OPT="no" shift ;; esac done #下面开始处理文件 if [ $OPT = "no" ] then if [ -f $FNAME ] then l_u_case exit else echo "$FNAME is not a file ,please check it" exit fi else exit fi 二、getopts: 获取用"-"开始的参数,如-fu, 其作用与-f -u 是一样的 例26、 #!/bin/sh while getopts :afu: OPTS do case $OPTS in a)echo "ALL" ;; f)echo "FULL" ;; u)echo "USER" ;; \?)echo exit ;; esac done 例27、-u选项必须带值,否则报错(若要屏蔽系统错误,在前面加:即可); 带入的值用变量OPTARG接收 #!/bin/sh while getopts :afu: OPTS do case $OPTS in a)echo "ALL" ;; f)echo "FULL" ;; u)echo "USER--$OPTARG" ;; \?)echo "error" exit ;; esac done ==================================================一些比较杂的东西 ==================================================一、信号:系统向脚本发出的信息或命令,有如下含义: 信号 信 号 名 含 义 SIGHUP 挂起或父进程被杀死 SIGINT 来自键盘的中断信号,通常是ctrl + c SIGQUIT 从键盘退出 SIGKILL 无条件中止 SIGSEGV 段(内存冲突) SIGTERM 软件中止,默认的 二、捕捉信号 trap 例28、当按下键盘中止后,用trap捕捉到信号,进行处理 #!/bin/sh trap tp_cmd() { echo "hahahaha" exit } loop= while : do loop=`expr $loop + ` echo $loop sleep done 例29、在某一段关键处理过程,可以屏蔽信号,从而保证完整性 #!/bin/sh #设置屏蔽信号 trap ###这一段我是不希望被打断的,否则后果很严重噢,除非你用kill - begin loop= while : do loop=`expr $loop + ` echo $loop " ] then break fi sleep done ###这一段我是不希望被打断的,否则后果很严重噢,除非你用kill - end #自定义退出函数 myexit() { echo "hahahaha" exit } ##现在可以打断了,没关系 trap while : do loop=`expr $loop + ` echo $loop sleep done 三、eval 例30、自动生成变量 #!/bin/sh loop= name="a" while : do loop=`expr $loop + ` eval `echo "$name$loop=$loop"` echo $name$loop=$loop " ] then exit fi done