Shell编程实验

实验二 Shell编程

一、如果当前目录下有文件f1,但是没有f2,解释命令ls f1 f2 2>ef1 1>&2的运行结果。

PWN@PWN-PC:~/Desktop$ ls f1 f2 2>ef1 1>&2
PWN@PWN-PC:~/Desktop$ cat ef1 
ls: 无法访问'f2': 没有那个文件或目录
f1
echo hello 1>&2 | grep aaa
#结果显示:
PWN@PWN-PC:~/Desktop$ echo hello 1>&2 | grep aaa
hello

echo hello 2>&1 | grep aaa
#结果显示:
PWN@PWN-PC:~/Desktop$ echo hello 2>&1 | grep aaa
PWN@PWN-PC:~/Desktop$ 

echo hello 1>&2 | grep e
#结果显示:
PWN@PWN-PC:~/Desktop$ echo hello 1>&2 | grep e
hello

echo hello 2>&1 | grep e
#结果显示:
PWN@PWN-PC:~/Desktop$ echo hello 2>&1 | grep e
hello

在这里插入图片描述

解释:

  • 命令的执行分正确输出和错误输出,在使用管道符的时候,管道符只接收管道符前面命令传来d正确输出,这时候就需要用2>&1改变输出类型。
  • 管道符只进行传输,不能够存储。所以在第一次2>ef1时就将得到的错误输出重定向给了文件ef1,之后再将1>&2就是把正确输出当作错误输出,然后通过管道2再写入ef1中。

二、使用for循环语句编写一段B-shell程序,完成显示用户注册目录下的a_sub, b_sub子目录下的所有C程序文件及其目标文件的列表。

PWN@PWN-PC:~$ pwd
/home/PWN
PWN@PWN-PC:~$ ls
Desktop  Documents  Downloads  Music  Pictures  Videos
PWN@PWN-PC:~$ mkdir a_sub b_sub
PWN@PWN-PC:~$ ls
a_sub  b_sub  Desktop  Documents  Downloads  Music  Pictures  Videos
PWN@PWN-PC:~$ touch a_sub/file{1..5}.c
PWN@PWN-PC:~$ ls -l a_sub/
总用量 0
-rw-r--r-- 1 PWN PWN 0 108 22:09 file1.c
-rw-r--r-- 1 PWN PWN 0 108 22:09 file2.c
-rw-r--r-- 1 PWN PWN 0 108 22:09 file3.c
-rw-r--r-- 1 PWN PWN 0 108 22:09 file4.c
-rw-r--r-- 1 PWN PWN 0 108 22:09 file5.c
PWN@PWN-PC:~$ touch a_sub/flag{1..3}
PWN@PWN-PC:~$ ls -l a_sub/
总用量 0
-rw-r--r-- 1 PWN PWN 0 108 22:09 file1.c
-rw-r--r-- 1 PWN PWN 0 108 22:09 file2.c
-rw-r--r-- 1 PWN PWN 0 108 22:09 file3.c
-rw-r--r-- 1 PWN PWN 0 108 22:09 file4.c
-rw-r--r-- 1 PWN PWN 0 108 22:09 file5.c
-rw-r--r-- 1 PWN PWN 0 108 22:09 flag1
-rw-r--r-- 1 PWN PWN 0 108 22:09 flag2
-rw-r--r-- 1 PWN PWN 0 108 22:09 flag3
PWN@PWN-PC:~$ touch b_sub/sys_lib{1..5}.c
PWN@PWN-PC:~$ ls -l b_sub/
总用量 0
-rw-r--r-- 1 PWN PWN 0 108 22:10 sys_lib1.c
-rw-r--r-- 1 PWN PWN 0 108 22:10 sys_lib2.c
-rw-r--r-- 1 PWN PWN 0 108 22:10 sys_lib3.c
-rw-r--r-- 1 PWN PWN 0 108 22:10 sys_lib4.c
-rw-r--r-- 1 PWN PWN 0 108 22:10 sys_lib5.c
PWN@PWN-PC:~$ 
#--------------------------
#!/bin/bash
dirlst="a_sub b_sub "
for i in $dirlst
do
    cd $HOME/$i
    ls -l *.c
    ls -l flag*
done

