首页 > 代码库 > bash脚本编程基础及配置文件

bash脚本编程基础及配置文件

shell脚本编程

         编程语言的分类:根据运行方式

                   编译运行:源代码----->编译器(编译)---->程序文件

                            C语言:

                   解释运行:源代码--->运行时启动解释器,由解释器边解释边运行;

 

         根据其编程过程中功能的实现是调用库还是调用外部的程序文件:

                   shell脚本编程:

                            利用系统上的命令及编程组件进行编程;

                   完成编程:

                            利用库或编程组件运行编程

 

         编程模型:

                   过程式编程语言,面向对象的编程语言

         程序=指令+数据

                   过程式:以指令为中心来组织代码,数据是服务于代码;

                            顺序执行

                            选择执行

                            循环执行

                            C语言,bash脚本语言)

                   对象式:以数据为中心来组织代码,围绕数据来组织指令;

                            类(class):实例化对象,method

                            JAVAC++Python

 

shell脚本编程:(特性)

         1)过程式编程

         2)解释运行

         3)依赖于外部程序文件

 

如何写shell脚本:

         脚本文件的第一行,顶格写,给出shebang,解释器路径,用于指明解释执行当前脚本的解释器程序文件

                   常见的解释器:

                            #!/bin/bash

                            #!/usr/bin/python

                            #!/usr/bin/perl

 

文本编辑器:nano

         行编辑器:sed

         全屏幕编辑器:nano,vim,vi

使用namo命令:

         ctrl+G:求助   ctrl+O:写入   ctrl+R:读档   ctrl+Y:上页   ctrl+V:下页 

         ctrl+K:剪切文字    ctrl+U:还原剪切   ctrl+C:游标位置    ctrl+T:拼写检查

         ctrl+X:离开    ctrl+J:对齐

一般而言shell脚本都以“.sh”结尾。

 

shell脚本是什么?

         命令的堆积;

         但是很多命令不具有幂等性,需要用程序逻辑来判断运行条件是否满足,以避免其运行         中发生错误;

 

编写第一个shell脚本:

 

         nanomyshell.sh

脚本内容为:

         #!/bin/bash

         useradduser3

         echo"user3" | passwd --stdin user3

         mktemp-d /tmp/test.XXX

最后脚本写完后,直接按“ctrl+X”保存退出

要想执行脚本,先看一下这个脚本的权限

                   [root@centos6~]# ls -l myshell.sh

                   -rw-r--r--.1 root root 86 Oct 26 22:51 myshell.sh

再看当前用户是以什么身份登入的:

                   [root@centos6~]# whoami

                   root

给用户加执行权限:

                   [root@centos6~]# chmod +x myshell.sh

                   [root@centos6~]# ls -l myshell.sh

                   -rwxr-xr-x.1 root root 86 Oct 26 22:51 myshell.sh

                   [root@centos6~]#

最后执行脚本:

[root@centos6 ~]# ./myshell.sh    

Changing password for user user3.

passwd: all authentication tokens updatedsuccessfully.

/tmp/test.noG

[root@centos6 ~]#

 

注意当我们再次运行上面的脚本时,我们的脚本还会执行,只是第一个创建用户的命令创建失败了,下面的两条命令执行成功了。

 

这说明,在shell脚本中并不是所有的命令失败,都会导致脚本终止的,而是命令执行失败,如果产生严重的错误,这种严重的错误比如会“exit”,一般而言任何脚本遇到“exit”都会终止或者我们使用某种判断机制将其强行终止。或者我们的脚本运行中出现了语法错误。脚本才有可能终止。

 

所以我我们可以将上面的脚本创建用户时,加一个判断,用户在就不创建,不在就创建,那么就是将第一个命令改为id user3||useradd user3”这样再次执行脚本就不会报错了

运行脚本:

         1)赋予执行权限,并执行运行此程序文件;

                            chmod  +x /PATH/TO/SCRIPT_FILE      //一加x所有的用户都有了执行权限

                            ./SCRIPT_FILE       //相对路径

                            /PATH/TO/SCRIPT_FILE     //绝对路径

         2)直接运行解释器,将脚本以命令行参数传递给解释器程序

                            bash /PATH/TO/SCRIPT_FILE

