波神

导航

shell 常见面试

1、求100以内的质数

#!/bin/bash
n=100
for((i=1;i<=n;i++))
    do 
       for((x=1;x<=i;x++))
           do 
               b=$(( $i%$x ))
               if [[ $b -eq 0 ]]; then
                a=$a+1
               fi
           done
           if [[ $a -eq 2 ]]; then
            echo  $i " "
           fi
           a=0
    done
echo

执行结果

[root@auto hzb]# sh zhishu.sh 
2  
3  
5  
7  
11  
13  
17  
19  
23  
29  
31  
37  
41  
43  
47  
53  
59  
61  
67  
71  
73  
79  
83  
89  
97  

 2、查看dockerps.log的第3行的第1列

[root@auto hzb]# 
[root@auto hzb]# cat dockerps.log 
CONTAINER ID        IMAGE                                                                         COMMAND                  CREATED             STATUS                 PORTS                            NAMES
b78a979df924        hub.chinacloud.com.cn/fast-pulsar.dev/pulsar-pkg-ui-all-in-one:20181123       "/entrypoint.sh nginx"   4 days ago          Up 4 days              443/tcp, 0.0.0.0:19016->80/tcp   pulsar-pkg-ui-all-in-one
d27e04e08e94        hub.chinacloud.com.cn/fast-pulsar.dev/portal:20180926                         "nginx -g 'daemon off"   3 weeks ago         Up 3 weeks             443/tcp, 0.0.0.0:19012->80/tcp   portal
a70779e0f1a8        hub.chinacloud.com.cn/fast-wh.dev/whitehole-event:20181026                    "/apps/whitehole-even"   3 weeks ago         Up 3 weeks (healthy)                                    whitehole-event                                "docker-entrypoint.sh"   4 months ago        Up 7 weeks (healthy)                                    mysql
[root@auto hzb]# sed -n '3p' ./dockerps.log |cut -d " " -f1
d27e04e08e94

 

3、删除文件的最初三行

set -i '1,3d' ./dockerps.log

 

4、晚上11点到早上8点之前,每隔2小时,打印系统时间

[root@auto hzb]# cat date.sh 
#!/bin/bash
echo -e "date is:\n"
date
echo 1 23,1-8/2 * * * root /root/hzb/date.sh >>/etc/crontab

扩展:

crontab任务配置基本格式:
*   *  *  *  *  command
分钟(0-59) 小时(0-23) 日期(1-31) 月份(1-12) 星期(0-6,0代表星期天)  命令

第1列表示分钟1~59 每分钟用*或者 */1表示
第2列表示小时1~23(0表示0点)
第3列表示日期1~31
第4列表示月份1~12
第5列标识号星期0~6(0表示星期天)
第6列要运行的命令

0 1 * * * /home/testuser/test.sh
每天晚上1点调用/home/testuser/test.sh

*/10 * * * * /home/testuser/test.sh
每10钟调用一次/home/testuser/test.sh

30 21 * * * /usr/local/etc/rc.d/lighttpd restart
上面的例子表示每晚的21:30重启apache。

45 4 1,10,22 * * /usr/local/etc/rc.d/lighttpd restart
上面的例子表示每月1、10、22日的4 : 45重启apache。

10 1 * * 6,0 /usr/local/etc/rc.d/lighttpd restart
上面的例子表示每周六、周日的1 : 10重启apache。

0,30 18-23 * * * /usr/local/etc/rc.d/lighttpd restart
上面的例子表示在每天18 : 00至23 : 00之间每隔30分钟重启apache。

0 23 * * 6 /usr/local/etc/rc.d/lighttpd restart
上面的例子表示每星期六的11 : 00 pm重启apache。

* */1 * * * /usr/local/etc/rc.d/lighttpd restart
每一小时重启apache

* 23-7/1 * * * /usr/local/etc/rc.d/lighttpd restart
晚上11点到早上7点之间,每隔一小时重启apache

0 11 4 * mon-wed /usr/local/etc/rc.d/lighttpd restart
每月的4号与每周一到周三的11点重启apache

