当前位置:文档之家› 编写自己的Shell 解释器

编写自己的Shell 解释器

编写自己的Shell 解释器
编写自己的Shell 解释器

编写自己的 Shell 解释器
摘要:本期的目的是向大家介绍 shell 的概念和基本原理,并且在此基础上动手做
一个简单 shell 解释器。同时,还将就用到的一些 linux 环境编程的知识做一定讲解。 本文适合的读者对象 对 linux 环境上的 c 语言开发有一定经验; 对 linux 环境编程(比如进程、管道)有一点了解。
概述
本章的目的是带大家了解 shell 的基本原理, 并且自己动手做一个 shell 解释器。 为此, 首先,我们解释什么是 shell 解释器。 其次,我们要大致了解 shell 解释器具有哪些功能; 最后,我们具体讲解如何实现一个简单的 shell 解释器,并对需要用到一些 linux 环 境编程的知识做一定讲解,并提醒你如果想深入掌握,应该去看哪些资料。
Shell 解释器是什么?
Shell 解释器是一个程序。对,是一个程序,而且,它就在我们的身边。在 linux 系统 中,当我们输入用户名和密码登陆之后,我们就开始执行一个 shell 解释器程序,通常是 /bin/bash, 当然也可以是别的, 比如/bin/sh。 (详细概念请看第一期中的 shell 有关部分) 提示:在 /etc/passwd 文件中,每个用户对应的最后一项,就指定了该用户登陆之后, 要执行的 shell 解释器程序。 在 linux 字符界面下,输入 man bash 调出 bash 的帮助页面 帮助的最开始就对 bash 下了一个定义:

bash 是一个兼容于 sh 的命令语言解释器,它从标准输入或者文件中读取命令并执 行。它的意图是实现 IEEE POSIX 标准中对 shell 和工具所规范的内容。
Shell 解释器的作用
在登陆 linux 系统之后,屏幕上就会出现一行提示符,在我的机器上,是这样的: [root@stevens root]#
这行提示符就是由 bash 解释器打印出来的,这说明,现在已经处于 bash 的控制之下 了,也同时提示用户,可以输入命令。用户输入命令,并回车确认后,bash 分析用户的命 令,如果用户的命令格式正确,那么 bash 就按照用户的意思去做一些事情。 比如,用户输入: [root@stevens root]# echo “hello, world” 那么,bash 就负责在屏幕上打印一行“hello world”。
如果,用户输入: [root@stevens root]# cd /tmp 那么,bash 就把用户的当前目录改变为 /tmp。 所以,shell 解释器的作用就是对用户输入的命令进行“解释”,有了它,用户才可以 在 linux 系统中任意挥洒。没有它的帮助,你纵然十八般本领在身,也施展不出。 bash 每次在“解释”完用户命令之后,又打印出一行提示符,然后继续等待用户的下 一个命令。这种循环式的设计,使得用户可以始终处于 bash 的控制之下。除非你输入 ex it、logout 明确表示要退出 bash。
Shell 语法梗概
我们不停的命令 bash 做这做那, 一般情况下它都很听话, 按你的吩咐去做。 可有时候, 它会对你说:“嗨,老兄,你的命令我理解不了,无法执行”。例如,你输入这样的命令:

[root@stevesn root]# aaaaaa
bash 会告诉你: bash: aaaaaa: command not found
是的, 你必须说的让它能听懂, 否则它就给你这么一句抱怨, 当然也还会有其它的牢骚。 那么,什么样格式的命令,它才能正确理解执行了?这就要引出 shell 的语言规范了。 Shell 作为一个命令语言解释器,有一套自己的语言规范,凡是符合这个规范的命令, 它就可以正确执行,否则就会报错。这个语言规范是在 IEEE POSIX 的第二部分:“shell 和 tools 规范”中定义的。关于这份规范,可以在这里看到。 官方的东西,总是冗长而且晦涩,因为它要做到面面俱到且不能有破绽。如果读者有兴 趣,可以仔细研究这份规范。而我们的目的只是理解 shell 的实现思想,然后去实现一个简 单的 shell 解释器,所以没必要陷入枯燥的概念之中。 现在请继续在 linux 字符界面下输入 man bash,调出 bash 的帮助页面,然后找到 “shell 语法”那一部分,我们就是以这里的描述作为实现的依据。 在 bash 帮助的“shell 语法”一节,是这样来定义 shell 语法的: ? 简单命令 简单命令是(可选的)一系列变量赋值, 紧接着是空白字符分隔的词和重定向符 号, 最后以一个控制操作符结束. 第一个词指明了要执行的命令, 它被作为第 0 个 参数. 其余词被作为这个命令的参数. 这个定义可以这样来理解: 1、 可以有变量赋值,例如 a=10 b=20 export a b 2、 “词”是以空白字符分隔开的,空白字符包括制表符(tab)和空格,例如: ls /tmp 就是两个词,一个 ls,一个 /tmp

3、可以出现重定向符号,重定向符号是“>”和“<”,例如: echo “hello world” > /tmp/log 4、 简单命令结束于控制操作符,控制操作符包括: || & && ; ;; ( ) |
例如,用户输入: ls /tmp 用户最后敲的回车键就是控制操作符 newline,表示要结束这个简单命令。 如果用户输入: echo “100” ; echo “200” 那么这是两个简单命令,第一个结束于“;”,第二个结束于 newline。 5、 简单命令的第一个词是要执行的命令,其余的词都是这个命令的参数,例如: echo “hello world” echo 第一个 echo 是命令,第二个词“hello world”是参数 1,第三个词 echo 是参数 2,而不再作为一个命令了。 简单命令是 shell 语法中最小的命令,通过简单命令的组合,又可以得到管道 命令和列表命令。 ? 管道(命令) 管道是一个或多个简单命令的序列,两个简单命令之间通过管道符号(“|”) 来分隔 例如 echo “hello world” | wc –l 就是一个管道,它由两个简单命令组成,两个简单命令之间用管道符号分隔开。 我们可以看到,管道符号“|”也是属于上面提到的控制操作符。 根据这个定义,一个简单命令也同时是一个管道。 管道的作用是把它前面的那个简单命令的输出作为后面那个简单命令的输入,就 上面这个例子来说:

echo “hello world” 本来是要在标准输出(屏幕)上打印 “hello world” 的,但是管道现在不让结果输出到屏幕上,而是“流”到 wc –l 这个简单命令,wc –l 就把“流”过来的数据作为它的标准输入进行计算,从而统计出结果是 1 行。 关于管道更详细的内容,我们在后面具体实现管道的时候再说明。 ? 列表(命令): 列表是一个或多个管道组成的序列,两个管道之间用操作符 ;, &, &&, 或 || 分隔。我们看到,这几个操作符都属于控制操作符。 例如 echo “hello world” | wc –l ; echo “nice to meet you” 就是一个列表,它由两个管道组成,管道之间用分号(;)隔开 分号这种控制操作符仅仅表示一种执行上的先后顺序。 ? 复合命令 这个定义比较复杂, 实现起来也有相当难度, 在咱们这个示例程序中, 就不实现了。 以上是 shell 语法规范的定义, 我们的 shell 程序就是要以此规范为依据, 实现对简 单命令、管道和列表的解释。对于列表中的控制操作符,我们只支持分号(;),其它的留 给读者自己来实现。 接下来,我们具体介绍如何实现一个简单的 shell 解释器。
实现 shell 实例
程序主框架
主程序很简单,它在做一些必要的初始化工作之后,进入这样一个循环: ? ? ? ? 打印提示符并等待用户输入 获取用户输入 分析用户输入 解释执行;
如果用户输入 logout 或者 exit 之后,才退出这个循环。 用类似伪代码的形式表示如下:

while(1) { print_prompt(); get_input(); parse_input(); if(“logout” || “exit”) break; do_cmd(); }
读取用户输入
如何获取用户输入?一种方法是通过 getchar() 从标准输入每次读一个字符,如果读 到的字符是 ‘\n’,说明用户键入了回车键,那么就把此前读到的字符串作为用户输入的 命令。 代码如下:
int len = 0; int ch; char buf[300];
ch = getchar(); while(len < BUFSIZ && ch != '\n') { buf[len++] = ch; ch = getchar(); } if(len == BUFSIZ) {

printf("command is too long\n"); break; } buf[len] = '\n'; len++; buf[len] = 0;
但是,我们注意到,在 bash 中,可以用“<-”和“->”键在命令行中左右移动,可以 用上下键调用以前使用的命令,可以用退格键来删除一个字符,还可以用 tab 键来进行命 令行补全。我们的 shell 如果也要支持这些功能,那么就必须对这些键进行处理。这样仅仅 对用户输入的读取就非常麻烦了。 实际上,任何需要一个获取用户输入的程序,都会涉及到同样的问题,如何象 bash 那 样处理键盘?GNU readline 库就是专门解决这个问题的, 它把对键盘的操作完全封装起来, 对外只提供一个简单的调用接口。有了它,对键盘的处理就不再让人头疼了。 关于 readline 库的详细信息, 可以通过 man readline 来看它的帮助页面。 在我们的 shell 程序中,我是这样来使用 readline 的。
char* line; char prompt[200]; while(1) { set_prompt(prompt); if(!(line = readline(prompt))) break; 。。。。。。 }