(解释:

                   使用解释器运行脚本,本质上其实就是利用了linux内核有一个特性,他可以通过文本的前n个字节,来判定这是一个什么格式的文件,尤其是看到文件前两个字节是“#!”就知道后面是shell脚本程序文件,我们不需要直接运行这个文件,而是先运行“#!”后面的解释器程序,然后由这个解释器程序来解释运行这个文件中的程序代码。)

 

演示:

[root@centos6 ~]# ll myshell.sh

-rw-r--r--. 1 root root 98 Oct 26 23:12myshell.sh

[root@centos6 ~]# bash myshell.sh

uid=502(user3) gid=502(user3)groups=502(user3)

Changing password for user user3.

passwd: all authentication tokens updatedsuccessfully.

/tmp/test.BkL

[root@centos6 ~]#

 

这也说明了,shell是严重依赖命令的,不然怎么说shell脚本是命令的堆积呢

 

 

练习1:写一个脚本,实现如下功能:

         1)显示/etc/目录下所有以大写P或小写p开头的文件或目录本身;

         2)显示/var目录下的所有文件或目录本身,并将显示结果中的小写字母转换为大写后显示:

         3)创建临时文件/tmp/myfile.XXXX

 

         解:

                            #!/bin/bash

                            ls  -d /etc/[Pp]*

                            ls   -d  /var/* |  tr  [:lower:] [:upper:]

                  

                            ls   -d /var/*  |  tr ‘a-z‘  ‘A-Z‘

                            mktemp  /tmp/myfile.XXXX

 

(拓展:

         上面的脚本我们还可以进行优化:

                   上面的脚本执行过程中没有执行后的反馈,我们可以进一步的进行完善:

                   如下:

         #!/bin/bash

         echo  "Show some  under  /etc"      //echo的内容都是直接显示在屏幕上

         ls  -d /etc/[Pp]*

         echo  "Traslate  lower to  upper"

         ls  -d /var/*  |  tr  ‘a-z‘  ‘A-Z‘

         echo  "Create a  temp  file"

         mktemp  /tmp/myfile.XXXX

 

注意:

         1)脚本中的空白行直接被忽略,所以不会输出空白行

         2)脚本中,除了shebang,余下所有以#开头的行,都会被视作注释行而被忽略;此           即为注释行

         3)如果想从脚本中输出一个空白行,则在脚本中加上一行,并且这行中只写一个echo

         4shell脚本的运行是通过运行一个子shell进程实现的;

 

 

bash的配置文件:定义别名

         (我们之前讲的,在shell进程中定义的别名,当我们的系统重启以后,当我们的shell登出再登录以后,我们在shell下定义的特性,包括变量,他的生命周期仅是当前shell进程,如果想突破这样的生命周期,我们应该在他的配置文件中定义)

        

         bash程序有两大类的配置文件:

                   profile

                   bashrc

 

                   profile类:为交互式登录的shell进程提供配置

                   bashrc类:为非交互式登录的shell进程提供配置

 

         登录类型:

                   交互式登录shell进程;

                            直接通过某终端输入账号和密码后登录打开的shell进程;

                            使用su命令:su -USERNAME,或者使用 su -l USERNAME执行的登录切换;

 

                   非交互式登录shell进程:

                            suUSERNAME执行的登录切换;

                            图形界面下打开的终端;

                            运行脚本时

 

         profile类:

                   全局:对所有用户都生效;

                            /etc/profile

                            /etc/profile.d/*.sh

                   用户个人:仅对当前用户有效;

                            ~/.bashrc_profile

                  功能:

                            1)用于定义环境变量;

                            2)运行命令或脚本;

 

         bashrc类:

                   全局:

                            /etc/bashrc

                   用户个人:

                            ~/.bashrc

                   功用:

                            1)定义本地变量;

                            2)定义命令别名;

注意:

         1)定义命令别名时,定义在全局文件“/etc/profile”或“/etc/bashrc”还是定义在用户个人文件“~/.bashrc_profile”或“~/.bashrc”文件中,要看我们自己的需要,如果是想要定义对所有的用户有效的命令别名,则就定义在文件“/etc/profile”或“/etc/bashrc”中,如果是只想对特定用户有效,那么就将命令别名定义在用户本身的家目录文件“~/.bashrc_profile”或“~/.bashrc”中。

         2)只用管理员用户才有权限定义全局的,普通用户是没有权限进行编辑的。

         3)当我们真正登录一个shell时,shell有这么多的配置文件,那么我们的shell应该先读取哪一个,后读取哪一个文件?

         举例:我们在全局文件中,定义“name=jerry”,在个人配置文件中定义“name=tom”,那么这个变量name,到底等于谁?是先读取的生效,还是后读取的生效?

         解:

                   后读的才是最终生效,因此配置文件的读取的次序才是至关重要。

                  

 

配置文件的读取次序:

         交互式登录shell进程:

                   /etc/profile------->/etc/profile.d/*------->~/.bash_profile------>~/.bashrc----->/etc/bashrc

         非交互式登录shell进程:

                   ~/.bashrc------>/etc/bashrc------->/etc/profile.d/*

 

(所以我们自己编辑的脚本在运行时,他的环境是取决于“~/.bashrc---->/etc/bashrc---->/etc/pprofile.d/*”这三个文件的,如果是登录系统是,则就取决于“/etc/profile---->/etc/profile.d/*----->~/.bashrc_profile------>~/.bashrc------>/etc/bashrc”这五个文件的。此前我们也知道,在命令行中定义的,不会永久有效,但是在change文件中定义的他不会立即有效,在配置文件中定义的,只对下次新登录的shell进程有效,对以往的老shell进程是无效的,)

 

         命令行中定义的特性,例如变量和别名作用于当前的shell进程的生命周期,即立即生效

         配置文件中定义的特性,只对随后新启动的shell进程有效;

让通过配置文件定义的特性立即生效:

         1)通过命令行重复定义一次;

         2)让shell进程重读配置文件;

                            重读配置文件,执行下面的命令:(点号就相当于source

                                              ~]#source  /PATH/FROM/CONF_FILE

                                    

                                               ~]#.  /PATH/FROM/CONF_FILE(配置文件的路径)

 

注意:定义别名,主要是定义在/etc/bashrc~/.bashrc文件中。

 

 

需求:

 

         如果我们希望每次用户登录成功以后,都会echo一下,显示说“欢迎登录系统,你已经进入监控区域,你的所有行为都将被记录,请注意您的言行”那么应该怎么实现呢?

         分析:

         要想让用户登录以后,能执行命令,应该在bashrc的配置文件中定义还是在profile文件中定义?我们知道,profile命令的两个功能:(1)用于定义环境变量;(2)运行命令或脚本;那么我们应该在全局中写还是在个人的家目录中写?如果要想让所有的用户登陆后都能显示,那就全局写,否则就在个人目录下写。

         假设我们在全局下写,我们应该写在那呢?

                   profile类的文件有两大类,(1/etc/profile2/etc/profile.d/*,那么我们要是在/etc/profile.d/目录下自己建立一个目录,以后管理也好管理,不用的时候直接删除就行。

         因此在“/etc/profile.d/”下创建一个文件名随便起,但是要以“.sh”结尾的文件例如:

该文件叫“welcome.sh

         编辑的内容为:

                            echo  "welcome aboard....."

然后当我们再次登录一个shell进程时,就会在shell刚开始前面出现我们编写内容:

技术分享

 

所以,如果我们想在用户登录时给一些提示信息,那么我们就可以在“/etc/profile.d/”目录下定义一个“.sh”结尾的文件,或者在“/etc/profile”文件中定义。

 

有些配置不会立即生效,但是对后来的新登录的窗口有效。

我们还可以在这样的配置文件中定义一些环境变量的。

         举例:

                   输出当前系统下的JAVA环境所在,我们通常输出一个环境变量叫JAVA_HOME

创建一个文件,vim  /etc/profile.d/java.sh,(因为输出环境变量使用“export”或“declare  -x”)然后在写的文件内容为:“export  JAVA_HOME=/usr这样就定义了一个环境变量“JAVA_HOME”,但是这么文件不会立即有效,需要重读这个配置为文件,使用命令点“.”或“source重读文件java.sh,然后执行一下命令“export”或“declare  -x”即可显示新定义的环境变量。

 

 

问题:

         1)如何定义对所有用户都生效的命令别名,例如  lftps=‘lftp 10.1.0.1/pub‘

         2)如何实现centos用户登录时,提示其已经登录,并显示当前系统时间(提示显示当前系统时间,可以通过命令引用来实现,也可以直接写在文件中)

         3)如何实现root用户的PATH环境查询多几个查询路径

 

 


本文出自 “11847750” 博客,请务必保留此出处http://11857750.blog.51cto.com/11847750/1875092

bash脚本编程基础及配置文件