linux shell实例(linux vi命令详解)

大家好,关于linux shell实例很多朋友都还不太明白,今天小编就来为大家分享关于linux vi命令详解的知识,希望对各位有所帮助!

Linux Shell 教程——想玩转linux就请一直看下去

Shell是一个用 C语言编写的程序,它是用户使用 Linux的桥梁。Shell既是一种命令语言,又是一种程序设计语言。

Shell是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。

Ken Thompson的 sh是第一种 Unix Shell,Windows Explorer是一个典型的图形界面 Shell。

Shell在线工具

Shell脚本(shell script),是一种为 shell编写的脚本程序。

业界所说的 shell通常都是指 shell脚本,但读者朋友要知道,shell和 shell script是两个不同的概念。

由于习惯的原因,简洁起见,本文出现的"shell编程"都是指 shell脚本编程,不是指开发 shell自身。

Shell编程跟 JavaScript、php编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了。

Linux的 Shell种类众多,常见的有:

在一般情况下,人们并不区分 Bourne Shell和 Bourne Again Shell,所以,像#!/bin/sh,它同样也可以改为#!/bin/bash。

#!告诉系统其后路径所指定的程序即是解释此脚本文件的 Shell程序。

打开文本编辑器(可以使用 vi/vim命令来创建文件),新建一个文件 test.sh,扩展名为 sh(sh代表shell),扩展名并不影响脚本执行,见名知意就好,如果你用 php写 shell脚本,扩展名就用 php好了。

输入一些代码,第一行一般是这样:

#!/bin/bash

echo"Hello World!"

运行实例»

#!是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell。

echo命令用于向窗口输出文本。

1、作为可执行程序

将上面的代码保存为 test.sh,并 cd到相应目录:

注意,一定要写成./test.sh,而不是 test.sh,运行其它二进制的程序也一样,直接写 test.sh,linux系统会去 PATH里寻找有没有叫 test.sh的,而只有/bin,/sbin,/usr/bin,/usr/sbin等在 PATH里,你的当前目录通常不在 PATH里,所以写成 test.sh是会找不到命令的,要用./test.sh告诉系统说,就在当前目录找。

2、作为解释器参数

这种运行方式是,直接运行解释器,其参数就是 shell脚本的文件名,如:

这种方式运行的脚本,不需要在第一行指定解释器信息,写了也没用。

linux shell 脚本实现tcp/upd协议通讯

linux设备里面有个比较特殊的文件:

/dev/[tcp|upd]/host/port只要读取或者写入这个文件,相当于系统会尝试连接:host这台机器,对应port端口。如果主机以及端口存在,就建立一个socket连接。将在,/proc/self/fd目录下面,有对应的文件出现。

一、测试下:/dev/tcp/host/post文件

复制代码

   

代码如下:

[chengmo@centos5 shell]$ cat/dev/tcp/127.0.0.1/22

   SSH-2.0-OpenSSH_5.1

   #我的机器shell端口是:22

   #实际:/dev/tcp根本没有这个目录,这是属于特殊设备

   [chengmo@centos5 shell]$ cat/dev/tcp/127.0.0.1/223

   -bash: connect:拒绝连接

   -bash:/dev/tcp/127.0.0.1/223:拒绝连接

   #223接口不存在,打开失败

   [chengmo@centos5 shell]$ exec 8/dev/tcp/127.0.0.1/22

   [chengmo@centos5 shell]$ ls-l/proc/self/fd/

   总计 0

   lrwx------ 1 chengmo chengmo 64 10-21 23:05 0-/dev/pts/0

   lrwx------ 1 chengmo chengmo 64 10-21 23:05 1-/dev/pts/0

   lrwx------ 1 chengmo chengmo 64 10-21 23:05 2-/dev/pts/0

   lr-x------ 1 chengmo chengmo 64 10-21 23:05 3-/proc/22185/fd

   lrwx------ 1 chengmo chengmo 64 10-21 23:05 8- socket:[15067661]

   #文件描述符8,已经打开一个socket通讯通道,这个是一个可以读写socket通道,因为用:""打开

   [chengmo@centos5 shell]$ exec 8-

   #关闭通道

   [chengmo@centos5 shell]$ ls-l/proc/self/fd/

   总计 0

   lrwx------ 1 chengmo chengmo 64 10-21 23:08 0-/dev/pts/0

   lrwx------ 1 chengmo chengmo 64 10-21 23:08 1-/dev/pts/0

   lrwx------ 1 chengmo chengmo 64 10-21 23:08 2-/dev/pts/0

   lr-x------ 1 chengmo chengmo 64 10-21 23:08 3-/proc/22234/fd