首先通过 set_prompt() 来设置要输出的提示符,然后以提示符作为参数调用 readli ne(),这个函数等待用户输入,并动态创建一块内存来保存用户输入的数据,可以通过返回 的指针 line 得到这块内存。 在每次处理完用户输入的命令之后, 我们必须自己负责来释放 这块内存。 有了 readline 之后,我们就可以象 bash 那样使用键盘了。 在通过 readline 获取用户输入之后,下一步就是对用户输入的命令进行分析。
命令行分析
对命令行的分析,实际上是一个词法分析过程。学过编译原理的朋友,都听说过 lex 和 yacc 的大名,它们分别是词法分析和语法分析工具。Lex 和 yacc 都有 GNU 的版本(op en source 的思想实在是太伟大了,什么好东东都有免费的用),分别是 flex 和 bison。 所谓“工欲善其事,必先利其器”,既然有这么好的工具,那我们就不必辛辛苦苦自己 进行词法分析了。对,我们要用 lex 来完成枯燥的命令行词法分析工作。 “去买本《lex 与 yacc》(中国电力出版社)来看吧。第一次学当然稍微有点难度,不 过一旦掌握了,以后再碰到类似问题,就可以多一个利器,可以节省劳动力了。 在我们的这个 shell 程序中,用 flex 来完成词法分析工作。相对语法分析来说,词 法分析要简单的多。由于我们只是做一个简单的 shell,因此并没有用到语法分析,而实际 上在 bash 的实现代码中,就用到了语法分析和 yacc。 关于 lex 的细节,在这里我就不能多说了。Lex 程序,通常分为三个部分,其中进行 语法分析工作的就是它的第二部分: “规则”。规则定义了在词法分析过程中,遇到什么 样的情况,应该如何处理。 词法分析的思路,就是根据前面定义的“shell 语法规范”来把用户输入的命令行拆解 成 首先,我们要把用户输入的命令,以空白字符(tab 键或者空格)分隔成一个个的参数, 并把这些参数保存到一个参数数组中。但是,这其中有几种特殊情况。 一、如果遇到的字符是“;”、“>”、“<”或“|”,由于这些符号是管道或者列表 中所用到的分隔符,因此必须把它们当作一个单独的参数。 二、以双引号(”)括起来的字符串要作为一个单独的参数,即使其中出现了空白字符、 “;”、“>”、“<”、“|”。其实,在 POSIX 标准中,对引号的处理相当复杂,不仅包括 双引号(”),还有单引号(’)、反引号(`),在什么情况下,应该用什么样的引号以 及对引号中的字符串应该如何解释, 都有一大堆的条款。 我们这里只是处理一种极简单的情 况。

其次,如果我们遇到换行符(’\n’),那么就结束本次命令行分析。根据前面定义的 shell 语法规范,最上层的是列表命令,因此下一步是把所有的参数作为一个列表命令来 处理。
根据这个思路,我们来看对应的 lex 规则。 %%
"\""
{BEGIN QUOTE;}
[^\n"]+ {add_arg(yytext);} "\"" \n ";" ">" "<" "|" {BEGIN 0;}
{BEGIN 0; do_list_cmd(); reset_args();} {add_simple_arg(yytext);} {add_simple_arg(yytext);} {add_simple_arg(yytext);} {add_simple_arg(yytext);} [^ \t\n|<>;"]+ {add_arg(yytext);}
\n .
{do_list_cmd(); reset_args();} ; %%
我们对这些规则逐条解释: 1-4 这 4 条规则,目的是为了在命令行中支持引号,它们用到了 lex 规则的状 态特性。

1、"\""
{BEGIN QUOTE;}
2、[^\n"]+ {add_arg(yytext);} 3、"\"" 4、\n {BEGIN 0;} {BEGIN 0; do_list_cmd(); reset_args();}
1、 如果扫描到引号( “),那么进入 QUOTE 状态。在这个状态下,即使扫描到空 白字符或“;”、“>”、“<”、“|”,也要当作普通的字符。 2、 如果处于 QUOTE 状态,扫描到除引号和回车以外的字符,那么调用 add_arg()函 数,把整个字符串加入到参数数组中。 3、 如果处于 QUOTE 状态,扫描到引号,那么表示匹配了前面的引号,于是恢复到默 认状态。 4、 如果处于 QUOTE 状态,扫描到回车,那么结束了本次扫描,恢复到默认状态,并 执行 do_list_cmd(),来执行对列表命令的处理。
以下几条规则,是在处于默认状态的情况下的处理。 5、";" 6、">" 7、"<" 8、"|" 9、[^ \t\n|<>;"]+ 10、\n {add_simple_arg(yytext);} {add_simple_arg(yytext);} {add_simple_arg(yytext);} {add_simple_arg(yytext);} {add_arg(yytext);} {do_list_cmd(); reset_args();}
5、 如果遇到分号(;),因为这是一个列表命令结束的操作符,所以作为一个单独的 参数,执行 add_simple_arg(),将它加入参数数组。 6、 如果遇到 >,因为这是一个简单命令结束的操作符,所以作为一个单独的参数, 执行 add_simple_arg(),将它加入参数数组。

7、 如果遇到 <,因为这是一个简单命令结束的操作符,所以作为一个单独的参数, 执行 add_simple_arg(),将它加入参数数组。 8、 如果遇到管道符号(|),因为这是一个管道命令结束的操作符,所以作为一个单 独的参数,执行 add_simple_arg(),将它加入参数数组。 9、 对于不是制表符(tab)、换行符(’\n’)、| 、<、>和分号(;)以外的字符 序列,作为一个普通的参数,加入参数数组。 10、 如果遇到换行符,那么结束本次扫描,执行 do_list_cmd(),来执行对列表
命令的处理。 11、 对于任意其它字符,忽略
通过 lex 的“规则”把用户输入的命令行分解成一个个的参数之后,都要执行 do_li st_cmd() 来执行对列表命令的处理。
命令处理
首先是对处于“shell 语法规范”中最上层的列表命令的处理。 ?
列表命令的处理过程:
依次检查参数数组中的每一个参数,如果是分号(;),那么就认为分号前面的所有参 数组成了一个管道命令, 调用 do_pipe_cmd() 来执行对管道命令的处理。 如果扫描到最后, 不再有分号出现,那么把剩下的所有参数作为一个管道命令处理。 代码很简单: static void do_list_cmd() { int i = 0; int j = 0; char* p; while(argbuf[i]) { if(strcmp(argbuf[i], ";") == 0) {// ; p = argbuf[i];

argbuf[i] = 0; do_pipe_cmd(i-j, argbuf+j); argbuf[i] = p; j = ++i; } else i++; } do_pipe_cmd(i-j, argbuf+j); }

接下来是对管道命令的处理。
管道命令的处理
管道是进程间通信(IPC)的一种形式,关于管道的详细解释在《unix 高级环境编程》 第 14 章:进程间通信以及《unix 网络编程:第 2 卷:进程间通信》第 4 章:管道和 FIFO 中可以看到。 我们还是来看一个管道的例子: [root@stevens root]# echo “hello world”|wc –c |wc –l
在这个例子中,有三个简单命令和两个管道。 第一个命令是 echo “hello world”,它在屏幕上输出 hello world。由于它后面是 一个管道,因此,它并不在屏幕上输出结果,而是把它的输出重定向到管道的写入端。 第二个命令是 wc –c,它本来需要指定输入源,由于它前面是一个管道,因此它就从 这个管道的读出端读数据。 也就是说读到的是 hello world, –c 是统计读到的字符数, wc 结果应该是 12。由于它后面又出现一个管道,因此这个结果不能输出到屏幕上,而是重定 向到第二个管道的写入端。 第三个命令是 wc –l。它同样从第二个管道的读出端读数据,读到的是 12,然后它统 计读到了几行数据,结果是 1 行,于是在屏幕上输出的最终结果是 1。 在这个例子中,第一个命令只有一个“后”管道,第三个命令只有一个“前”管道,而 第二个命令既有“前”管道,又有“后”管道。 在我们处理管道命令的 do_pipe_cmd()函数中,它的处理过程是: 首先定义两个管道 prefd 和 postfd,它们分别用来保存“前”管道和“后”管道。此 外,还有一个变量 prepipe 来指示“前”管道是否有效。 然后依次检查参数数组中每一个参数,如果是管道符号(|),那么就认为管道符号前 面所有的参数组成了一个简单命令,并创建一个“后”管道。如果没有“前”管道(管道中

第一个简单命令是没有“前”管道的),那么只传递“后”管道来调用 do_simple_cmd(), 否则,同时传递“前”管道和“后”管道来调用 do_simple_cmd()。 执行完以后,用“前”管道来保存当前的“后”管道,并设置“前”管道有效标识 pre pipe,继续往后扫描。如果扫描到最后,不再有管道符号出现,那么只传递“前”管道来调 用 do_simple_cmd()。 代码如下: int i = 0, j = 0, prepipe = 0; int prefd[2], postfd[2]; char* p; while(argv[i]) { if(strcmp(argv[i], "|") == 0) { // pipe p = argv[i]; argv[i] = 0; pipe(postfd); //create the post pipe if(prepipe) do_simple_cmd(i-j, argv+j, prefd, postfd); else do_simple_cmd(i-j, argv+j, 0, postfd); argv[i] = p; prepipe = 1; prefd[0] = postfd[0]; prefd[1] = postfd[1]; j = ++i; } else i++;

} if(prepipe) do_simple_cmd(i-j, argv+j, prefd, 0); else do_simple_cmd(i-j, argv+j, 0, 0);
最后,我们分析简单命令的处理过程。
简单命令处理过程
我们已经看到,对列表命令和管道命令的处理,实际只是一个分解过程,最终命令的执 行还是要由简单命令来完成。 在简单命令的处理过程中,必须考虑以下情况: 1、区分内部命令和外部命令 根据简单命令的定义, 它的第一个参数是要执行的命令, 后面的参数作为该命令的参数。 要执行的命令有两种情况: 一种是外部命令,也就是对应着磁盘上的某个程序,例如 wc、ls 等等。对这种外部命 令,我们首先要到指定的路径下找到它,然后再执行它。 二是内部命令,内部命令并不对应磁盘上的程序,例如 cd、echo 等等,它需要 shell 自己来决定该如何执行。例如对 cd 命令,shell 就应该根据它后面的参数改变当前路径。 对于外部命令,需要创建一个子进程来执行它,而对于内部命令,则没有这个必要。 外部命令的执行,是通过 exec 函数来完成的。有六种不同形式的 exec 函数,它们可 以统称为 exec 函数。我们使用的是 execv()。关于 exec 的细节,请看《unix 环境高级编 程》第 8 章:进程控制。 对于内部命令,我们目前支持五种,分别是: exit:退出 shell 解释器 cd:改变目录 echo:回显

export:导入或显示环境变量 history:显示命令历史信息 这几个内部命令分别由 do_exit()、do_cd()、do_echo()、do_export()、do_h istory()来实现。 2、处理重定向 在简单命令的定义中,包括了对重定向的支持。重定向有多种情况,最简单的是输入重 定向和输出重定向,分别对应着“<”和“>”。 输入重定向,就是把“<”后面指定的文件作为标准输入,例如: wc < xxx 表示把 xxx 这个文件的内容作为 wc 命令的输入。 输出重定向,就是把“>”后面指定的文件作为标准输出,例如: echo “hello world” > xxx 表示把 echo “hello world” 的结果输入到 xxx 文件中,而不是屏幕上。 为了支持重定向,我们首先对简单命令的参数进行扫描,如果遇到“<”或者“>”那么 就认为遇到了重定向,并把“<”或者“>”符号后面的参数作为重定向的文件名称。 对于输入重定向,首先是以只读方式打开“<”后面的文件,并获得文件描述符,然后 将该文件描述符复制给标准输入。 对于输出重定向,首先是以写方式打开“>”后面的文件,并获得文件描述符,然后将 该文件描述符复制给标准输出。 具体实现在 predo_for_redirect() 函数中: 3、管道的实现 管道的实现实际上也是一种重定向的处理。对于“前”管道,类似于输入重定向,不同 的是,它是把一个指定的描述符(“前”管道的输出端)复制给标准输入。对于“后”管道, 类似于输出重定向,不同的是,它把一个指定的描述符(“后”管道的输入端)复制给标准 输出。 在对管道的处理上, 还必须要注意管道和输入或输出重定向同时出现的情况, 如果是一 个“前”管道和一个输入重定向同时出现,那么优先处理输入重定向,不再从“前”管道中 读取数据了。同样,如果一个“后”管道和一个输出重定向同时出现,那么优先处理输出重 定向,不再把数据输出到“后”管道中。

至此, 我们已经描述了实现一个简单的 shell 解释器的全部过程, 相应的代码和 makefile 在我们的网站上可以下载。 希望大家能够结合代码和这篇文章, 亲自动手做一次, 以加深对 shell 解释器的理解。

Shell命令

Shell Shell 就是用户与操作系统内核之间的接口,起着协调用户与系统的一致性和在用户与系统之间进行交互的作用。 4.1.1 Shell 的基本概念 1. 什么是S hell Shell 就是用户与操作系统内核之间的接口,起着协调用户与系统的一致性和在用户与系统之间进行交互的作用。Shell 在L inux 系统中具有极其重要的地位,如图4-1 所示

第 4 章 Shell 与 V i 编辑器 - 71 - diff grep vi multitasking sh gcc device hardware interface kernn e l TCP/IP stack bash utilii t es 图 4-1 Linux 系统结构组成 2. Shell 的功能 Shell 最重要的功能是命令解释,从这种意义上来说,Shell 是一个命令解释器。Linux 系统中的所有可执行文件都可以作为 Shell 命令来执行。将可执行文件作一个分类,如表 4-1 所示。 表 4-1 可执行文件的分类 部的解释器将其解释为系统功能调用并转交给内核执行;若是外部命令或实用程序就试图 在硬盘中查找该命令并将其调入内存,再将其解释为系统功能调用并转交给内核执行。在 查找该命令时分为两种情况: 用户给出了命令路径,Shell 就沿着用户给出的路径查找,若找到则调入内存,若没有 则输出提示信息; 用户没有给出命令的路径,Shell 就在环境变量 PATH 所制定的路径中依次进行查找, 若找到则调入内存,若没找到则输出提示信息。 图 4-2 描述了 S hell 是如何完成命令解释的。

Linux实验项目四--shell编程

实验项目四shell编程 一、实验目的 (1)了解shell的作用和主要分类; (2)掌握bash的建立和执行方式; (3)掌握bash的基本语法; (4)学会编写shell脚本。 二、实验内容 (1)shell脚本的建立和执行; (2)历史命令和别名定义; (3)shell变量和位置参数、环境变量; (4)bash的特殊字符; (5)一般控制结构; (6)算术运算及bash函数。 三.实验软件 VMWare Workstation 5.0; Red hat linux 9.0; 四.实验主要步骤 1、利用vi建立一个脚本文件,其中包括date,cal,pwd,ls等常用命令。然后以不同方式执行脚本。 2、运行history命令,配置历史命令环境。 3、体会bash的命令补齐功能。 4、用alias定义别名,然后执行。 5、编辑如下脚本进行执行: 6、编写一个shell脚本,求斐波那契数列的前10项及总和。 7、设计一个程序cuts,它由标准输入读取数据,获取由第一个参数n和第二个参数m所限定范围的数据,n和m都是整数,即从输入的字符串中抽取第n个字符至第m个字符之间的所有字符(包括这两个字符)。例如: $cuts 11 14 tis is a test of cuts program (输入) tst(显示结果

五.实验结果 1、利用vi建立一个脚本文件,其中包括date,cal,pwd,ls等常用命令。然后以不同方式执行脚本。 2、运行history命令,配置历史命令环境。 3、体会bash的命令补齐功能。 双击tab键,能列出所有符合条件的结果,只有唯一结果时单击可补全。 4、用alias定义别 名,然后执行。 5、编辑如下脚本进行执行:

linux+shell脚本语言基础知识

linux shell脚本语言基础知识 一.shell简介 Linux系统的shell作为操作系统的外壳,为用户提供使用操作系统的界面,更确切的说,shell是用户与Linux操作系统沟通的桥梁。用户既可以输入命令执行,又可以利用Shell脚本编程,完成更加复杂的操作。 shell是一个命令解释器,它从输入设备读取命令,再将其转为计算机可以了解的指令,然后执行它。在linux中,shell又不仅是简单的命令解释器,而且是一个全功能的编程环境。 Linux的Shell种类众多,常见的有:Bourne Shell(/usr/bin/sh或/bin/sh)、Bourne Again Shell(/bin/bash)、C Shell(/usr/bin/csh)、K Shell (/usr/bin/ksh)、Shell for Root(/sbin/sh),等等。不同的Shell语言的语法有所不同,所以不能交换使用。每种Shell都有其特色之处,基本上,掌握其中任何一种就足够了。通常用Bash,也就是Bourne Again Shell进行编程。 二.shell使用 1.建立和运行shell程序 shell脚本程序:按照一定的语法结构把若干linux命令组织在一起,是这些命令按照我们的要求完成一定的功能。它可以进行类似程序的编写,并且不需要编译就能执行。(只需修改其权限) 像编写高级语言的程序一样,编写shell程序需要一个文本编辑器,如VI和VIM,通常使用VIM文本编辑器,支持更便利的插入模式。 首先使用VIM编辑器编辑一个hello.sh文件: #!/bin/bash #hello world example

ubuntu shell 使用命令大全

ubuntu shell 使用命令大全 前言 下面的命令大都需要在控制台/ 终端/ shell 下输入。 控制台, 终端, 和shell 意味着同样一件事- 一个命令行界面,他可以用来控制系统。 打开一个控制台: 应用程序--> 附件--> 终端 任何一个使用'sudo' 作为前缀的命令都需要拥有管理员(或root) 访问权限。所以你会被提示输入你自己的密码。 安装升级 查看软件xxx安装内容 dpkg -L xxx 查找软件库中的软件 apt-cache search 正则表达式 或 aptitude search 软件包 显示系统安装包的统计信息 apt-cache stats 显示系统全部可用包的名称 apt-cache pkgnames 显示包的信息 apt-cache show k3b 查找文件属于哪个包 apt-file search filename 查看已经安装了哪些包 dpkg -l 查询软件xxx依赖哪些包 apt-cache depends xxx 查询软件xxx被哪些包依赖 apt-cache rdepends xxx 增加一个光盘源 sudo apt-cdrom add 系统升级 sudo apt-get update (这一步更新包列表) sudo apt-get dist-upgrade (这一步安装所有可用更新) 或者 sudo apt-get upgrade (这一步安装应用程序更新,不安装新内核等) 清除所有已删除包的残馀配置文件 dpkg -l |grep ^rc|awk '{print $2}' |sudo xargs dpkg -P 如果报如下错误,证明你的系统中没有残留配置文件了,无须担心。 dpkg: --purge needs at least one package name argument Type dpkg --help for help about installing and deinstalling packages [*]; Use `dselect' or `aptitude' for user-friendly package management; Type dpkg -Dhelp for a list of dpkg debug flag values; Type dpkg --force-help for a list of forcing options; Type dpkg-deb --help for help about manipulating *.deb files; Type dpkg --license for copyright license and lack of warranty (GNU GPL) [*]. Options marked [*] produce a lot of output - pipe it through `less' or `more' ! 编译时缺少h文件的自动处理 sudo auto-apt run ./configure 查看安装软件时下载包的临时存放目录

Shell脚本编写基础

Shell本身是一个用C语言编写的程序,它是用户使用Linux的桥梁。Shell既是一种命令语言,又是一种程序设计语言。作为命令语言,它交互式地解释和执行用户输入的命令;作为程序设计语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支。它虽然不是Linux系统核心的一部分,但它调用了系统核心的大部分功能来执行程序、建立文件并以并行的方式协调各个程序的运行。因此,对于用户来说,shell 是最重要的实用程序,深入了解和熟练掌握shell的特性极其使用方法,是用好Linux系统的关键。可以说,shell使用的熟练程度反映了用户对Linux使用的熟练程度。 一、什么是shell 当一个用户登录Linux系统之后,系统初始化程序init就为每一个用户运行一个称为shel l(外壳)的程序。那么,shell是什么呢?确切一点说,shell就是一个命令行解释器,它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序,用户可以用shell 来启动、挂起、停止甚至是编写一些程序。 当用户使用Linux时是通过命令来完成所需工作的。一个命令就是用户和shell之间对话的一个基本单位,它是由多个字符组成并以换行结束的字符串。shell解释用户输入的命令,就象DOS里的https://www.doczj.com/doc/c36303927.html,所做的一样,所不同的是,在DOS中,https://www.doczj.com/doc/c36303927.html,只有一个,而在Linux下比较流行的shell有好几个,每个shell都各有千秋。一般的Linux系统都将bash作为默认的shell。 二、几种流行的shell 目前流行的shell有ash、bash、ksh、csh、zsh等,你可以用下面的命令来查看你自己的shell类型: #echo $SHELL $SHELL是一个环境变量,它记录用户所使用的shell类型。你可以用命令: #shell-name 来转换到别的shell,这里shell-name是你想要尝试使用的shell的名称,如ash等。这个命令为用户又启动了一个shell,这个shell在最初登录的那个shell之后,称为下级的shell或子shell。使用命令: $exit 可以退出这个子shell。 使用不同的shell的原因在于它们各自都有自己的特点,下面作一个简单的介绍: 1.ash ash shell是由Kenneth Almquist编写的,Linux中占用系统资源最少的一个小shell,它只包含24个内部命令,因而使用起来很不方便。 2.bash bash是Linux系统默认使用的shell,它由Brian Fox和Chet Ramey共同完成,是Bourne Again Shell的缩写,内部命令一共有40个。Linux使用它作为默认的shell是因为它有诸如以下的特色: (1)可以使用类似DOS下面的doskey的功能,用方向键查阅和快速输入并修改命令。 (2)自动通过查找匹配的方式给出以某字符串开头的命令。 (3)包含了自身的帮助功能,你只要在提示符下面键入help就可以得到相关的帮助。 3.ksh ksh是Korn shell的缩写,由Eric Gisin编写,共有42条内部命令。该shell最大的优点是几乎和商业发行版的ksh完全兼容,这样就可以在不用花钱购买商业版本的情况下尝试商业版本的性能了。 4.csh

很实用的Shell脚本(实践版)

很实用的Shell脚本(实践版)

/erpHome/shell/old/$1/$2.zip.old find . -mtime +7 | xargs nice -n 20 zip -qm /erpHome/shell/old/$1/$2_$DayOfWeek.zip # find . -mtime +7 Fi archiveOld2.sh . /erpHome/shell/setP.sh export DayOfWeek=`date +"%u"`

if test "$#" -lt 1 || test -z "$1" then echo At least one argument needed. exit fi if test ! -e "$ShellHome/old/$1" then cd $ShellHome/old/ mkdir -p $1 fi if test ! -e "$ERPHome/$1" then echo "$ERPHome/$1" "does not exist" exit fi cd $ERPHome/$1 mv $ShellHome/old/$1_$DayOfWeek.zip $ShellHome/old/$1.zip.old find . -mtime +7 -type f | xargs nice -n 20 zip -qm $ShellHome/old/$1_$DayOfWeek.zip #find . -mtime +7 -type f

archiveOldAll.sh /erpHome/shell/archiveOld.sh work/dr/engine jrprint /erpHome/shell/archiveOld.sh work/de tmp /erpHome/shell/archiveOld2.sh public

利用shell脚本做可执行安装程序

利用shell脚本制作可执行安装程序 制作简单的安装包的时候可以简单的用cat命令连接两个文件,然后头部是脚本文件,执行的时候把下面的文件分解出来就行了。一般这个后部分的文件是个压缩包,那样,就能够打包很多文件了,在脚本中解压出来即可。这就是Linux那些bin、run等安装脚本的简单制作了。 如在linux 下制作二进制 .bin 文件的制做方法:就是使用cat 命令将执行脚本和打包文件同时放到一个.bin的文件里。这样安装的时候只要使用一个包,直接执行该包即可安装完毕,简单方便。 下例就是一名为install.sh脚本,它实现以下功能: ●自动创建用户及用户组 ●自动检查网络环境并安装环境包所需要的支撑环境 ●显示安装进度 ●自动检查并配置防火墙 ●自动安装环境包 ●自动增加自启动脚本 1.bin文件制作步骤 a)打包文件 tar cvf myapp-env-1.0-linux-x64-installer.tar.gz myapp-env-1.0-linux-x64-installer.tar b)编写脚本 内容见《install.sh脚本内容》节 c)可执行安装程序制作方法 # cat install.sh myapp-env-1.0-linux-x64-installer.tar.gz > myapp-env-1.0-linux-x64-installer.bin 这样就生成myapp-env-1.0-linux-x64-installer.bin的安装文件,该文件是由shell脚本和二进制合成的。前半部分是脚本后半部分是二进制文件,用strings等二进制查看命令可以看到。 2.安装 chmod 755 myapp-env-1.0-linux-x64-installer.bin ./ myapp-env-1.0-linux-x64-installer.bin 3.install.sh脚本内容

