本文转自敬爱的林肯老师博客
一 文件内容如下:
100
a 100
b -50
c -20
d -30
要求输出结果为:
100
a 100
200
b -50
150
c -20
130
d -30
一句话思路:用shell肯定是不行,因为是操作文件。用sed倒是可以操作文件,但有数学运算还要用到变量。所以,用awk应该是最好的。
awk 'NR==1{sum=$1;print $0}NR!=1{print $0;sum=sum-$2;print sum}' 内容文件
知识点:awk变量,域
二 文件内容如下:
123abc456
456def123
567abc789
789def567
要求输出:
456ABC123
123DEF456
789ABC567
567DEF789
一句话思路:以点带面,文字处理,shell不行,awk不行,用sed加正则表达式
sed -r 's/([1-9]{3})([a-f]{3})([1-9]{3})/\3\2\1/;y/abcdef/ABCDEF/' 内容文件
知识点:-r 支持扩展的正则表达式,跟grep用-P类似。y其实就是tr只是写到sed里面更好看一些,sed的查找替换,当然还有正则中的分组。sed中的分组可以这么用,awk就不行了只能用&,而且分组数量不能超过9,即不会有\10出现。
三. 文件内容如下
1.1.1.1 11
1.1.1.1 22
1.1.1.1 33
1.1.1.1 44
2.2.2.2 11
2.2.2.2 22
2.2.2.2 33
2.2.2.2 44
要求使用sed及awk分别将文件输出:
1.1.1.1 11 22 33 44
2.2.2.2 11 22 33 44
一句话思路:这个没啥思路了,上面还分析分析用什么合适,这里面没的选了,人家都说了,就弄吧。
sed -r 'N;N;N;s/\n/ /g;s/(.*)(11 )(.*)(22 )(.*)(33 )(.*)(44)/\1\2\4\6\8/' 内容文件
知识点:N将文件的下一行读入模式空间,3个N就是读取下面三行进入当前模式空间,读进去的行依然保留换行,所以删除换行,后面的就不说了,你懂的。
awk '{sum[$1]=sum[$1]" "$2}END{for(var in sum)print var sum[var]}' 内容文件
知识点:awk数组,awk字符串赋值,使用for遍历awk数组。
四. 分析apache日志,给出当日访问ip的降序列表。
一句话思路:分析ip就要提取ip,提取的办法除了awk,还有个东西叫cut。
cut -d " " -f1 /etc/httpd/log/access_log | sort | uniq -c | sort -nr
知识点:cut命令,sort将汇总相同内容,uniq -c合并重复内容,并给出重复次数。sort -nr 使用数字排序,默认是ascii,并且是降序,默认是升序。
awk '{sum[ip]++}END{for(var in sum)print ip sum[var]}' /etc/httpd/log/access_log | sort -k2 -nr
知识点:awk数据,sort -k2 -nr 降序数字排序就不说了,-k参数指定使用哪个列进行排序。默认是自然是第一列。
五.亚瑟王环
有1到100的数字序列。有计数器每数到12,就将计数器指向的数字在亚瑟环中剔除,问该序列中最后剩下的数字是多少?
一句话思路:100,12的太复杂,就弄个10,2的,完成之后替换一下。。。。。。
最后的答案是:81 面试的时候你可以说是心算的(别脱口而出,稍微伪装一下),就是不知道行不行。
做计数器,当计数器到达12的时候就将一个数组中对应的值赋值为零。当所有数组中的数字还剩唯一的不为零的值的时候就是剩下的数字。
#/bin/bash
for i in {1..100};do
huan[$i]=$i
done #先初始化一个数组,其实用变量也行,个人喜好,用awk也行,但一篇内容一个shell有点不合适。
t=0 #定义一个计数器
sum=0
while true;do #定义一个无限循环,因为确实不知道要数多少次。
for((i=1;i<101;i++));do if [ ${huan[$i]} -gt 0 ];then #不等于零就把计数器加1 let t++ fi if [ $t -eq 12 ];then #数到12就将数组中的数清零,同时计数器清零 huan[$i]=0 t=0 fi done for((i=1;i<101;i++));do #遍历数组,如果数组中只有一个数不为零就跳出循环 if [ ${huan[$i]} -gt 0 ];then let sum++
sum[1]=${huan[$i]} fi done if [ $sum -eq 1 ];then break else sum=0 fi done
echo ${sum[1]}
篇幅有限,不能全部列出,后面还会不断有内容更新。欢迎批评指教,不详之处,务请见谅!
本文出自 “ ” 博客,请务必保留此出处
这篇的内容相对基础,主要集中在计划任务和find命令上面。 crontab 分时日月周 find命令的 exec 和 xargs 这是两个比较容易遗忘的知识点。
1、编写shell程序,实现自动删除50个账号的功能。账号名为stud1至stud50。 一句话思路:找出规律,循环解决 for((i=1;i<51;i++));do userdel -r stud$i ;done 知识点:for循环,当然是用while循环也是可以的,until也行。 2、某系统管理员需每天做一定的重复工作,请按照下列要求,编制一个解决方案: (1)在下午4 :50删除/abc目录下的全部子目录和全部文件; (2)从早8:00~下午6:00每小时读取/xyz目录下x1文件中每行第一个域的全部数据加入到/backup目录下的bak01.txt文件内; (3)每逢星期一下午5:50将/data目录下的所有目录和文件归档并压缩为文件:backup.tar.gz; 一句话思路:主要考验管理员对于计划任务的熟悉程度 crontab -e 50 16 * * * rm -rf /abc/* * 8-18/1 * * * awk '{print $1 > "/backup/bak01.txt"}' /xyz/x1 50 17 * * 1 tar -czf backup.tar.gz /data 知识点:awk的输出重定向,当然用管道也是可以的。tar命令打包参数,这样做会有一个提示,只是去掉了目录不用理会。 3、gameser这个服务启动命令为./gameser服务,请写一个脚本,当服务宕掉,脚本自动拉起gameser服务。 一句话思路:进程管理 #!/bin/bash while true;do result=`ps aux | grep gameser | wc -l` if [ $result -lt 2 ];then ./gameser; fi sleep 5 done 知识点:还可以使用pgrep命令。 4、linux crontab;请在3月23号21点18分的时候,重启服务器 一句话思路:计划任务+关机 crontab -e 18 21 23 3 * init 6 知识点:可能会延展提问到最安全的关机命令,“写缓存”sync 最好两遍,有人说三遍,其实四遍也行,要不干脆还是别关机了! 5、你想每天23:00运行xxxx.sh脚本。并自动进行日志分析。第2天上班的时候看到分析结果 给出你的部属方案 一句话思路:计划任务,日志分析 0 23 * * * sh ****.sh;err=$?;logger -p cron.err $err 知识点:第一个参数一定要写零,否则在定义的23点里每分钟都会执行。计划任务只有当报错的时候才会以邮件形式发送给用户,所以这里使用logger命令将消息发送给日志服务器,这里只是发送了命令返回值,你可以随意发送内容,看你喜欢了。 6、要求:运行脚本输入两个数得到如下结果: #sh xxx.sh 2 3 ** *** ***** 一句话思路:看到这个第一反应就是循环呗。 #!/bin/bash line1=$1 line2=$2 let line3=$1+$2 while [ $line1 -gt 0 ];do echo -n \* let line1=$line1-1 done echo while [ $line2 -gt 0 ];do echo -n \* let line2=$line2-1 done echo while [ $line3 -gt 0 ];do echo -n \* let line3=$line3-1 done echo 知识点:如果你的第一反应是使用循环,那就进入一个死循环了,因为根本就没有规律。我们都知道,循环是依靠一定规律的。echo 的 -n参数。*在shell中是通配符,所以要加转义字符。(希望你能给出更好的解决方案!) 9、查找文件后缀是log的 三天前的文件删除 一句话思路:查找就一定是find find / -name "*.log" -and -mtime +3 -exec rm -rf {} \; 知识点:-mtime + 代表后面数字之外的,- 就是之内的。 10、写一个脚本将目录下大于100kb的文件移动到/tmp下 一句话思路:同上 find ./ -size +100k -exec mv {} /tmp \; 知识点:-exec {} \; 标准写法,没有好办法,背吧。 11 、日志如下统计访问IP最多的前10个 192.168.0.6 - - [25/Nov/2010:13:55:10 +0800] "GET /cacti/p_w_picpaths/auth_login.gif HTTP/1.1" 200 21265 "http://192.168.0.104/cacti/graph_view.php?action=tree&tree_id=2&leaf_id=8&page=3" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; InfoPath.1)" 192.168.0.6 - - [25/Nov/2010:13:55:14 +0800] "GET /favicon.ico HTTP/1.1" 404 287 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; InfoPath.1) 这个题在前一篇中已经给出答案,这里就不再赘述。 http://7648853.blog.51cto.com/4990508/851407 12、过滤出当前目录下所有以字母(不区分大小写)开头的文件 一句话思路:过滤就是grep ls | grep -P "^[a-zA-Z]" ls | grep -P -i "^[a-z]" 知识点:正则表达式,使用-i参数让grep命令不区分大小写。 13、文件A.txt内容为"12:34:68",只输出A.txt中的"34" 一句话思路:提取内容就是awk awk -F ":" '{print $2}' A.txt 知识点:awk 域,-F参数指定分隔符,默认分隔符是空格。 14、用sed命令实现直接将文件B.TXT中的所有123替换成345 一句话思路:没思路了,人家都说了用sed sed -i 's/123/456/g' B.TXT 知识点:-i参数让sed修改文件,默认不修改源文件。题目中提到了所有字样,所以要使用g参数。 15、用sed修改文件mailbox.txt的20行的zhango为wang 一句话思路:命题作文sed,没有瞎想空间 sed -i '20s/zhango/wang/' mailbox.txt 知识点:上题是全局,这题规定了行。如果写成这样"/20/",就是正则表达式了。 16、正则表达式,IP地址的匹配,写一下 一句话思路:遥想当年,web开发程序员面试不出意外的第一道题。 ([0-9]{1,3}\.){1,3}([0-9]){1,3} 知识点:正则表达式,写个简单的,这个答案不严谨,但考虑到只是面试,所以将就将就也能用。 17、写出命令。统计日志文件weblog.log中 今天14:00~15:00的记录条数(时间格式:2011-01-01—15:30:11) 一句话思路:第一反应,这个要用awk,分析统计嘛。可真要用awk麻烦就大了。 sum14=`grep -c "2011-01-01-14" weblog.log` sum15=`grep -c "2011-01-01-15" weblog.log` echo $[$sum14+$sum15] 知识点:grep命令-c参数,统计匹配的行数。shell中的数学计算。 18、求一组数的最大值和最小值 一句话思路:运维越来越像开发了,冒泡法都有了。越来越难混了,一个运维不看手册,要看算法了。 知识点:去看书吧,看算法的。 19、将当前目录所有文件扩展名改为log 一句话思路:如果你的第一反应是使用find命令,那么恭喜你,你中了敌人的奸计,不是不能实现,是很麻烦。 for file in `ls ./ | grep -P "(.*)(\..*)"`;do echo $file | mv $file `sed -r 's#(.*)(\..*)#\1.log#'`; done for file in `ls ./ | grep -P "(.*)(\..*)"`;do echo $file | mv $file `echo ${file%.**}`.log; done 知识点:第一个方法中使用了sed,第二个方法中使用了字符操作,#从前向后数,%从后向前数。其实说白了,就是为了拼凑出 mv 参数1 参数2。其实很多时候,编写shell脚本的时候要学会反向推导,逆向思考。 还有一种方法是使用cut命令,但如果遇到文件有两个扩展名的情况下就会出现问题。redhat as4 安装完成后,在root目录下会生成install.log install.log.syslog这两个文件,如果使用cut就会出现错误。具体原因在这里就不说了。运维嘛,需要的是严谨! 20、用shell在/usr/local下 建立20个子目录 xunlei1-xunlei20,再在这个子目录下分别建255个子目录dir1-dir255,再在255个子目录下创建10000个文件xunlei1.html-xunlei10000.html 一句话思路:这有啥,{}大括号呗。 mkdir -p /usr/loca/xunlie{1..20}/dir{1..255}/ touch /usr/loca/xunlie{1..20}/dir{1..255}/xunlei{1..10000}.html 知识点:如果你就这么写上去,那你又中计了。为什么呢,因为超过了shell命令参数的最大限制。shell中参数的限制是:5452。所以要分着写。 写到这里,不禁感叹,面试这件事情越来越难。本来面试就紧张,满怀期待,不仅要跟HR讨价还价,还要与技术主管斗智斗勇,好吧,人是活的,我们忍了。可连死的面试题都要处处小心。可话说回来,面试题做不出来,就算你跟诸葛亮对着骂街都能微操胜券也没用。 在这里要特别感谢邰锴同学,这些shell题是他帮忙汇总整理出来的。
本文出自 “ ” 博客,请务必保留此出处
1.如下是对api接口日志的截取,存放在check.log文件中 22:57:36|check|por1|117.136.15.67|4|username|fail|5|29| 22:57:36|check|por1|183.1.94.215|4|username|succ|1644841971|14| 22:57:36|check|pro2|0.0.0.0| |username|succ|162885433|6| 22:57:36|check|por2|0.0.0.0|9|username|fail|-4038|0| 22:57:36|check|por3|120.11.82.19|2|username|fail|5|49| 22:57:36|check|por4|172.16.86.82|0|username|succ|1548062613|1| 22:57:36|check|por2|123.125.156.135|9| |succ|1632786393|1| 22:57:36|check|por5|124.231.21.100|5|username|succ|224803739|3| 22:57:36|check|por4|172.16.86.82|0|username|succ|1505887155|1| 22:57:36|check|por2|0.0.0.0|9|username|succ|1343846051|1| 22:57:36|check|por6|113.193.202.138|8|username|succ|1729273615|1| 22:57:36|check|por6|116.75.149.20|8|username|succ|1729981552|1| 22:57:36|check|por5|116.5.164.94|5|username|succ|214405328|1| 22:57:36|check|por2|0.0.0.0|9|username|succ|1433162137|1| 22:57:36|check|por3|218.69.6.30|5|username|succ|28725136|42| 22:57:36|check|por2|0.0.0.0|8| |fail|5|4| 22:57:36|check|por5|123.115.102.222|5|243905232|succ|243905232|1| 22:57:36|check|por4|172.16.86.82|0|1011711900|succ|1011711900|39| 日志各字段代表的意义如下: 时间|接口名称|使用该接口的产品名称|调用接口的IP地址|用户类型|用户账号名称|接口返回结果(succ or fail)|当接口返回结果为“succ”时,该字段为用 户唯一编号;当接口返回结果为“fail”时,该字段为接口返回的错误代号|接口执行时间(毫秒级别) 问题:请使用shell命令的组合得到每个产品调用该接口成功时接口的平均执行速度,并按照执行速度由低到高排序(注:用户类型和用户账号名称为空的访问不 计算在内),以如下格式输出: pro1 :0.0714286 pro2 :0.3333333 pro3 :0.0238095 pro4 :0.0731707 pro5 :0.6 pro6 :1 一句话思路:有计算、有排序,awk是唯一选择。统计总数的同时,还要统计出现次数,最后进行计算。
awk -F "|" '$(NF-3)~/succ/{por[$3]=por[$3]+$(NF-1);sum[$3]++}END{for(var in por)print var" :"por[var]/sum[var] | " sort -k2 -nr"}' check.log
知识点:awk数组,awk管道,为避免不等长使用NF变量
2.用一行命令实现:查找当前目录下(含子目录),文件内容中含有sina且文件名以".config"结尾的文件 一句话思路:批量按规则查找文件内容grep grep -lr "sina" ./ | grep -P "(.*)(\.config$)" 知识点:grep -r 递归查找,-P支持perl正则表达式 3.用shell查询以“.”结尾的文件,并加上后缀“.ts” 一句话思路:在之前的曾经有过批量修改扩展名的实例,但这次有所不同,使用find命令就可以搞定 find ./ -name "*." -exec mv {} {}ts \; 知识点:find命令
4.假定某个web服务器访问log其中一行如下: 61.159.245.95 - - [30/Apr/2003:01:04:20 +0800] "GET / HTTP/1.1" 200 151 "http://www.baidu.com" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.3; 360SE)" 该LOG文件超过10万行,如果列出最后的10万行中请求最多前十位IP,显示如下的结果: 119 211.101.169.200 103 211.101.169.206 50 61.149.38.249 11 202.106.138.194 请用一行命令显示出上面的结果
一句话思路:之前有过类似的,这里不再赘述 awk '{ip[$1]++}END{for(var in ip)print ip[var],var |"sort -nr|head -n10"}' log 5.linux下ifconfig命令显示结果如下: eth0 Link encap:Ethernet HWaddr 00:0C:29:AA:E6:44 inet addr:192.168.213.128 Bcast:192.168.213.255 Mask:255.255.255.0 inet6 addr: fe80::20c:29ff:feaa:e644/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:39962 errors:0 dropped:0 overruns:0 frame:0 TX packets:27038 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:35108954 (33.4 MiB) TX bytes:6573610 (6.2 MiB) Base address:0x2000 Memory:c9020000-c9040000 lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:1833 errors:0 dropped:0 overruns:0 frame:0 TX packets:1833 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:4840659 (4.6 MiB) TX bytes:4840659 (4.6 MiB) 执行如下命令 /sbin/ifconfig eth0|grep 'inet '|sed 's/^.*addr://g'|sed 's/ Bcast.*$//g' 请写出命令的输出结果 ip地址 犹豫了一下这个要不要写,在命令行里执行一下就行了。 6.多线程/多进程 程序同时访问相同的资源(例如:同时向一个文件里写数据)需要注意些什么? 至少注意文件锁,读锁与写锁 7.写脚本实现,可以用shell,perl等。把文件B中有的,但是文件A中没有的所有行,保存为文件C,并统计C的行数 diff B A | grep "<" | sed 's/< //' > C 8.脚本实现把/tmp/目录下所有创建超过7天的文件删除 find /tmp -mtime +7 -exec rm -rf {} \; 9.把1 2 3 4 5 6按如下格式输出 1 2 3 4 5 6 如何实现 echo 1 2 3 4 5 6 | sed "s# #\n#g" 10.设计一个shell程序,在2012年12月23日凌晨3点备份并压缩前一天/svn目录的所有内容,存放在/root/bak目录里,且文件名为如下形式svn.2008.05.06.tar.gz,试写脚本。 at 201212230300 at> find /svn -mtime +1 -and -mtime -2 -exec cp -r {} /root/bak \; at> tar -czf svn.2008.05.06.tar.gz /root/bak
感谢何运涛同学,已经毕业的同学,薪水也不错。现在我们是同行了,这些题目是他帮忙整理的,原始版本都是照片,都是他一个一个字打上去的,尤其是第一题!
本文出自 “ ” 博客,请务必保留此出处