Linux(15):shell 编程

shell基础

什么是 shell ?

Shell是一个命令解释器,它的作用是解释执行用户输入的命令及程序等,用户输入一条命令, Shell 就解释执行一条。
这种从键盘一输入命令,就可以立即得到回应的对话方式,被称之为交互的方式。

Shell存在于操作系统的最外层,负责直接与用户对话,把用户的输入解释给操作系统,并处理各种各样的操作,
系统的输出结果,输出到屏幕返回给用户,当我们输入系统用户名和密码,登录到 Linux 后的所有操作都是由Shell 解释并执行的。

什么是 shell 脚本?

当命令或程序语句不在命令行下执行,而是通过一个程序文件执行时,该程序就被称为 Shell 脚本。
如果在 Shell 脚本里内置了很多条命令、语句及循环控制,然后一次性把这些命令执行完,这种通过文件执行脚本的方式,称为非交互的方式。 
Shell 脚本类似于 DOS 系统下的批处理程序。用户可以在 Shell 脚本中敲入一系列的命令及命令语句组合。
这些命令、变量和流程控制语句等有机地结合起来就形成了一个 Shell 脚本。


# 示例:清除/var/log下messages日志文件的Shell脚本(含命令、变量和流程控制语句)
#!/bin/bash

LOG_DIR=/var/log
ROOT_UID=0

# 第一步:必须是 root 用户才能执行脚本,否则给出提示并终止脚本运行

if [ "$UID" -ne "$ROOT_UID" ]                    # $UID 是系统变量
then
    echo "only root user can run this script"
    exit 1 
fi

# 第二步:成功切换到目录 /var/log ,否则给出提示并终止脚本运行
cd $LOG_DIR || {                                # || 的作用:前面的命令执行失败了,则执行后面的操作
    echo "change dir failed"
    exit 1
}

# 第三步:清理日志 /var/log/message ,清理成功,给出正确提示
cat /dev/null>messages && {                        # && 的作用:前面的操作执行成功了,再执行后面的操作
    echo "Logs cleaned up."
    exit 0
}

# 第四步:清理失败,给出相应提示
echo "Logs cleaned up failed"
exit 1

Shell脚本在Linux运维工作中地位

Shell脚本语言很擅长处理纯文本类型的数据,而Linux系统中几乎所有的配置文件、日志文件(如NFS、Rsync、Httpd、Nginx、LVS、MySQL
等),以及绝大多数的启动文件都是纯文本类型的文件。自然学好Shell脚本语言,就可以利用它在Linux系统中发挥巨大的作用。

Shell脚本语言和3P语言对比

Shell脚本语言的优势在于处理偏操作系统底层的业务,例如:Linux系统内部的很多应用,对于一些常见的企业业务,使用Shell开发会更简单
快速,例如:让软件一键自动化安装、优化,监控报警脚本,软件启动脚本,日志分析脚本等,虽然PHP/Python语言也能够做到,但是,考虑到
掌握难度、开发效率、开发习惯等,它们可能就不如用Shell脚本语言流行及有优势了。对于一些常规的业务应用,使用Shell更符合Linux运维简
单、易用、高效的三大基本原则。

PHP语言:
PHP是网页程序语言,也是脚本语言。是一款更注于Web页面开发(前端展示)的语言,例如:wordpress、dedecms、discuz等著名开源产品都是用
PHP语言开发的。

Perl语言:
Perl脚本语言,语法灵活、复杂,缺点是不易读,团队协作困难,存世的大量相关程序软件(比如,xtrabackup热备工具、MySQL MHA集群高可用
软件等都有Perl语言的身影)。

Python语言:
Python是当下流行的语言,不但可以用于脚本程序开发,也可实现Web程序开发(例如:CMDB管理系统),还可以做软件开发( OpenStack)、
游戏开发、大数据开发、移动端开发。

shell脚本的注释

#号后面表示注释

# 多行注释:
# 方式1:
插入注释:
按CTL+v(win下面ctrl+q)进入列模式;
按大些“I”进入插入模式,输入注释符“#”或者是"//",然后立刻按下ESC(两下)