Linux Shell常用命令总结

1. find find pathname -options [-print -exec -ok] 让我们来看看该命令的参数: pathname find命令所查找的目录路径。例如用.来表示当前目录,用/来表示系统根目录。 -print find命令将匹配的文件输出到标准输出。 -exec find命令对匹配的文件执行该参数所给出的shell命令。相应命令的形式为'command' {} \;,注意{}和\;之间的空格,同时两个{}之间没有空格, 注意一定有分号结尾。 0) -ok 和-exec的作用相同,只不过以一种更为安全的模式来执行该参数所给出的shell命令,在执行每一个命令之前,都会给出提示,让用户来确定是否执行 find . -name "datafile" -ctime -1 -exec ls -l {} \; 找到文件名为datafile*, 同时创建实际为1天之内的文件, 然后显示他们的明细. find . -name "datafile" -ctime -1 -exec rm -f {} \; 找到文件名为datafile*, 同时创建实际 为1天之内的文件, 然后删除他们. find . -name "datafile" -ctime -1 -ok ls -l {} \; 这两个例子和上面的唯一区别就是-ok会在每个文件被执行命令时提示用户, 更加安全. find . -name "datafile" -ctime -1 -ok rm -f {} \; 1) find . -name 基于文件名查找,但是文件名的大小写敏感. find . -name "datafile*" 2) find . -iname 基于文件名查找,但是文件名的大小写不敏感. find . -iname "datafile*" 3) find . -maxdepth 2 -name fred 找出文件名为fred,其中find搜索的目录深度为2(距当前目录), 其中当前目录被视为第一层. 4) find . -perm 644 -maxdepth 3 -name "datafile*" (表示权限为644的, 搜索的目录深度为3, 名字为datafile*的文件) 5) find . -path "./rw" -prune -o -name "datafile*" 列出所有不在./rw及其子目录下文件名为datafile*的文件。 find . -path "./dir*" 列出所有符合dir*的目录及其目录的文件. find . \( -path "./d1" -o -path "./d2" \) -prune -o -name "datafile*" 列出所有不在./d1和d2及其子目录下文件名为datafile*的文件。 6) find . -user ydev 找出所有属主用户为ydev的文件。 find . ! -user ydev 找出所有属主用户不为ydev的文件,注意!和-user之间的空格。 7) find . -nouser 找出所有没有属主用户的文件,换句话就是,主用户可能已经被删除。 8) find . -group ydev 找出所有属主用户组为ydev的文件。