0 4 1 jan * /usr/local/etc/rc.d/lighttpd restart
一月一号的4点重启apache

*/30 * * * * /usr/sbin/ntpdate 210.72.145.44
每半小时同步一下时间

 

 

 5、如何将本地80端口的请求转发到8080端口,当前主机IP为172.16.0.166

   /sbin/iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to 172.16.0.166:8080

   /sbin/iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to 8080

6、获取java进程的pid

[root@auto hzb]# ps -ef|grep java|tr -s " "|cut -d " " -f2
1515
7908
22456
22749
23014

ps的输出字段间会有多个空格,所以直接用cut并不合适,用tr压缩连续空格后用cut

扩展:语法:tr [–c/d/s/t] [SET1] [SET2]
SET1: 字符集1
SET2:字符集2
-c:complement,用SET2替换SET1中没有包含的字符
-d:delete,删除SET1中所有的字符,不转换
-s: squeeze-repeats,压缩SET1中重复的字符
-t: truncate-set1,将SET1用SET2转换,一般缺省为-t

echo aaacccddd | tr -s [a-z]
acd

将语句中所有的小写字母变成大写字母,其中-t可省略

echo "Hello World I Love You" |tr -t [a-z] [A-Z]
HELLO WORLD I LOVE YOU

删除指定字符

$ cat test.txt
Monday     09:00
Tuesday    09:10
Wednesday  10:11

-d代表删除,[0-9]代表所有的数字,[: ]代表冒号和空格

$ cat test.txt | tr -d "[0-9][: ]"
Monday
Tuesday
Wednesday

 

 7、将当前目录下大于10944的文件转移到当前目录的bak下