取消注释:
Ctrl + v 进入块选择模式,选中你要删除的行首的注释符号,注意// 要选中两个,选好之后按d即可删除注释

# 方式2:
把需要注释的代码放到 :<<EOF...EOF 中,如下所示:
:<<EOF
echo "hello world"
echo "hello world"
EOF

# 方式2 的原理:冒号在shell里面也是命令,表示什么都不做

# 方式3:
把需要注释的代码放到 cat >/dev/null<<EOF...EOF 中,如下:
cat >/dev/null<<EOF
echo "hello world"
echo "hello world"
EOF

Shell脚本的执行

# 方式1. bash script name 或 sh script name
这是当脚本文件本身没有可执行权限(即文件权限属性x位为 号)时常使用的方法,或者脚本文件开头没有指定解释器时需要使用的方法(推荐)

# 方式2. path/script name 或 ./script name
指在当前路径下执行脚本(脚本要有执行权限),需要先将脚本文件的权限改为可执行(即文件权限属性加 x位),
具体方法为 chmod +x script name 。然后通过脚本绝对路径或相对路径就可以直接执行脚本了。

# 方式3. source script name 或 . script name

# 方式4. sh <script name 或 cat scripts name|sh

# 示例:关闭开机自启动的程序
chkconfig --list|grep 3:on|awk '{print "chkconfig",$1,"off"}'|bash        # 非循环的方法


# Shell脚本执行过程及父子Shell知识和互相调用

# 登陆一个命令行时,就相当于开启了一个 shell
# 示例
[root@m01 scripts]# cat test.sh 
user=`whoami`                            # 运行这个脚本时,`whoami` 会执行,即把 root 赋值给 user 变量
[root@m01 scripts]# sh test.sh             # 此时的 sh test.sh 相当于 新开启了一个 shell (子shell),即在一开始登陆的shell下新开启了一个子shell
[root@m01 scripts]# echo $user            # 这个 shell 是你一开始登陆时的 shell    (父shell)
                                        # 一开始登陆的 shell 中找不到 user 这个变量的值
[root@m01 scripts]# source test.sh         # 当 source 执行一个脚本时,这个脚本相当于是在当前 shell 下运行(即一开始登陆的shell),即此时没有开启新的shell
[root@m01 scripts]# echo $user 
root                                    # 经过 source test.sh 之后,echo $user 就会有输出
[root@m01 scripts]# cat call_test.sh    
sh test.sh                                # 在 call_test.sh 中又执行了一个新的子shell
echo $user
[root@m01 scripts]# sh call_test.sh     # sh call_test.sh 执行了一个新的子shell
                                        # call_test.sh 这个子shell 无法调用 test.sh 这个子shell中的变量(test.sh的shell相当于call_test.sh shell的子shell)
[root@m01 scripts]# cat call_test.sh
source ./test.sh                        # 利用 source 或 . 能让 test.sh 和 call_test.sh 在同一个shell下面执行脚本
echo $user
[root@m01 scripts]# sh call_test.sh 
root                                    # 利用 source 或 . 就能让 call_test.sh 中 shell 获取到 test.sh 的shell 中的内容
[root@m01 scripts]# OLDBOY=oldboy        # 在一开始登陆的shell中定义一个变量 OLDBOY
[root@m01 scripts]# cat call_parent.sh 
echo $OLDBOY                            # 在 call_parent.sh 的 shell 中调用父shell中的变量 OLDBOY
[root@m01 scripts]# sh call_parent.sh 
                                        # 无法调用 父shell 中的变量
[root@m01 scripts]# source call_parent.sh     # 利用 source 也能让 子shell调用父shell 中的变量
oldboy
[root@m01 scripts]# 

# 使用 source 和 . 来执行脚本,相当于在同一个shell下面执行脚本,此时变量可以相互调用;
# bash 或 sh 来执行脚本,会开启一个新的 shell (一个子shell,父shell调用不了子shell中的变量)

# 父shell和子shell的概念:
在脚本A中运行的脚本B就称为脚本A的子shell, A 是 B 的父shell;
父shell和子shell之间默认不能互相调用 

猜你喜欢

转载自www.cnblogs.com/neozheng/p/11071412.html