news 2026/9/11 6:24:45

Shell编程——初步入门

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Shell编程——初步入门

初步入门

    • 1、什么时Shell
    • 2、什么是Shell脚本
    • 3、Shell脚本在Linux运维工作中的地位
    • 4、脚本语言的种类
      • 4.1、Shell脚本语言的种类
      • 4.2、其他常用的脚本语言种类
      • 4.3、Shell脚本语言的优势
    • 5、常用操作系统默认的Shell
    • 6、Shell脚本的建立和执行
      • 6.1、Shell脚本的建立
      • 6.2、Shell脚本的执行
      • 6.3、Shell脚本开发的基本规范及习惯

1、什么时Shell

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

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

下图针对命令解释器Shell在操作系统中所处的位置给出了基本图解。

提示:Shell的英文是贝壳的意思,从图中可以看出,命令解释器(Shell)就像贝壳一样包住了系统核心。

2、什么是Shell脚本

理解了Shell之后,再理解Shell脚本就简单了。当命令或程序语句不在命令行下执行,而是通过一个程序文件来执行时,该程序就被称为Shell脚本。如果在Shell脚本里内置了很多条命令、语句及循环控制,然后将这些命令一次性执行完毕,这种通过文件执行脚本的方式称为非交互的方式。Shell脚本类似于DOS系统下的批处理程序(早期扩展名一般为“*.bat”​)​。用户可以在Shell脚本中敲入一系列的命令及命令语句组合。这些命令、变量和流程控制语句等有机地结合起来,就形成了一个功能强大的Shell脚本。

下面是在Windows下利用bat批处理程序开发的备份企业网站及数据库数据的脚本范例。

在Windows下利用bat批处理程序备份网站及数据库数据的脚本。

@echo off set date=%date:~0,4%-%date:~5,2%-%date:~8,2% #<==定义时间变量。 mysqldump -uroot -poldboy -A -B > D:\bak\"%date%".sql #<==备份数据库数据。 rar.exe a -k -r -s -m1 D:\bak\"%date%".sql.rar D:\bak\"%date%".sql #<==打包备份出来的数据库数据。 del D:\bak\*.sql #<==删除未打包的无用数据库数据。 rar.exe a -k -r -s -m1 D:\bak\"%date%"htdocs.rar D:\work\PHPnow\htdocs #<==打包站点目录下的数据。

清除/var/log下messages日志文件的简单命令脚本。

# 清除日志脚本, 版本 1。cd/var/logcat/dev/null>messagesecho"Logs cleaned up."

提示:/var/log/messages是Linux系统的日志文件,很重要。

上面所示的脚本其实是有一些问题的,具体如下:

  1. 如果不是root用户,则无法执行脚本清理日志,并且会提示系统的权限报错信息。
  2. 没有任何流程控制语句,简单地说就是只进行顺序操作,没有成功判断和逻辑严密性。

范例:写一个包含命令、变量和流程控制的语句来清除/var/log下messages日志文件的Shell脚本。

# ! /bin/bash# 清除日志脚本, 版本 2LOG_DIR=/var/logROOT_UID=0#<==$UID为0的用户,即root用户# 脚本需要使用root用户权限来运行,因此,对当前用户进行判断,对不合要求的用户给出友好提示,并终止程序运行。if["$UID"-ne"$ROOT_UID"]#<==如果当前用户不是root,则不允许执行脚本。thenecho"Must be root to run this script."#<==给出提示后退出。exit1#<==退出脚本。fi# 如果切换到指定目录不成功,则给出提示,并终止程序运行。cd$LOG_DIR||{echo"Cannot change to necessary directory."exit1}# 经过上述两个判断后,此处的用户权限和路径应该就是对的了,只有清空成功,才打印成功提示。cat/dev/null>messages&&{echo"Logs cleaned up."exit0# 退出之前返回0表示成功,返回1表示失败。}echo"Logs cleaned up fail."exit1

初学者如果想要快速掌握Shell脚本的编写方法,最有效的思路就是采用电子游戏中过关的方式,比如,对于范例脚本可以设计成如下几关:

  • 第一关,必须是root才能执行脚本,否则给出友好提示并终止脚本运行。
  • 第二关,成功切换目录(cd /var/log)​,否则给出友好提示并终止脚本运行。
  • 第三关,清理日志(cat /dev/null > messages)​,若清理成功,则给出正确提示。
  • 第四关,通关或失败,分别给出相应的提示(echo输出)​。

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

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