经典shell-脚本实例

Linux shell 脚本实例 1. 写一个脚本,利用循环计算10的阶乘#!/bin/sh factorial=1 for a in `seq 1 10` do factorial=`expr $factorial \* $a` done echo "10! = $factorial" 2. 写一个脚本,执行后,打印一行提示“Please input a number:",要求用户输入数值,然后打印出该数值,然后再次要求用户输入数值。直到用户输入"end"停止。 #!/bin/sh unset var while [ "$var" != "end" ] do echo -n "please input a number: " read var if [ "$var" = "end" ] then break fi echo "var is $var" done ////////////////////////////////////////// #!/bin/sh unset var while [ "$var" != "end" ] do echo -n "please input a number: " read var if [ "$var" = "end" ] then break fi echo "var is $var" done 3. 写一个脚本,利用循环和continue关键字,计算100以内能被3整除的数之和 4.一个函数,利用shift计算所有参数乘积,假设参数均为整数 #! /bin/sh result=1 while [ $# -gt 0 ] do result=`expr $result * $1` shift done echo $result 5.写一个脚本,可以根据参数文件名,以正确的参数调用tar来解压缩tar.gz或tar.bz2文件。#!/bin/shcase ${1##*.tar.} in bz2) tar jxvf $1 ;; gz) tar zxvf $1 ;; *) echo "wrong file type"esac6.写一个脚本以方便用户查询rpm的相关信息。这个脚本首先提示用户选择查询依据,比如文件名,包名,全部等。然后提示用户选择查询信息,比如包名,包里所包含的所有文件,包的信息等。然后询问是否继续查询,是则循环刚才的过程,否则退出。