三、掌握shell程序执行的三种基本方式,注意调试shell程序的命令书写方式有什么不同?

  • 脚本文件本身没有权限执行,没有x权限,则使用的方法,或脚本未指定shebang,那么久用指定解释器的方法去执行。

  • 含有x权限时,就用./去执行脚本

  • 用 . 或者source去执行

  • 重定向写入,bash < shell.sh

    调试

    如何调试Shell脚本
    \1) 检查语法错误:
    一般来说我们可以通过修改shell脚本的源代码,令其输出相关的调试信息来定位错误,那有没有不修改源代码来调试shell脚本的方法呢?答案就是使用shell的执行选,下面是一些常用选项的用法:
    -n 只读取shell脚本,但不实际执行
    -x 进入跟踪方式,显示所执行的每一条命令
    -c “string” 从strings中读取命令

    “-n”可用于测试shell脚本是否存在语法错误,但不会实际执行命令。在shell脚本编写完成之后,实际执行之前,首先使用“-n”选项来测试脚本是否存在语法错误是一个很好的习惯。因为某些shell脚本在执行时会对系统环境产生影响,比如生成或移动文件等,如果在实际执行才发现语法错误,您不得不手工做一些系统环境的恢复工作才能继续测试这个脚本。

    “-c”选项使shell解释器从一个字符串中而不是从一个文件中读取并执行shell命令。当需要临时测试一小段脚本的执行结果时,可以使用这个选项,如下所示:
    sh -c ‘a=1;b=2;let c= a + a+ a+b;echo “c=$c”’

    “-x"选项可用来跟踪脚本的执行,是调试shell脚本的强有力工具。“-x”选项使shell在执行脚本的过程中把它实际执行的每一个命令行显示出来,并且在行首显示一个”+"号。 "+"号后面显示的是经过了变量替换之后的命令行的内容,有助于分析实际执行的是什么命令。 “-x”选项使用起来简单方便,可以轻松对付大多数的shell调试任务,应把其当作首选的调试手段。

    \2) 调试工具-bashdb
    使用shell调试器bashdb,这是一个类似于GDB的调试工具,可以完成对shell脚本的断点设置,单步执行,变量观察等许多功能。

    使用bashdb进行debug的常用命令
    1.列出代码和查询代码类:
    l 列出当前行以下的10行
    - 列出正在执行的代码行的前面10行
    . 回到正在执行的代码行
    w 列出正在执行的代码行前后的代码
    /pat/ 向后搜索pat
    ?pat?向前搜索pat

    2.Debug控制类:
    h 帮助
    help 命令 得到命令的具体信息
    q 退出bashdb
    x 算数表达式 计算算数表达式的值,并显示出来
    !!空格Shell命令 参数 执行shell命令
    使用bashdb进行debug的常用命令(cont.)
    控制脚本执行类:
    n 执行下一条语句,遇到函数,不进入函数里面执行,将函数当作黑盒
    s n 单步执行n次,遇到函数进入函数里面
    b 行号n 在行号n处设置断点
    del 行号n 撤销行号n处的断点
    c 行号n 一直执行到行号n处
    R 重新启动
    Finish 执行到程序最后
    cond n expr 条件断点

四、为便于系统管理员对磁盘分配的管理,请编写一段B-shell程序,当文件系统/home占用空间改变时给出相应的信息提示。要求/home占用量在系统磁盘中为:

  1. 小于50%时,提示“用户文件系统磁盘使用负荷量小”。
  2. 大于50%,小于90%时,提示“用户文件系统磁盘使用负荷量正常”。
  3. 大于等于90%时,提示“用户文件系统磁盘使用负荷量偏大。

思路:怎么获取磁盘的空间情况?注意题目是需要知道一个目录的空间占用情况,和磁盘的占用不是一个问题。

单独运行df和du命令,查看用户注册目录的空间使用情况,然后再根据此二命令的输出,决定编程的方法。

#! /bin/bash
hm=`du -s /home|cut -f 1`
#用du查询/home目录大小,参数-s指定目录,cut截取内容
rt=`df /home|grep /|tr -s [:space:]|cut -f 2 -d " "`
#用df获得/home所在磁盘的大小,tr将不一致的间隔缩小成一个间隔,cut截取内容。
let ret=hm*100/rt
#用let运算,计算占比,因为let是整除而且不会显示小数,所以先乘一个100。
#调试:echo "$hm,$rt,$ret"
#调试:ret=30
case $ret in
        9[0-9])echo "用户文件系统磁盘使用负荷量偏大";;
        [5-8][0-9])echo "用户文件系统磁盘使用负荷量正常";;
        [0-4][0-9]|[0-9]) echo "用户文件系统磁盘使用负荷量小";;