二、通过重定向读取远程web服务器头信息

复制代码

   

代码如下:

#!/bin/sh

   #testhttphead.sh

   #实现通过主机名,端口读取web服务器header信息

   #copyright chengmo,qq:8292669

   if(($#2));then

   echo"usage:$0 host port";

   exit 1;

   fi

   #如果参数缺失,退出程序,返回状态1

   exec 6/dev/tcp/$1/$2 2/dev/null;

   #打开host的port可读写的socket连接,与文件描述符6连接

   if(($?!=0));then

   echo"open$1$2 error!";

   exit 1;

   fi

   #如果打开失败,$?返回不为0,终止程序

   echo-e"HEAD/ HTTP/1.1/n/n/n/n/n"6;

   #将HEAD信息,发送给socket连接

   cat6;

   #从socket读取返回信息,显示为标准输出

   exec 6-;

   exec 6-;

   #关闭socket的输入,输出

   exit 0;

脚本建立后:存为testhttphead.sh

运行结果:

复制代码

   

代码如下:

[chengmo@centos5~/shell]$ sh testhttphead.sh www.baidu.com 80

   HTTP/1.1 200 OK

   Date: Thu, 21 Oct 2010 15:17:23 GMT

   Server: BWS/1.0

   Content-Length: 6218

   Content-Type: text/html;charset=gb2312

   Cache-Control: private

   Expires: Thu, 21 Oct 2010 15:17:23 GMT

   Set-Cookie: BAIDUID=1C40B2F8C676180FD887379A6E286DC1:FG=1; expires=Thu, 21-Oct-40 15:17:23 GMT; path=/; domain=.baidu.com

   P3P: CP=" OTI DSP COR IVA OUR IND COM"

   Connection: Keep-Alive

   [chengmo@centos5~/shell]$ sh testhttphead.sh 127.0.0.1 8080

   open 127.0.0.1 8080 error!

突然有个奇怪想法:

我们在windows时代就通过telnet可以实现tcp/upd协议通讯,那么如果用传统方法怎么实现呢?

复制代码

   

代码如下:

[chengmo@centos5~/shell]$ echo-e"HEAD/ HTTP/1.1/n/n/n/n/n"|telnet www.baidu.com 80

   Trying 220.181.6.175...

   Connected to www.baidu.com.

   Escape character is'^]'.

   Connection closed by foreign host.

   #直接给发送,失败

   [chengmo@centos5~/shell]$(telnet www.baidu.com 80)EOF

   HEAD/ HTTP/1.1

   EOF

   Trying 220.181.6.175...

   Connected to www.baidu.com.

   Escape character is'^]'.

   Connection closed by foreign host.

   #重定向输入,还是失败?

找到正确方法:

复制代码

   

代码如下:

[chengmo@centos5 shell]$(echo-e"HEAD/ HTTP/1.1/n/n/n/n/n";sleep 2)|telnet www.baidu.com 80

   Trying 220.181.6.175...

   Connected to www.baidu.com.

   Escape character is'^]'.

   HTTP/1.1 200 OK

   Date: Thu, 21 Oct 2010 15:51:58 GMT

   Server: BWS/1.0

   Content-Length: 6218

   Content-Type: text/html;charset=gb2312

   Cache-Control: private

   Expires: Thu, 21 Oct 2010 15:51:58 GMT

   Set-Cookie: BAIDUID=0B6A01ACECD5353E4247E088A8CB345A:FG=1; expires=Thu, 21-Oct-40 15:51:58 GMT; path=/; domain=.baidu.com

   P3P: CP=" OTI DSP COR IVA OUR IND COM"

   Connection: Keep-Alive

   #成功了!加入sleep居然可以了,sleep改成1秒也可以

是不是由于sleep后,echo会推出2秒发给通道:telnet呢?推论可以从这2个方面推翻:

一个方面:通过()括的数据是一对命令,会作为一个子命令执行,一起执行完程序结束。每个命令echo语句,就直接发送到屏幕(也就是标准输出),只要有标准输出了,就会通过通道马上传个:telnet,如果接下来命令还有输出,会注意传给telnet,直到()内所有命令执行完,与通道连接就断开了。

再一个方面:如果说是起到推迟发送的话,什么时候有数据过来,发给telnet,什么时候telnet命令启动。跟你推迟一点还是早一点发送过来。没有关系。

这种类型命令,看出sleep,其实就是保持通道跟telnet连接2秒钟。通道连接着了,telnet终端输入也还在,因此可以保持从baidu服务器获得数据。

所以,延迟多久,还是跟服务器处理速度有关系。

如果通过echo向telnet发送数据,保持通道联通,使用sleep是个很好方法。

通过重定向给telnet输入参数这种方法,我还想不到怎么样实现延迟输入。有知道朋友,可以指点指点.

区别:

telnet与echo实现 http访问,与通过打开读写socket是不一样的,打开socket通道,是可以进行交换处理的。传入命令,活动结果,再传入命令,再获得结果。telnet通过echo就不能这样处理了。

三、通过shell脚本重定向实现监控memcache状态

复制代码

   

代码如下:

#!/bin/sh

   #通过传入ip以及端口,发送指令获得返回数据

   #copyright chengmo qq:8292669

   #函数往往放到最上面

   function sendmsg()

   {

   msg=$1;

   echo"$1"8;

   getout;

   }

   #向socket通道发送指令,并且调用获得返回参数

   function getout()

   {

   #read命令-u从打开文件描述符 8读取数据,-d读取数据忽略掉:/r换行符

   while read-u 8-d$'/r' name;

   do

   if ["${name}"=="END"-o"${name}"=="ERROR" ];then

   break;

   fi;

   echo$name;

   done

   }

   #由于:memcached每次通讯完毕,会返回:END或者ERROR(出错),通过判断是否是"END"觉得读取是不是结束,否则循环不会停止

   if [$#-lt 2 ];then

   echo"usage:$0 host port [command]";

   exit 1;

   fi;

   [[$#-gt 2 ]]command=$3;

   #设置默认值如果command为定义则为:stats

   command="${command=stats}";

   host="$1";

   port="$2";

   exec 8/dev/tcp/${host}/${port};

   #打开通向通道是8

   if ["$?"!="0" ];then

   echo"open$host$port fail!";

   exit 1;

   fi

   sendmsg"$command";

   #发送指定命令

   sendmsg"quit";

   #发送退出通向命令

   exec 8-;

   exec 8-;

   #关闭socket通道

   exit 0;

这是通过重定向,实现socket通讯中,发送然后获取返回的例子。其实,上面代码看似一次只能发送一段。时间上。我们可以反复调用:sendmsg,捕捉输出数据。实现连续的,读与写操作。

实例截图:

其它实现方法:

其实通过:telnet也可以实现的。

[chengmo@centos5 shell]$(echo"stats";sleep 2)|telnet 127.0.0.1 11211

通过nc命令实现:

[chengmo@centos5 shell]$(echo"stats")|nc 127.0.0.1 11211

不需要加延迟,直接打开通道

第二个程序里面,看到shell完全可以处理交互设计了。如果按照这样,登陆ftp,pop3,stmp都可以类似实现。这些,我们通过shell socket类似程序实现,应该不困难,只是捕捉如发送解析的问题了。

Linux Shell 通配符.元字符.转义符使用实例介绍

下面是一个实例:

复制代码

   

代码如下:

[chengmo@localhost~/shell]$ ls

   a.txt b.txt c.old

   #2

   [chengmo@localhost~/shell]$ ls*.txt

   a.txt b.txt

   #3

   [chengmo@localhost~/shell]$ ls d*.txt

   ls:无法访问 d*.txt:没有那个文件或目录

从上面这个实例,不知道大家有没有发现问题呢。我们先了解一下,通配符相关知识,再分析下这个实例吧。

一、linux shell通配符(wildcard)

通配符是由shell处理的(不是由所涉及到命令语句处理的,其实我们在shell各个命令中也没有发现有这些通配符介绍),它只会出现在命令的“参数”里(它不用在命令名称里,也不用在操作符上)。当shell在“参数”中遇到了通配符时,shell会将其当作路径或文件名去在磁盘上搜寻可能的匹配:若符合要求的匹配存在,则进行代换(路径扩展);否则就将该通配符作为一个普通字符传递给“命令”,然后再由命令进行处理。总之,通配符实际上就是一种shell实现的路径扩展功能。在通配符被处理后, shell会先完成该命令的重组,然后再继续处理重组后的命令,直至执行该命令。

我们回过头分析上面命令吧:在第2个命令中,*.txt实际shell搜索文件,找到了符合条件的文件,命令会变成:ls a.txt b.txt,实际在执行ls时候传给它的是a.txt b.txt.

而命令3,d*.txt由于当前目录下面没有这样的文件或目录,直接将”d*.txt”作为ls参数,传给了 ls.这个时候”*”只是一个普通的 ls参数而已,已经失去了它通配意义。由于找不到文件,所以会出现:无法访问提示!

了解了shell通配符,我们现在看下,shell常见通配符有那一些了。

shell常见通配符:

                   字符           含义           实例           *           匹配 0或多个字符           a*b a与b之间可以有任意长度的任意字符,也可以一个也没有,如aabcb, axyzb, a012b, ab。           ?           匹配任意一个字符           a?b a与b之间必须也只能有一个字符,可以是任意字符,如aab, abb, acb, a0b。           [list]           匹配 list中的任意单一字符           a[xyz]b  a与b之间必须也只能有一个字符,但只能是 x或 y或 z,如: axb, ayb, azb。           [!list]           匹配除list中的任意单一字符           a[!0-9]b a与b之间必须也只能有一个字符,但不能是阿拉伯数字,如axb, aab, a-b。           [c1-c2]           匹配 c1-c2中的任意单一字符如:[0-9] [a-z]           a[0-9]b 0与9之间必须也只能有一个字符如a0b, a1b... a9b。           {string1,string2,...}           匹配 sring1或 string2(或更多)其一字符串           a{abc,xyz,123}b   a与b之间只能是abc或xyz或123这三个字符串之一。               

需要说明的是:通配符看起来有点象正则表达式语句,但是它与正则表达式不同的,不能相互混淆。把通配符理解为shell特殊代号字符就可。而且涉及的只有,*,? [],{}这几种。

二、shell元字符(特殊字符 Meta)

shell除了有通配符之外,由shell负责预先先解析后,将处理结果传给命令行之外,shell还有一系列自己的其他特殊字符。

               字符   说明   IFS   由 space或 tab或 enter三者之一组成(我们常用 space)。   CR   由 enter产生。   =   设定变量。   $   作变量或运算替换(请不要与 shell prompt搞混了)。      重导向 stdout。*      重导向 stdin。*   |   命令管线。*      重导向 file descriptor,或将命令置于背境执行。*   ()   将其内的命令置于 nested subshell执行,或用于运算或命令替换。*   {}   将其内的命令置于 non-named function中执行,或用在变量替换的界定范围。   ;   在前一个命令结束时,而忽略其返回值,继续执行下一个命令。*      在前一个命令结束时,若返回值为 true,继续执行下一个命令。*   ||   在前一个命令结束时,若返回值为 false,继续执行下一个命令。*   !   执行 history列表中的命令。*           

加入”*”都是作用在命令名直接。可以看到shell元字符,基本是作用在命令上面,用作多命令分割(或者参数分割)。因此看到与通配符有相同的字符,但是实际上作用范围不同。所以不会出现混淆。

以下是man bash得到的英文解析:

metacharacter

 A character that, when unquoted, separates words. One of the following:

 | ;() space tab

   control operator

 A token that performs a control function. It is one of the following symbols:

 ||;;;()| newline

   三、shell转义符

有时候,我们想让通配符,或者元字符变成普通字符,不需要使用它。那么这里我们就需要用到转义符了。 shell提供转义符有三种。

               字符   说明   ‘’(单引号)   又叫硬转义,其内部所有的shell元字符、通配符都会被关掉。注意,硬转义中不允许出现’(单引号)。   “”(双引号)   又叫软转义,其内部只允许出现特定的shell元字符:$用于参数代换 `用于命令代替   /(反斜杠)     又叫转义,去除其后紧跟的元字符或通配符的特殊意义。           

man bash英文解释如下:

There are three quoting mechanisms: the escape character, single quotes, and double quotes.

实例:

复制代码

   

代码如下:

[chengmo@localhost~/shell]$ ls/*.txt

   ls:无法访问*.txt:没有那个文件或目录

   [chengmo@localhost~/shell]$ ls'*.txt'

   ls:无法访问*.txt:没有那个文件或目录

   [chengmo@localhost~/shell]$ ls'a.txt'

   a.txt

   [chengmo@localhost~/shell]$ ls*.txt

   a.txt b.txt

可以看到,加入了转义符“*”已经失去了通配符意义了。

四、shell解析脚本的过程

看到上面说的这些,想必大家会问到这个问题是,有这么想特殊字符,通配符,那么 shell在得到一条命令,到达是怎么样处理的呢?我们看下下面的图:

如果用双引号包括起来,shell检测跳过了1-4步和9-10步,单引号包括起来,shell检测就会跳过了1-10步。也就是说,双引号只经过参数扩展、命令代换和算术代换就可以送入执行步骤,而单引号转义符直接会被送入执行步骤。而且,无论是双引号转义符还是单引号转义符在执行的时候能够告诉各个命令自身内部是一体的,但是其本身在执行时是并不是命令中文本的一部分。

阅读剩余
THE END