个人整理shell脚本编程笔记

shell脚本编程学习笔记(一) 一、脚本格式 vim shell.sh #!/bin/bash//声明脚本解释器,这个‘#’号不是注释,其余是注释 #Program://程序内容说明 #History://时间和作者 二、shell变量的种类 用户自定义变量:由用户自己定义、修改和使用 与定义变量:Bash与定义的特殊变量,不能直接修改 位置变量:通过命令行给程序传递执行的参数 1、定义变量: 变量名要以英文字母或下划线开头,区分大小写。 格式:变量名=值 输出变量:echo $变量名 2、键盘输入为变量内容: 格式:read [-p "信息"] 变量名 如:read -p "pewase input your name:" name 3、不同引号对变量的作用 双引号"":可解析变量,$符号为变量前缀。 单引号'':不解析变量,$为普通字符。 反引号``:将命令执行的结果输出给变量。 三、shell条件测试 1、test命令: 用途:测试特定的表达式是否成立,当条件成立时,命令执行后的返回值为0,否则为其他数字。 格式:test 条件表达式[ 条件表达式] (注意:[]与表达式之间存在空格) 2、常见的测试类型: 测试文件状态 格式:[ 操作符文件或目录] 如:if [ -d /etc ] then echo "exists" else echo "not exists" fi 常见的测试操作符: -d:测试是否为目录 -e:测试目录或文件是否存在 -f:测试是否为文件 -r:测试当前用户是否有读权限 -w:测试当前用户是否有写权限 -x:测试当前用户是否有执行权限

shell脚本练习题

shell脚本例子集锦(习题总结) 练习一:写一个脚本 1.设定变量FILE的值为/etc/passwd 2.依次向/etc/passwd中的每个用户问好,并且说出对方的ID是什么 形如:(提示:LINE=`wc -l /etc/passwd | cut -d" " -f1`) Hello,root,your UID is 0. 3.统计一个有多少个用户 答案一:#!/bin/bash file="/etc/passwd" LINES=`wc -l $file | cut -d" " -f1` for I in `seq 1 $LINES`;do userid=`head -$I $file | tail -1 |cut -d: -f3` username=`head -$I $file | tail -1 |cut -d: -f1` echo "hello $username,your UID is $userid" done echo "there are $LINES users" 答案二:#!/bin/bash file=/etc/passwd let num=0 for I in `cat $file`;do username=`echo "$I" | cut -d: -f1` userid=`echo "$I" | cut -d: -f3` echo "Hello,$username,your UID is $userid" num=$[$num+1] done echo "there are $num users" 练习二:写一个脚本 1.切换工作目录至/var 2.依次向/var目录中的每个文件或子目录问好,形如: (提示:for FILE in /var/*;或for FILE in `ls /var`;) Hello,log 3.统计/var目录下共有多个文件,并显示出来 答案:#!/bin/bash cd /var let num=0 for I in `ls /var/*`;do echo "hello $I" num=$[$num+1] done echo "the number of files is $num" 练习三:写一个脚本 1.设定变量file的值为/etc/passwd

实验十三 shell脚本练习

上机实验内容: 1、请编写一个脚本,其功能是将当前用户的根目录下的work目录打包为名为“user’s-workdir-in-YYMMDD”的tar包(提示:参考用date建立文件) 要求:i)若该目录不存在,显示“dir not exist” ii)若该文件不是目录类型,显示“work is a type”,此处的type为文件类型 #!/bin/bash [ -e /work ] && tar -cvf "User's-workdir-in-`date +%Y%m%d`.tar" /work || echo "dir not exist" declare filetype="" [ -f /work ] && filetype="常规文件" [ -d /work ] && filetype="目录文件" [ -b /work ] && filetype="块设备文件" [ -c /work ] && filetype="字符设备" [ -S /work ] && filetype="套接字文件" [ -p /work ] && filetype="FIFO(管道)文件" [ -L /work ] && filetype="连接文件" [ "$filetype" != "" ] && echo "work is a $filetype" 2、编写一个脚本,其中包含一个打印函数,用于将多次输入的字符组合为一个字符串 要求:i)使用函数实现新值的输出 ii)使用循环语句完成多个字符的输入,直到输入字符串EOF才完成字符串的累加#!/bin/bash function add(){ str="$str"$input echo $str } read -p "请输入一个字符串或者输入EOF结束本次操作:" input declare str while [ "$input" != "EOF" ] do add read -p "请输入一个字符串或者输入EOF结束本次操作" input done 3、自我练习:设计一个运算器,实现“加、减、乘、除”功能。 (四则运算:符号使用+、-、*、/) #!/bin/bash

PowerShell基本语法及常用命令