下图形象地展示了Shell脚本在运维工作中的地位。

4、脚本语言的种类

4.1、Shell脚本语言的种类

Shell脚本语言是弱类型语言(无须定义变量的类型即可使用)​,在Unix/Linux中主要有两大类Shell:一类是Bourne shell,另一类是C shell。

1. Bourne shell

Bourne shell又包括Bourne shell(sh)​、Korn shell(ksh)​、Bourne Again Shell(bash)三种类型。

  • Bourne shell(sh)由AT&T的Steve Bourne开发,是标准的UNIX Shell,很多UNIX系统都配有sh。
  • Korn shell(ksh)由David Korn开发,是Bourneshell(sh)的超集合,并且添加了csh引入的新功能,是目前很多UNIX系统标准配置的Shell,这些系统上的/bin/sh往往是指向/bin/ksh的符号链接。
  • Bourne Again Shell(bash)由GNU项目组开发,主要目标是与POSIX标准保持一致,同时兼顾对sh的兼容,bash从csh和ksh借鉴了很多功能,是各种Linux发行版默认配置的Shell, Linux系统上的/bin/sh往往是指向/bin/bash的符号链接。尽管如此,bash和sh还是有很多的不同之处:一方面,bash扩展了一些命令和参数;另一方面,bash并不完全和sh兼容,它们有些行为并不一致,但在大多数企业运维的情况下区别不大,特殊场景可以使用bash替代sh。

** 2. C shell**

C shell又包括csh、tcsh两种类型。

  • csh由Berkeley大学开发,随BSD UNIX发布,它的流程控制语句很像C语言,支持很多Bourne shell所不支持的功能,例如:作业控制、别名、系统算术、命令历史、命令行编辑等。
  • tcsh是csh的增强版,加入了命令补全等功能,在FreeBSD、Mac OS X等系统上替代了csh。

以上介绍的这些Shell中,较为通用的是标准的Bourneshell(sh)和C shell(csh)​。其中Bourne shell(sh)已经被Bourne Again shell(bash)所取代。

可通过以下命令查看CentOS 6系统的Shell支持情况。

[root@oldboy ~]# cat /etc/shells/bin/sh#<==这是Linux里常用的Shell,指向/bin/bash。/bin/bash#<==这是Linux里常用的Shell,也是默认使用的Shell。/sbin/nologin#<==这是Linux里常用的Shell,用于禁止用户登录。/bin/dash /bin/tcsh /bin/csh

Linux系统中的主流Shell是bash, bash是由Bourne Shell(sh)发展而来的,同时bash还包含了csh和ksh的特色,但大多数脚本都可以不加修改地在sh上运行,如果使用了sh后发现结果和预期有差异,那么可以尝试用bash替代sh。

4.2、其他常用的脚本语言种类

  • 1. PHP语言
    PHP是网页程序语言,也是脚本语言。它是一款更专注于Web页面开发(前端展示)的语言,例如:wordpress、dedecms、discuz等著名的开源产品都是用PHP语言开发的。用PHP程序语言也可以处理系统日志、配置文件等,还可以调用Linux系统命令,但是,很少有人这么用。
  • 2. Perl语言
    Perl脚本语言比Shell脚本语言强大很多,在2010年以前很流行,它的语法灵活、复杂,在实现不同的功能时可以用多种不同的方式,缺点是不易读,团队协作困难,但它仍不失为一种很好的脚本语言,存世的大量相关程序软件
  • 3. Python语言
    Python是近几年非常流行的语言,它不但可以用于脚本程序开发,也可以实现Web页面程序开发(例如:CMDB管理系统)​,甚至还可以实现软件的开发(例如:大名鼎鼎的OpenStack、SaltStack都是Python语言开发的)​、游戏开发、大数据开发、移动端开发。

4.3、Shell脚本语言的优势

Shell脚本语言的优势在于处理偏操作系统底层的业务,例如:Linux系统内部的很多应用(有的是应用的一部分)都是使用Shell脚本语言开发的,因为有1000多个Linux系统命令为它做支撑,特别是Linux正则表达式及三剑客grep、awk、sed等命令。

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