esac

五、熟悉编程有关基础命令技巧和规则,如变量的命名,引用,位置变量及使用,输出语句及输出格式控制,输入语句和变量存储,从命令输出中提取字段值等。

变量

  • 变量定义与赋值时,变量与值之间不得有空格:var=“abcd”

    无需声明类型,且bash默认把所有变量都认为是字符串

  • 变量的打印:echo $var 、echo ${var}

  • 变量命名规则:

    1. 见名知意
    2. 只能包含数字、字母、下划线
    3. 不能以数字开头
    4. 不能用标点符号
    5. 变量名严格区分大小写
  • 变量的作用域:切换shell变量会丢失

    1. 本地变量,只存在于当前shell中,定义shell变量时变量名不需要加$符,本地变量只在用户当前shell生存期中有效

    2. 环境变量,全局变量,针对当前shell以及其任意子进程,环境变量也分自定义内置两种环境变量

    3. 局部变量:针对在shell函数或是shell脚本中定义的

    4. 位置参数变量:用于shell脚本中传递的参数(相当于命令执行时的参数、路径这种)

    5. 特殊变量:shell内置的特殊功效变量

      $0:获取shell脚本文件名,以及脚本路径

      $n:获取shell脚本的第n个参数,n在1~9之间,如$1,$2, 9 , 大于 9 则需要写 9,大于9则需要写 9,大于9则需要写{10},参数空格隔开

      $#:获取执行的shell脚本后面的参数总个数

      ∗ :获取 s h e l l 脚本所有参数,不加引号等同于 *:获取shell脚本所有参数,不加引号等同于 :获取shell脚本所有参数,不加引号等同于@作用,加上引号"$ *"作用,其主要用于接收参数为单个字符串“$1 $2 $3 $4 $5 $6 $7”

      $@:不加引号,效果同上,加上引号,是接收所有参数为独立字符串“$1” “$2” “$3” “$4” “$5” “$6” “$7”

    6. 特殊状态变量

      $?:这是一个状态变量,如果上一次的命令执行成功就会是0,错误1-255(错误码)

      echo $?:在脚本中用于查看是否执行成功某条指令

      $$:取得当前shell脚本的进程号

      $!:上一次后台进程的PID

      $_:取得上一次执行命令的最后一个参数

    7. 自定义变量

  • 引号变量

    1. 单引号变量,不识别特殊语法
    2. 双引号变量,能识别特殊符号
    3. 反引号变量,会将变量值识别为命令,且将命令执行的结果作为变量的值存储起来

    调用bsh解释器执行脚本,都会开启一个子shell,因此不保留当前的shell变量;

    调用source或者.符号,在当前shell环境下加载脚本,因此保留变量

  • 环境变量设置

    环境变量一般指的是用export内置命令导出的变量,用于定义shell的运行环境,保证shell命令的正确执行。

    shell通过环境变量确定登录的用户名、PATH路径、文件系统等各种应用。

    环境变量可以在命令行中临时创建,但是用户退出shell终端,变量就会丢失,如果要永久生效,需要修改环境变量配置文件。

    • 用户个人配置文件在:~/.bash_profile、 ~/.bashrc 远程登录用户特有文件

    • 全局配置文件/etc/profile 、 /etc/bashrc ,且系统建议最好创建在/etc/profile.d,而非直接修改主文件,修改全局配置文件,影响所有登录系统的用户

      优先用户自己配置的环境变量,其次才是全局变量

    • 检查系统环境变量的命令

      1. set,输出所有变量,包括全局变量、局部变量

        set |wc -l: 可以显示总行数

        set |grep ^name:找到以name开头的变量

      2. env,只显示全局变量

      3. declare,输出所有的变量,同set

      4. export,显示和设置环境变量值

    • 撤销环境变量、删除变量或函数:unset 变量名

    • 设置只读变量:readonly age=18,设置好之后变量不能再被修改,当shell结束,只读变量才失效。

      过滤出环境变量中的所有环境变量的名字:

      export | awk -F ‘[:=]’ ‘{print $3}’