PowerShell基本语法及常用命令 Powershell常用命令 1.Get-Command 得到Powshell所有命令 2.Get-Process 获取所有进程 3.Set-Alias 给指定命令重命名如:Set-Alias aaa Get-Command 4.Set-ExecutionPolicy remotesigned 设置powershell可直接执行脚本文件一般脚本文件以.ps1结尾执行脚本文件直接输入文件地址即可执行脚本文件中只写命令即可 5.Get-Help get-* 查询以get开头的命令Get-Help *service* Get-Help Get-Command 获取Get-Command命令的基本用法 6.Get-Member 获取对象属性如: $var | Get-Memeber 访问$var属性直接$var.T oString() PS中的变量定义 不需要定义或声明数据类型 在变量前加"$" 定义变量的规则 -变量可以是数字$123 -变量可以是字符串$abc -变量可以是特殊字符${@1b} 内置的变量 -$pshome -$home

-$profile 变量赋值: $var=123 $var="aaaaaa" 取变量值: $var 变量赋值方法:Set-Variable var 100 取值方法: Get-Variable var 清空值: Clear-Variable var 删除变量Remove-Variable var 取多个变量如var1 var2 var3地值: Get-Variable var* 另一种赋值方法$var1="bbb" $var2="$var $var1" 结果$var2="aaaaaa bbb" $var2='$var $var1' 结果$var2="$var $var1" $date=Get-Date 获取当前时间 $date.AddDays(3) 当前时间加3天 排序用法 Get-Process | Sort-Object ws 根据WS值由小到大排序 Get-Process | Sort-Object | fl Get-Process | Sort-Object | Format-List 以列表形式显示数据 导入导出文件 Get-Process > c:\aa.txt

Shell脚本编程详解-吐血共享

第12章 Shell 脚本编程 ● Shell 命令行的运行 ● 编写、修改权限和执行Shell 程序的步骤 ● 在Shell 程序中使用参数和变量 ● 表达式比较、循环结构语句和条件结构语句 ● 在Shell 程序中使用函数和调用其他Shell 程序 12-1 Shell 命令行书写规则 ◆ Shell 命令行的书写规则 对Shell 命令行基本功能的理解有助于编写更好的Shell 程序,在执行Shell 命令时多个命令可以在一个命令行上运行,但此时要使用分号(;)分隔命令,例如: [root@localhost root]# ls a* -l;free;df 长Shell 命令行可以使用反斜线字符(\)在命令行上扩充,例如: [root@localhost root]# echo “ this is \ >long command ” This is long command 注意: “>”符号是自动产生的,而不是输入的。 12-2 编写/修改权限及执行Shell 程序的步骤 ◆ 编写Shell 程序 ◆ 执行Shell 程序 Shell 程序有很多类似C 语言和其他程序设计语言的特征,但是又没有程序语言那样复杂。Shell 程序是指放在一个文件中的一系列Linux 命令和实用程序。在执行的时候,通过Linux 操作系统一个接一个地解释和执行每条命令。首先,来编写第一个Shell 程序,从中学习Shell 程序的编写、修改权限、执行过程。

12-2-1 编辑Shell程序 编辑一个内容如下的源程序,保存文件名为date,可将其存放在目录/bin下。 [root@localhost bin]#vi date #! /bin/sh echo “Mr.$USER,Today is:” echo &date “+%B%d%A” echo “Wish you a lucky day !” 注意: #! /bin/sh通知采用Bash解释。如果在echo语句中执行Shell命令date,则需要在date 命令前加符号“&”,其中%B%d%A为输入格式控制符。 12-2-2 建立可执行程序 编辑完该文件之后不能立即执行该文件,需给文件设置可执行程序权限。使用如下命令。[root@localhost bin]#chmod +x date 12-2-3 执行Shell程序 执行Shell程序有下面三种方法: 方法一: [root@localhost bin]#./ date Mr.root,Today is: 二月 06 星期二 Wish you a lucky day ! 方法二: 另一种执行date的方法就是把它作为一个参数传递给Shell命令: [root@localhost bin]# Bash date Mr.root,Today is: 二月 06 星期二 Wish you a lucky day ! 方法三: 为了在任何目录都可以编译和执行Shell所编写的程序,即把/bin的这个目录添加到整个环境变量中。 具体操作如下: [root@localhost root]#export PATH=/bin:$PATH [root@localhost bin]# date Mr.root,Today is: 二月 06 星期二 Wish you a lucky day !

shell脚本之前的基础知识

第十二章学习shell脚本之前的基础知识 日常的linux系统管理工作中必不可少的就是shell脚本,如果不会写shell脚本,那么你就不算一个合格的管理员。目前很多单位在招聘linux系统管理员时,shell脚本的编写是必考的项目。有的单位甚至用shell脚本的编写能力来衡量这个linux系统管理员的经验是否丰富。笔者讲这些的目的只有一个,那就是让你认真对待shell脚本,从一开始就要把基础知识掌握牢固,然后要不断的练习,只要你shell脚本写的好,相信你的linux求职路就会轻松的多。笔者在这一章中并不会多么详细的介绍shell脚本,而只是带你进入shell脚本的世界,如果你很感兴趣那么请到网上下载相关的资料或者到书店购买相关书籍吧。 在学习shell 脚本之前,需要你了解很多关于shell的知识,这些知识是编写shell脚本的基础,所以希望你能够熟练的掌握。 【什么是shell】 简单点理解,就是系统跟计算机硬件交互时使用的中间介质,它只是系统的一个工具。实际上,在shell和计算机硬件之间还有一层东西那就是系统内核了。打个比方,如果把计算机硬件比作一个人的躯体,而系统内核则是人的大脑,至于shell,把它比作人的五官似乎更加贴切些。回到计算机上来,用户直接面对的不是计算机硬件而是shell,用户把指令告诉shell,然后shell再传输给系统内核,接着内核再去支配计算机硬件去执行各种操作。 笔者接触的linux发布版本(Redhat/CentOS)系统默认安装的shell叫做bash,即Bourne Again Shell,它是sh(Bourne Shell)的增强版本。Bourn Shell 是最早行起来的一个shell,创始人叫Steven Bourne,为了纪念他所以叫做Bourn Shell,检称sh。那么这个bash有什么特点呢? 1)记录命令历史 我们敲过的命令,linux是会有记录的,预设可以记录1000条历史命令。这些命令保存在用户的家目录中的.bash_history文件中。有一点需要你知道的是,只有当用户正常退出当前shell时,在当前shell中运行的命令才会保存至.bash_history文件中。 与命令历史有关的有一个有意思的字符那就是”!”了。常用的有这么几个应用:(1)!! (连续两个”!”),表示执行上一条指令;(2)!n(这里的n是数字),表示执行命令历史中第n条指令,例如”!100”表示执行命令历史中第100个命令;(3)!字符串(字符串大于等于1),例如!ta,表示执行命令历史中最近一次以ta为开头的指令。

linux Shell(脚本)编程入门 实例讲解详解