PHP语言的优势在于小型网站系统的开发;Python语言的优势在于开发较复杂的运维工具软件、Web界面的管理工具和Web业务的开发(例如:CMDB自动化运维平台、跳板机、批量管理软件SaltStack、云计算OpenStack软件)等。我们在开发一个应用时应根据业务需求,结合不同语言的优势及自身擅长的语言来选择,扬长避短,从而达到高效开发及易于自身维护等目的。

5、常用操作系统默认的Shell

在常用的操作系统中,Linux下默认的Shell是BourneAgain shell(bash); Solaris和FreeBSD下默认的是Bourne shell(sh); AIX下默认的是Korn Shell(ksh)​。

这里重点讲Linux系统环境下的Bourne Again shell(bash)​。

下面来看一个企业面试题:CentOS Linux系统默认的Shell是什么?这题的答案就是bash。

通过以下两种方法可以查看CentOS Linux系统默认的Shell。

  • 方法1:
    [root@oldboy ~]# echo $SHELL/bin/bash
  • 方法2:
    [root@oldboy ~]# grep root /etc/passwdroot:x:0:0:root:/root:/bin/bash

提示:结尾的/bin/bash就是用户登录后的Shell解释器。

注意:本书写作的环境为Linux系统,具体版本为CentOS 6.x x86_64,绝大部分已写好的脚本程序都不需要经过任何修改,就可以直接应用于其他的Linux系统中。对于一些UNIX系统,因为默认不是bash解释器,所以需要根据解释器版本进行调整,本书的全部内容都是以bash及和bash兼容的sh解释器为基础编写的。

6、Shell脚本的建立和执行

6.1、Shell脚本的建立

在Linux系统中,Shell脚本(bash Shell程序)通常是在编辑器vi/vim中编写的,由UNIX/Linux命令、bash Shell命令、程序结构控制语句和注释等内容组成。这里推荐用Linux自带的功能更强大的vim编辑器来编写,可以事先做一个别名alias vi=‘vim’,并使其永久生效,这样以后习惯输入vi的读者也就可以直接调用vim编辑器了,设置方法如下:

[root@oldboy ~]# echo "alias vi='vim'" >>/etc/profile[root@oldboy ~]# tail -1 /etc/profilealiasvi='vim'[root@oldboy ~]# source /etc/profile

1.脚本开头(第一行)

一个规范的Shell脚本在第一行会指出由哪个程序(解释器)来执行脚本中的内容,这一行内容在Linux bash的编程一般为:

#! /bin/bash#! /bin/sh #<==255个字符以内。

其中,开头的“#! ”字符又称为幻数(其实叫什么都无所谓,知道它的作用就好)​,在执行bash脚本的时候,内核会根据“#! ”后的解释器来确定该用哪个程序解释这个脚本中的内容。

注意,这一行必须位于每个脚本顶端的第一行,如果不是第一行则为脚本注释行,例如下面的例子。

[oldboy@oldboy ~]$cattest.sh#! /bin/bashecho"oldboy start"#! /bin/bash #<==写到这里就是注释了。#! /bin/sh #<==写到这里就是注释了。echo"oldboy end"

2. bash与sh 的区别

早期的bash与sh稍有不同,它还包含了csh和ksh的特色,但大多数脚本都可以不加修改地在sh上运行,比如:

[root@oldboy ~]# ll /bin/shlrwxrwxrwx.1root root431920:54 /bin/sh ->bash[root@oldboy ~]# ll /bin/bash-rwxr-xr-x1root root940416101621:56 /bin/bash

提示:sh为bash的软链接,大多数情况下,脚本的开头使用“#! /bin/bash”和“#! /bin/sh”是没有区别的,但更规范的写法是在脚本的开头使用“#!/bin/bash”​。

下面的Shell脚本是系统自带的软件启动脚本的开头部分。

[root@oldboy ~]# head -1 /etc/init.d/sshd#! /bin/bash[root@oldboy ~]# head -1 /etc/init.d/ntpd#! /bin/bash[root@oldboy ~]# head -1 /etc/init.d/crond#! /bin/sh

提示:如果使用/bin/sh执行脚本出现异常,那么可以再使用/bin/bash试一试,但是一般不会发生此类情况。