六、编写一段shell程序完成:根据从键盘输入的学生成绩,显示相应的成绩标准(分出不及格、及格、中、良和优秀等)。

#!/bin/sh

read a
case $a in
        9[0-9]|100)echo "优秀";;
        8[0-9])echo "良";;
        7[0-9])echo "中";;
        6[0-9])echo "及格";;
        [0-5][0-9])echo "不及格";;
        *) echo "Wrong content!";;

esac

七、假设score.txt文件中保存了三个班级的学生的某门课程考试成绩,请编写一段shell程序计算每个班级的学生人数与平均分。

学习读取文件的方法。

如果数据文件的内容是3个班级5门不同课程的内容,程序应该怎么调整?

#!/bin/sh
#这个程序的操作与目标文件中的内容格式关系很大,就是根据文件内容格式来进行的操作

class="计科201 计科202 计科203"
for i in $class
do
	total=`grep -F $i score.txt|wc -l`
	#以班级为关键词检索出相关行(grep -F $i)并统计行数(wc -l),行数即是人数。
	average=`grep -F $i score.txt|awk -F: '{sum+=$3}END{print ":",sum/NR}'`
	#在之前检索出来的一个班级的内容中截取第三列所在的内容,并进行累加得到sum,sum再除以内置变量NR(行数)就得到平均值了。
	echo "$i班:$total人,平均分$average。"
done
#文本格式
计科201:a:75
计科202:b:76
计科201:c:77
计科203:d:78
计科202:e:79
计科203:f:80
#!/bin/sh

class="计科201 计科202 计科203"
for i in $class
do
	total=`grep -F $i score1.txt|wc -l`
	echo "$i班:$total人"
	for j in 3 4 5 6 7
	do
		x=`sed -n '1p' score1.txt|awk -F" " '{print $'$j'}'`
		#原理和上一个一样,这里就是简单地获取第一行的内容,读取科目,便于简化操作。
		average=`grep -F $i score1.txt|awk -F" " '{sum+=$'$j'}END{print ":",sum/NR}'`
		echo "$i$x平均分:$average"
	done
done
#文件内容格式
班级 姓名 语文 数学 英语 计算机 网络攻防
计科201 a 110 130 125 99 100
计科201 b 99 101 145 80 75
计科201 c 107 112 126 68 60
计科201 d 113 135 140 95 95
计科202 e 121 140 130 68 52
计科202 f 111 150 30 56 32
计科202 g 141 123 86 23 51
计科202 h 90 25 35 60 75
计科202 i 51 36 85 62 34
计科203 j 134 62 140 55 66
计科203 k 111 112 113 70 71
计科203 l 142 143 144 99 100
计科203 m 150 150 150 100 100
计科203 n 100 100 100 100 100
计科203 o 101 101 101 101 101
实验目的 Linux操作系统shell是用户与系统内核沟通的介,它为用户使用操作系统的服务提供了一个命令界面。用户在shell提示符($或#)下输入的每一个命令都由shell先解释,然后传给内核执行。本实验要求用C语言编写一个简单的shell程序,希望达到以下目的:  用C语言编写清晰易读、设计优良的程序,并附有详细的文档。  熟悉使用Linux下的软件开发工具,例如gcc、gdb和make。  在编写系统应用程序时熟练使用man帮助手册。  学习使用POSIX/UNIX系统调用、对进程进行管理和完成进程之间的通信,例如使用信号和管道进行进程间通信。  理解并发程序的同步问题。  锻炼在团队成员之间的交流与合作能力。 2. 实验要求 1. ysh解释程序的重要特征 本实验要实现一个简单的命令解释器,也就是Linuxshell程序。实验程序起名为ysh,要求其设计类似于目前流行的shell解释程序,如bash、csh、tcsh,但不需要具备那么复杂的功能。ysh程序应当具有如下一些重要的特征:  能够执行外部程序命令,命令可以带参数。 . 。  能够执行fg、bg、cd、history、exit等内部命令。  使用管道和输入输出重定向。  支持前后台作业,提供作业控制功能,包括打印作业的清单,改变当前运行作业的前台/后台状态,以及控制作业的挂起、止和继续运行。 除此之外,在这个实验还须做到:  使用make工具建立工程。  使用调试器gdb来调试程序。  提供清晰、详细的设计文档和解决方案。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿拉垮神登

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值