linux Shell(脚本)编程入门实例讲解详解 为什么要进行shell编程 在Linux系统中,虽然有各种各样的图形化接口工具,但是sell仍然是一个非常灵活的工具。Shell不仅仅是命令的收集,而且是一门非常棒的编程语言。您可以通过使用shell使大量的任务自动化,shell特别擅长系统管理任务,尤其适合那些易用性、可维护性和便携性比效率更重要的任务。 下面,让我们一起来看看shell是如何工作的: 建立一个脚本 Linux中有好多中不同的shell,但是通常我们使用bash (bourne again shell) 进行shell编程,因为bash是免费的并且很容易使用。所以在本文中笔者所提供的脚本都是使用bash(但是在大多数情况下,这些脚本同样可以在bash 的大姐,bourne shell中运行)。 如同其他语言一样,通过我们使用任意一种文字编辑器,比如nedit、kedit、emacs、vi等来编写我们的shell程序。程序必须以下面的行开始(必须方在文件的第一行): 符号#!用来告诉系统它后面的参数是用来执行该文件的程序。在这个例子中我们使用/bin/sh来执行程序。当编辑好脚本时,如果要执行该脚本,还必须使其可执行。 要使脚本可执行: 然后,您可以通过输入: ./filename 来执行您的脚本。 注释 在进行shell编程时,以#开头的句子表示注释,直到这一行的结束。我们真诚地建议您在程序中使用注释。如果您使用了注释,那么即使相当长的时间内没有使用该脚本,您也能在很短的时间内明白该脚本的作用及工作原理。 变量 在其他编程语言中您必须使用变量。在shell编程中,所有的变量都由字符串组成,并且您不需要对变量进行声明。要赋值给一个变量,您可以这样写:

shell常用命令

目录 一、目录操作 a) ls--查看文件/目录: 常用:ls –l 查看详细文件列表 b) pwd--查看当前目录: c) cd--改变工作目录: 常用①:cd ../ 跳转到上一级目录 常用②:cd /boot/ 跳转到指定目录 d) mkdir--创建目录: 常用:mkdir 123 创建一个空文件夹 e) rm--删除文件/目录: 常用: rm -rf 123 删除目录文件夹,并且目录下的文件一并删除。 f) mv--移动文件/目录改名、移动: 移动文件: mv 1.sh ./123 → mv 目标文件移动至某目录 重名命文件:mv 1.sh 123.sh → mv 原文件欲改后文件 g) ln--建立软连接和硬连接: 软连接:ln -s 123.sh ../ → ln -s 源文件欲放置路径 硬连接:ln 123.sh ../ → ln 源文件欲放置路径 h) rmdir--删除空目录: 二、文件操作 a)cat--查看文件内容,若文件不存在,创建对应文件: 常用:cat 1.txt b)cp--拷贝文件、目录: 备份:cp 123.sh 1.sh → cp 源文件目标文件 复制至某路径:cp 123.sh ../ → cp 源文件目标路径 c)chmod--修改文件权限: 常用:chmod 777 1.sh 给1.sh最高权限 一般模式:chmod +rw 1.sh 仅当前用户下1.sh具有可读写权限 d)touch--创建文件: 常用:touch ./1.sh → touch 路径+名称 f)vim--创建并打开文件: 常用:vim ./1.sh → vim 路径+名称 g)find--在指定目录查找符合条件的文件: 以[文件名+类型]寻找:find ./ -name “*.*”→ find 路径 -nama

实验4 SHELL脚本的编写(一)

广东技术师范学院实验报告 学院:计科院专业:班级:成绩: 姓名:学号:组别:组员: 实验地点:实验日期:指导教师签名: 实验4项目名称:SHELL脚本的编写(一) 1、实验目的 通过对典型的SHELL脚本进行验证,以及编写具有一定实用程度的SHELL 脚本,理解并掌握SHELL脚本的基本编写方法。 2、实验内容 2.1什么是shell脚本 要明白什么是shell脚本,首先要理解什么是脚本(script)。脚本是指一种未经编译而直接解释执行的程序,最典型例子就是javascript程序。我们知道,程序代码写好后,有两种方式让它执行。一是通过编译器编译成二进制执行代码后提交给系统执行,而另一种则不经过编译,直接送给解释器解释执行。 shell脚本指的就是一种通过shell来解释并执行的程序。UNIX中的shell,它既是一个界面程序,又是一个脚本的解释器,同时又能提供一种功能丰富的脚本语言供用户编写脚本程序。用户只需要通过vi等编辑器将脚本编写好(脚本本身上还是一个文本),通过命令行的形式提交给shell,shell便会对其解释并执行了。 2.2 shell脚本与系统管理 Shell脚本在系统管理上占有重要的位置。原因在于系统管理的日常工作许多都是常规化的,例如日志管理、重要数据备份、账户管理、文件系统清理等工作,一次性地编写一个管理脚本程序,就能避免重复的管理工作。当然,现在有许多管理工具供管理员使用,不是任何工作都需要编写一个shell脚本。不过任何一个管理工具都不可能为特定某个应用业务度身定制,针对当前应用业务的需要编写shell脚本属于高级系统管理员应具备的能力。 此外,有一个问题值得讨论,利用其它高级语言也一样可以写管理程序,为什么要用shell脚本语言?这在于shell脚本最终提交给shell解释执行,因此可直接在程序中使用各种shell命令(c程序是不可能这样做的)。这些shell命令从操作系统管理的角度来看,都涉及到系统资源申请、使用和释放,shell脚本只通过简单的命令即可实现,而高级语言却需要复杂的、大量的系统API函数调用。同学们回顾之前实验中的作业题,每一题只需一到两条shell命令即可完成,但如果用c语言编写相应的程序,也许不可能几条语句就可以实现的了。 关于shell脚本的编写是一个很大的话题,本实验介绍基本的shell程序编写,

shell常用命令大全

一、文件目录类命令 1、查看联机帮助信息 man命令如:#man ls info命令如:#info cd 2、列出当前目录或指定目录的文件名和目录名 ls[选项]文件或目录 常用[选项]如下: -a:显示所有的文件,包括以“.”开头的隐含文件。 -l:长格式输出 -m:宽行输出 -F:以各种符号表示不同的文件类型 --color:彩色输出 -R:递归输出 3、touch 功能:修改文件的创建日期或以当前系统日期创建一个空文件。 -d:修改文件的日期。 #touch–d2*******test.txt 4、cp 功能:复制文件 用法:cp[选项]源文件或目录目标文件或目录 选项: a:该选项通常在拷贝目录时使用。它保留链接、文件属性,并递归地

拷贝目录,其作用等于dpR选项的组合。 -d拷贝时保留链接。 -f删除已经存在的目标文件而不提示。 -i和f选项相反,在覆盖目标文件之前将给出提示要求用户确认。回答y时目标文件将被覆盖,是交互式拷贝。 -p此时cp除复制源文件的内容外,还将把其修改时间和访问权限也复制到新文件中。 -r若给出的源文件是一目录文件,此时cp将递归复制该目录下所有的子目录和文件。此时目标文件必须为一个目录名。 5、mv 功能:给文件或目录改名或将一个文件或目录移到另一个目录 用法:mv[选项]源文件或目录目标文件或目录 -i交互方式操作。如果mv操作将导致对已存在的目标文件的覆盖,此时系统询问是否重写,要求用户回答y或n,这样可以避免误覆盖文件。-f禁止交互操作。在mv操作要覆盖某已有的目标文件时不给任何指示,指定此选项后,i选项将不再起作用。 6、rm 功能:删除文件或目录 用法:rm[选项]文件… -f强制删除 -r指示rm将参数中列出的全部目录和子目录均递归地删除。 -i进行交互式删除

相关主题
文本预览
相关文档 最新文档