一般情况下,在安装Linux系统时会自动安装好bash软件,查看系统的bash版本的命令如下。

[root@oldboy ~]# cat /etc/redhat-releaseCentOS release6.8(Final)#<==这里显示的是作者写作的Linux的环境版本。[root@oldboy ~]# bash --versionGNU bash, version4.1.2(1)-release(x86_64-redhat-linux-gnu)#<==这里显示的是bash的版本。Copyright(C)2009Free Software Foundation, Inc.#<==下面几行是自由软件提示的相关信息。License GPLv3+: GNU GPL version3or later <http://gnu.org/licenses/gpl.html> This isfreesoftware;you arefreeto change and redistribute it. There is NO WARRANTY, to the extent permitted by law.

如果读者使用的是较老版本的Shell,那么建议将其升级到最新版本的Shell,特别是企业使用,因为近两年老版本的bash被暴露出存在较严重的安全漏洞。

例如:bash软件曾经爆出了严重漏洞(破壳漏洞)​,凭借此漏洞,攻击者可能会接管计算机的整个操作系统,得以访问各种系统内的机密信息,并对系统进行更改等。任何人的计算机系统,如果使用了bash软件,都需要立即打上补丁。检测系统是否存在漏洞的方法为:

[root@oldboy ~]# env x='() { :; }; echo be careful' bash -c "echo this is a test"this is atest

如果返回如下两行,则表示需要尽快升级bash了,不过,仅仅是用于学习和测试就无所谓了。

be careful this is atest

升级方法为:

[root@oldboy ~]# yum -y update bash[root@oldboy ~]# rpm -qa bashbash-4.1.2-40.el6.x86_64

下面是Linux中常用脚本开头的写法,不同语言的脚本在开头一般都要加上如下标识内容:

1#! /bin/sh2#! /bin/bash3#! /usr/bin/awk4#! /bin/sed5#! /usr/bin/tcl6#! /usr/bin/expect #<==expect解决交互式的语言开头解释器。7#! /usr/bin/perl #<==perl语言解释器。8#! /usr/bin/env python #<==python语言解释器。

CentOS和Red Hat Linux下默认的Shell均为bash。因此,在写Shell脚本的时候,脚本的开头即使不加“#!/bin/bash”​,它也会交给bash解释。如果写脚本不希望使用系统默认的Shell解释,那么就必须要指定解释器了,否则脚本文件执行后的结果可能就不是你所要的。建议读者养成好的编程习惯,不管采用什么脚本,最好都加上相应的开头解释器语言标识,遵守Shell编程规范。

如果在脚本开头的第一行不指定解释器,那么就要用对应的解释器来执行脚本,这样才能确保脚本正确执行。例如:

  • 如果是Shell脚本,就用bash test.sh执行test.sh。
  • 如果是Python脚本,就用python test.py执行test.py。
  • 如果是expect脚本,就用expect test.exp执行test.exp。

3.脚本注释

在Shell脚本中,跟在#后面的内容表示注释,用来对脚本进行注释说明,注释部分不会被当作程序来执行,仅仅是给开发者和使用者看的,系统解释器是看不到的,更不会执行。注释可自成一行,也可以跟在脚本命令的后面与命令在同一行。开发脚本时,如果没有注释,那么团队里的其他人就会很难理解脚本对应内容的用途,而且若时间长了,自己也会忘记。因此,我们要尽量养成为所开发的Shell脚本书写关键注释的习惯,书写注释不光是为了方便别人,更是为了方便自己,避免影响团队的协作效率,

以及给后来接手的人带来维护困难。特别提示一下,注释尽量不要用中文,在脚本中最好也不要有中文。

6.2、Shell脚本的执行

当Shell脚本运行时,它会先查找系统环境变量ENV,该变量指定了环境文件(加载顺序通常是/etc/profile、~/.bash_profile、~/.bashrc、/etc/bashrc等)​,在加载了上述环境变量文件后,Shell就开始执行Shell脚本中的内容​。

Shell脚本是从上至下、从左至右依次执行每一行的命令及语句的,即执行完了一个命令后再执行下一个,如果在Shell脚本中遇到子脚本(即脚本嵌套)时,就会先执行子脚本的内容,完成后再返回父脚本继续执行父脚本内后续的命令及语句。