#!/bin/bash
fileinfo=($(du ./*))
length=${#fileinfo[@]}
for((i=0;i<$length;i=$((i+2 ))));
  do
   if[ ${fileinfo[$i]} -le 10 ];then
     mv ${fileinfo[$((i+1 ))]} ./bak/
   fi
  done

分析:du ./*的内容如下:

[root@auto test]# du ./*
0    ./bak
4    ./docker-compose.yml
4    ./header.json
8    ./test.conf
4    ./test.env
4    ./testmv.sh
289228    ./test.tar
98056    ./test.tar.gz
10944    ./test.tbz
分析:($(du ./*))
[root@auto test]# echo ${fileinfo[@]}
4 ./docker-compose.yml 4 ./header.json 8 ./test.conf 4 ./test.env 4 ./testmv.sh 289228 ./test.tar 98056 ./test.tar.gz 10944 ./test.tbz

 8、linux下面的sed和awk的编写

  1)如何显示文本file.txt中第二大列大于56789的行?

awk -F "," '{if($2>56789){print $0}}' file.txt

$0表示整个当前行,$1表示每行第一个字段

 2)显示file.txt的1,3,5,7,10,15行?

  sed -n "1p;3p;5p;7p;10p;15p" file.txt

  awk 'NR==1||NR==3||NR==5||…||NR=15{print $0}' file.txt

3)将file.txt的制表符,即tab,全部替换成"|"

sed-i "s#\t#\|#g" file.txt

 

9、请用Iptables写出只允许10.1.8.179 访问本服务器的22端口。

  /sbin/iptables -A input -p tcp -dport 22 -s 10.1.8.179 -j ACCEPT

  /sbin/iptables -A input -p udp -dport 22 -s 10.1.8.179 -j ACCEPT

  /sbin/iptables -P input -j DROP

10、假设有一个脚本scan.sh,里面有1000行代码,并在vim模式下面,请按照如下要求写入对应的指令

 

1)将shutdown字符串全部替换成reboot

  :%s/shutdown/reboot/g

2)清空所有字符

  :%d

3)不保存退出

  q!

11、找出系统内大于50k,小于100k的文件,并删除它们。

  #!/bin/bash

  file=`find / -size +50k -size -100k`

  for i in $file;do

      rm -rf $i

  done

12、脚本(如:目录dir1、dir2、dir3下分别有file1、file2、file2,请使用脚本将文件改为dir1_file1、dir2_file2、dir3_file3) 

  #!/bin/bash

  file=`ls dir[123]/file[123]`

  for i in $file;do

      mv $i ${i%/*}/${i%%/*}_${i##*/}

  done
${i%/*}:从右边删除最短匹配,比如dir1/file1,删除/*后,变成dir1
${i%%/*}:从右边删除最长匹配,比如dir1/file1,删除/*后,变成dir1,因为只有一个/,最短和最长匹配是一样的。
${i##*/}:从左边删除最长匹配:比如dir1/file1,删除*/后,变成file1

13、 如何计算传递进来的参数 ?

$#

14 、如何在脚本中获取脚本名称 ?

$0

15、 如何检查之前的命令是否运行成功 ?

$?

16、 如何获取文件的最后一行 ?

tail-1

17、如何获取文件的第一行 ?

head-1 

18、假如文件中每行第一个元素是 FIND,如何获取第二个元素 

awk'{ if ($1 == "FIND") print $2}'

19、如何进行两个整数相加 ?

A=5
B=6
echo $(($A+$B))  # 方法 2
echo $[$A+$B]    # 方法 3
expr $A + $B     # 方法 4
echo $A+$B | bc  # 方法 5
awk 'BEGIN{print '"$A"'+'"$B"'}'   # 方法 6

20、判断是否存在

if [ ! -d "/data/" ]  #判断目录不存在
if [  -d "/data/" ]  #判断目录存在
if [ ! -f "/data/filename" ] #判断文件不存在
if [  -f "/data/filename" ] #判断文件不存在

-e 判断对象是否存在
-d 判断对象是否存在,并且为目录
-f 判断对象是否存在,并且为常规文件
-L 判断对象是否存在,并且为符号链接
-h 判断对象是否存在,并且为软链接
-s 判断对象是否存在,并且长度不为0
-r 判断对象是否存在,并且可读
-w 判断对象是否存在,并且可写
-x 判断对象是否存在,并且可执行
-O 判断对象是否存在,并且属于当前用户
-G 判断对象是否存在,并且属于当前用户组
-nt 判断file1是否比file2新  [ "/data/file1" -nt "/data/file2" ]
-ot 判断file1是否比file2旧  [ "/data/file1" -ot "/data/file2" ]

 [ -z STRING ] “STRING” 的长度为零则为真。

 [ -n STRING ] or [ STRING ] “STRING” 的长度为非零 non-zero则为真。

21、写出 shell 脚本中所有循环语法 ?

for:

for i in $(ls);do

echo item:$i

done

while:

#!/bin/bash
COUNTER=0
while [ $COUNTER -lt 10 ]; do
echo The counter is $COUNTER
let COUNTER=COUNTER+1
done

until:

#!/bin/bash
COUNTER=20
until [ $COUNTER -lt 10 ]; do
echo COUNTER $COUNTER
let COUNTER-=1
done

22、如何获取文本文件的第 10 行 ?

head -10 file|tail -1

23、命令:[ -z "" ] && echo 0 || echo 1 的输出是什么

0

 24、name=John && echo 'My name is $name' 的输出是什么

My name is $name

 25、name=John && echo “My name is $name” 的输出是什么

My name is John

26、如何只用 echo 命令获取字符串变量的一部分 ?

echo ${variable:x:y}
x - 起始位置
y - 长度

 例子:

variable="My name is Petras, and I am developer."
echo ${variable:11:6} # 会显示 Petras

27、如果给定字符串 variable="User:123:321:/home/dir",如何只用 echo 命令获取 /home/dir ?

echo ${variable##*:}

28、如何使用 awk 列出 UID 小于 100 的用户 ?

awk -F: '$3<100' /etc/passwd

29、如何在 bash shell 中更改标准的域分隔符为 ":" ?

 IFS=":"

30、如何打印变量的最后 5 个字符 ?

[root@auto ~]# str="aaaaaaaaaa"
[root@auto ~]# echo ${str: -5}
aaaaa
[root@auto ~]# echo ${str:-5}
aaaaaaaaaa
[root@auto ~]# str="aaaabbbb"
[root@auto ~]# echo ${str: +5}
bbb

31、将test.txt中的内容以大写显示

[root@auto ~]# cat test.txt 
aaaa
bbbb
cccc
[root@auto ~]# cat test.txt |tr a-z A-Z
AAAA
BBBB
CCCC

32、wc的用法:

[root@auto ~]# cat test.txt 
aaaa
bbbb
ccccc
[root@auto ~]# cat test.txt|wc -l
3
[root@auto ~]# cat test.txt|wc -c
16
[root@auto ~]# cat test.txt|wc -m
16
[root@auto ~]# cat test.txt|wc -w
3
[root@auto ~]# cat test.txt|wc -L
5

-c 统计字节数。

-l 统计行数。

-m 统计字符数。这个标志不能与 -c 标志一起使用。

-w 统计字数。一个字被定义为由空白、跳格或换行字符分隔的字符串。

-L 打印最长行的长度。

33、列出第二个字母是 e或z的文件或目录 

[root@auto ~]# ls
anaconda-ks.cfg  hzb  java0.log  java1.log  java1.log.lck  test.txt
[root@auto ~]# ls -d ?[ez]*
hzb  test.txt

如果是第三个字母:ls -d ??[ez]*

34、如何去除字符串中的所有空格

[root@localhost ~]# str="aa  vvvvvv ccc   dd"
[root@localhost ~]# echo $str|tr -d " "
aavvvvvvcccdd

35、写出输出数字 0 到 100 中 3 的倍数(0 3 6 9 …)的命令 ? 

for i in {0..100..3}; do echo $i; done
或
for (( i=0; i<=100; i=i+3 )); do echo "Welcome $i times"; done

36、如何打印传递给脚本的所有参数 ?

echo $*
或
echo $@

37、[ $a == $b ] 和 [ $a -eq $b ] 有什么区别

[ $a == $b ] - 用于字符串比较
[ $a -eq $b ] - 用于数字比较

38、如何检查字符串是否以字母 "abc" 开头 ?

[[ $string == abc* ]]

39、[[ $string == abc* ]] 和 [[ $string == "abc*" ]] 有什么区别 

  • [[ $string == abc* ]] - 检查字符串是否以字母 abc 开头
  • [[ $string == "abc*" ]] - 检查字符串是否完全等于 abc*

40、如何列出以 ad 或 ma 开头的用户名 ?

[root@auto hzb]# egrep "^ad|^ma" /etc/passwd|cut -d: -f1
adm
mail

41、$#,$*,$@,$$的用法 

$# 是传给脚本的参数个数

$0 是脚本本身的名字
$1 是传递给该shell脚本的第一个参数
$2 是传递给该shell脚本的第二个参数
$@ 是传给脚本的所有参数的列表
$* 是以一个单字符串显示所有向脚本传递的参数,与位置变量不同,参数可超过9
$$ 是脚本运行的当前进程ID号
$? 是显示最后命令的退出状态,0表示没有错误,其他表示有错误
#!/bin/bash
IFS=":";
echo $#
echo $*
echo $@
echo "$*"
echo "$@"
echo $$
echo $?
echo $!
IFS=" ";
[root@auto hzb]# ./test.sh 123 abc xyz
3
123 abc xyz
123 abc xyz
123:abc:xyz
123 abc xyz
31404
0

$* 会根据 IFS 的不同来组合值,而 $@ 则会将值用" "来组合值!

42、数组的一些操作 ?

[root@auto hzb]# arr=("xx" "aa" "yy" "bb") -定义数组
[root@auto hzb]# echo ${arr[0]}            -打印第一个元素
xx
[root@auto hzb]# echo ${arr[@]}            -打印全部元素
xx aa yy bb
[root@auto hzb]# echo ${!arr[@]}           -打印每个元素的下标
0 1 2 3
[root@auto hzb]# unset arr[2]              -删除第三个元素
[root@auto hzb]# echo ${arr[@]}
xx aa bb
[root@auto hzb]# arr[0]="BBB"              -重新给第一个元素设置值
[root@auto hzb]# echo ${arr[@]}
BBB aa bb

 

posted on 2018-11-28 09:56  波神  阅读(528)  评论(0编辑  收藏  举报