通常情况下,在执行Shell脚本时,会向系统内核请求启动一个新的进程,以便在该进程中执行脚本的命令及子Shell脚本,基本流程如下图所示。

特殊技巧:设置Linux的crond任务时,最好能在定时任务脚本中重新定义系统环境变量,否则,一些系统环境变量将不会被加载,这个问题需要注意!

Shell脚本的执行通常可以采用以下几种方式。

  • 1)bash script-name或sh script-name:这是当脚本文件本身没有可执行权限(即文件权限属性x位为-号)时常使用的方法,或者脚本文件开头没有指定解释器时需要使用的方法。这也是老男孩推荐使用的方法。
  • 2)path/script-name或./script-name:指在当前路径下执行脚本(脚本需要有执行权限)​,需要将脚本文件的权限先改为可执行(即文件权限属性加x位)​,具体方法为chmod +x script-name。然后通过脚本绝对路径或相对路径就可以直接执行脚本了。
    在企业生产环境中,不少运维人员在写完Shell脚本之后,由于忘记为该脚本设置执行权限,然后就直接应用了,结果导致脚本没有按照自己的意愿手动或定时执行,对于这一点,避免出现该问题的方法就是用第1种方法替代第2种。
  • 3)source script-name或.script-name:这种方法通常是使用source或“.”​(点号)读入或加载指定的Shell脚本文件(如san.sh)​,然后,依次执行指定的Shell脚本文件san.sh中的所有语句。这些语句将在当前父Shell脚本father.sh进程中运行(其他几种模式都会启动新的进程执行子脚本)​。因此,使用source或“.”可以将san.sh自身脚本中的变量值或函数等的返回值传递到当前父Shell脚本father.sh中使用。这是它和其他几种方法最大的区别,也是值得读者特别注意的地方。

source或“.”命令的功能是:在当前Shell中执行source或“.”加载并执行的相关脚本文件中的命令及语句,而不是产生一个子Shell来执行文件中的命令。注意“.”和后面的脚本名之间要有空格。

如果读者学过PHP开发就会明白,source或“.”相当于include的功能。HTTP服务软件Apache、Nginx等配置文件里都支持这样的用法。

  • 4)sh<script-name或cat scripts-name|sh:同样适用于bash,不过这种用法不是很常见,但有时也可以有出奇制胜的效果,例如:不用循环语句来实现精简开机自启动服务的案例,就是通过将所有字符串拼接为命令的形式,然后经由管道交给bash操作的案例。

范例:创建模拟脚本test.sh,并输入如下内容。

[oldboy@oldboy ~]$cat>test.sh#<==编辑test.sh脚本文件。echo'I am oldboy'

输入“echo ‘I am oldboy’”内容后按回车键,然后再按Ctrl+d组合键结束编辑。此操作为特殊编辑方法,这里是作为cat用法的扩展知识(通过使用来记忆是个好习惯)​。

现在使用第1种方法实践,命令如下:

[oldboy@oldboy ~]$cattest.shecho'I am oldboy'[oldboy@oldboy ~]$shtest.sh#<==使用第1种方式的sh命令执行test.sh脚本文件。I am oldboy[oldboy@oldboy ~]$bashtest.sh#<==使用第1种方式的bash命令执行test.sh脚本文件。I am oldboy

这里使用第1种方法的bash和sh,均可以执行脚本并得到预期的结果。

使用第2种方法实践,命令如下:

[oldboy@oldboy ~]$.test.sh#<==请注意开头的“.”后面有空格。I am oldboy[oldboy@oldboy ~]$sourcetest.sh I am oldboy

提示:​“.”或source命令的功能相同,都是读入脚本并执行脚本。

给test.sh添加可执行权限,命令如下:

[oldboy@oldboy ~]$chmodu+x test.sh[oldboy@oldboy ~]$ ./test.sh I am oldboy

可以看到,给test.sh加完可执行权限后就能执行了。前面也提到了,这种方法在使用前每次都需要给定执行权限,

但容易被忘记,且多了一些步骤,增加了复杂性。

使用第3种方法实践时,会将source或“.”执行的脚本中的变量值传递到当前的Shell中,如下:

[oldboy@oldboy ~]$echo'userdir=`pwd`'>testsource.sh#<==第一行的内容通常用echo处理更方便[oldboy@oldboy ~]$cattestsource.shuserdir=`pwd`#<==定义了一个命令变量,内容是打印当前路径。注意,打印命令用反引号[oldboy@oldboy ~]$shtestsource.sh#<==采用sh命令执行脚本[oldboy@oldboy ~]$echo$userdir#<==此处为空,并没有出现当前路径/home/oldboy的输出,这是为什么

根据上面的例子可以发现,通过sh或bash命令执行过的脚本,若在脚本结束之后,在当前Shell窗口中查看userdir变量的值,会发现值是空的。现在以同样的步骤改用source或“.”执行,然后再看看userdir变量的值:

[oldboy@oldboy ~]$sourcetestsource.sh#<==采用source执行同一脚本[oldboy@oldboy ~]$echo$userdir/home/oldboy#<==此处输出了当前路径/home/oldboy,这又是为什么呢

来了解一下系统NFS服务的脚本是如何使用“.”的:

# Source function library../etc/init.d/functions#<==通过"."加载系统函数库functions

说明:操作系统及服务自带的脚本是我们学习的标杆和参考(虽然有时感觉这些脚本也不是十分规范)​。

结论:通过source或“.”加载执行过的脚本,由于是在当前Shell中执行脚本,因此在脚本结束之后,脚本中的变量(包括函数)值在当前Shell中依然存在,而sh和bash执行脚本都会启动新的子Shell执行,执行完后退回到父Shell。因此,变量(包括函数)值等无法保留。在进行Shell脚本开发时,如果脚本中有引用或执行其他脚本的内容或配置文件的需求时,最好用“.”或source先加载该脚本或配置文件,处理完之后,再将它们加载到脚本的下面,就可以调用source加载的脚本及配置文件中的变量及函数等内容了。

以下采用第4种方法来实践:

[root@oldboy ~]# ls -l oldboy.sh-rw-r--r--.1root root28Nov1815:52 oldboy.sh[root@oldboy ~]# cat oldboy.shecho"I am oldboy teacher."[root@oldboy ~]# sh<oldboy.sh #<==尽量不要使用这种方法。I am oldboy teacher.[root@oldboy ~]# cat oldboy.sh|bash #<==这种方法在命令行拼接字符串命令后,需要执行时就会用到 I am oldboy teacher.

提示:代码中提到的两种执行方法相当于sh scripts-name,效率很高,但是初学者用得少。

范例:已知如下命令及返回结果,请问echo $user的返回的结果为(​)​。

[oldboy@test ~]$cattest.shuser=`whoami`[oldboy@test ~]$shtest.sh[oldboy@test ~]$echo$user

参考的选择项如下:

  • a)当前用户
  • b)oldboy
  • c)空(无内容输出)

这是某互联网公司Linux运维职位的笔试题。在这里c)是正确答案,原因前面已经讲过了,即使用sh执行脚本会导致当前Shell无法获得变量值。

通过上述面试题可得出如下的结论:

  • 儿子Shell脚本会直接继承父亲Shell脚本的变量、函数(就好像是儿子随父亲姓,基因也会继承父亲的)等,反之则不可以。
  • 如果希望反过来继承(就好像是让父亲随儿子姓,让父亲的基因也继承儿子的)​,就要用source或“.”在父亲Shell脚本中事先加载儿子Shell脚本。

6.3、Shell脚本开发的基本规范及习惯

Shell脚本的开发规范及习惯非常重要,虽然这些规范不是必须要遵守的,但有了好的规范和习惯,可以大大提升开发效率,并能在后期降低对脚本的维护成本。当多人协作开发时,大家有一个互相遵守的规范就显得更重要了。即使只是一个人开发,最好也采取一套固定的规范,这样脚本将会更易读、更易于后期维护,最重要的是要让自己养成一个一出手就很专业和规范的习惯。下面来看看有哪些规范,这些规范在第14章也会提及,以便于大家进一步巩固。

  • 1)Shell脚本的第一行是指定脚本解释器,通常为:
#! /bin/bash#! /bin/sh
  • 2)Shell脚本的开头会加版本、版权等信息:
    # Date: 16:29 2012-3-30# Author: Created by oldboy# Blog:http://oldboy.blog.51cto.com# Description:This scripts function is.....# Version:1.1
    可修改“~/.vimrc”配置文件配置vim编辑文件时自动加上以上信息的功能。
  • 3)在Shell脚本中尽量不用中文(不限于注释)​。
    尽量用英文注释,防止本机或切换系统环境后中文乱码的困扰。如果非要加中文,请根据自身的客户端对系统进行字符集调整,如:export LANG=“zh_CN.UTF-8”,并在脚本中,重新定义字符集设置,和系统保持一致。
  • 4)Shell脚本的命名应以.sh为扩展名。
    例如:script-name.sh
  • 5)Shell脚本应存放在固定的路径下。
    例如:/server/scripts

以下则是Shell脚本代码书写的良好习惯。

  • 1)成对的符号应尽量一次性写出来,然后退格在符号里增加内容,以防止遗漏。这些成对的符号包括:
{}[]''、``、""
  • 2)中括号(​[​]​)两端至少要有1个空格,因此,键入中括号时即可留出空格[ ]​,然后再退格键入中间的内容,并确保两端都至少有一个空格,即先键入一对中括号,然后退1格,输入两个空格,再退1格,双中括号(​[​[​]​]​)的写法也是如此。
  • 3)对于流程控制语句,应一次性将格式写完,再添加内容。
    比如,一次性完成if语句的格式,应为:
    if条件内容then内容fi
    一次性完成for循环语句的格式,应为:
    fordo内容done
  • 4)通过缩进让代码更易读,比如:
    if条件内容then内容fi
  • 5)对于常规变量的字符串定义变量值应加双引号,并且等号前后不能有空格,需要强引用的(指所见即所得的字符引用)​,则用单引号(’ ')​,如果是命令的引用,则用反引号()​。例如:
    OLDBOY_FILE="test.txt"
  • 6)脚本中的单引号、双引号及反引号必须为英文状态下的符号,其实所有的Linux字符及符号都应该是英文状态下的符号,这点需要特别注意。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 6:24:42

基于Django的B站数据分析系统开发实践

1. 项目背景与核心价值 去年帮学弟调试毕业设计时,我意外发现B站开放平台的API数据比想象中丰富得多。这个基于Django的B站数据分析系统,最初只是为了应付毕设,后来竟成了我们实验室的常备工具。它不仅能自动抓取UP主视频数据、弹幕内容和用户…

作者头像 李华
网站建设 2026/9/11 6:24:00

ESP32+MicroPython RGB灯珠实战入门指南

1. 为什么RGB灯珠是ESP32新手最该动手的第一个“视觉项目” 刚拿到一块ESP32开发板,烧完固件、点亮LED、连上Wi-Fi——这些动作做完,你大概率会陷入一种微妙的空虚感:硬件在手,却还没真正“看见”它在动。不是代码没跑通&#xff…

作者头像 李华
网站建设 2026/9/11 6:23:57

基于51单片机的智能花盆设计:从土壤湿度检测到自动浇水系统

简介:基于单片机的智能花盆设计源码包,定位为毕业设计/嵌入式课程设计辅助资料,适合单片机学习者、电类相关专业学生完成智能浇灌、环境监测等课题。包内共72个文件,约200.7MB,涵盖C语言与头文件源码、Keil工程文件&am…

作者头像 李华
网站建设 2026/9/11 6:23:00

STM32F103通过CH376读取U盘:SPI驱动与FATFS移植实战

简介:基于STM32F103的USB读取U盘实战例程包,面向嵌入式单片机开发人群,适合首次接触USB主机应用或想通过标准库快速搭建外设驱动的学习者。整套例程均经实战验证,代码采用KEIL标准库编写,在演示U盘读写的同时&#xff…

作者头像 李华
网站建设 2026/9/11 6:22:19

2026毕业论文AI工具实测:8款神器从选题到答辩全程攻略

又是一年毕业季,我后台私信里关于“毕业论文怎么写”“查重怎么降”的提问肉眼可见地多了起来。今年和往年最大的不同是,问题里多了一类:“AI工具到底能不能用”“用哪款AI写论文靠谱”“降AI率是怎么回事”。作为从ChatGPT刚火就开始折腾各种…

作者头像 李华