Linux Shell 脚本编写指南——第二章


本文为Linux Shell Scripting Tutorial (LSST) v2.0学习记录


第二章:开始shell脚本编程

本章节学习目标:

  • 编写你第一个shell 程序

  • 理解创建一个shell脚本的步骤

2.1 Bash shell(全称Bourne again shell)

有关bash的创建历史(来自维基百科):

Bourne shell是一个交互式的shell,由AT&T实验室的史蒂夫在1977年发布,位于大多数Unix系统上的/bin/sh,随着时间的发展,GNU计划的诞生伴随着shell的开发,这个时候1987年布莱恩编写了Bash,也就是Bourne again shell,总的来说,Bash虽然是一个满足POSIX规范的shell,但有很多拓展。

Bash就是shell,或者可以说是Linux系统的命令语言解释器:

  • Bash式GNU计划的产物
  • Linux的默认shell
  • 反向兼容UNIX系统的sh
  • 与Korn shell(ksh)以及C shell(csh)兼容
  • 在多平台类似UNIX/dos/Windows都是可运行多个

BASH的提升特性

  • 命令行编辑
  • 命令行补全
  • 无限大小的命令历史
  • 提示控制
  • 不限大小的array
  • 以2-64为基数的整数运算
  • ……

作者

  • Brian J. Fox authored the GNU Bash shell, in 1987.
  • Fox maintained Bash as the primary maintainer until 1993, at which point Chet Ramey took over.
  • Chet Ramey is the current maintainer of the GNU Bourne Again Shell and GNU Readline.

下载

2.2 shell命令

bash shell有两种类型的命令:

  1. 内置命令
  2. 外部命令(在bin/目录里面的命令)

bash和命令类型

bash接受以下几种类型的命令:

  • 别名(例如ll
  • 关键词(例如if
  • 函数(例如genpassword
  • 内置命令(例如pwd
  • 文件(例如/bin/date)

type命令

找出某个命令(ls)是内置命令还是外部命令:

new@Chevy-PC:~$ type ls
ls is aliased to `ls --color=auto'
# 显示为外部命令

找出某个命令(command)是内置命令还是外部命令:

new@Chevy-PC:~$ type -a history
history is a shell builtin
# 显示为内置命令

bash命令关键词以及内置命令

2.3 Hello, World! 第一个shell脚本

创建一个shell脚本你需要经过以下几个步骤:

  1. 利用一个文本编辑器(例如vi),将你的指令写入一个文本
  2. 保存该文本并退出
  3. 改变该文本的可执行权限
  4. 测试该脚本并放入你的生产环境
  5. 最简单的shell脚本就是一行代码告诉计算机执行一个命令

让我们来熟悉vi的操作并创建第一个shell script

# 打开一个文件
vi first_script.sh

# 进入编辑模式
# 按Esc键,然后按I键就进入编辑模式

# 进入命令模式
# 按Esc键就进入命令模式

# 保存文件
# 按Esc键然后输入:w
# 或者按Esc键然后输入:w first_script.sh

# 保存并退出文件
# 按Esc键然后输入:wq
# 或者按Esc键然后输入:x

# 跳到某一行
# 按Esc键然后输入:x, x代表第几行

# 搜索一个字符
# 按Esc键然后输入/str, str代表该字符

# 退出vi(不保存)
# 按Esc键然后输入:q

# 让我们来编辑第一个脚本,输入以下字符并保存退出
#!/bin/bash
echo "Hello, World!" 
echo "Knowledge is power."

# 将该文件改为可以执行文件并执行
new@Chevy-PC:~$ chmod 777 first_script.sh
new@Chevy-PC:~$ ./first_script.sh
Hello, World!
Knowledge is power.

Shebang

在脚本的第一行,我们需要告诉系统用哪种程序来运行这个脚本,写法为#!/path_to_binaries,我们一般称其为Shebang或者bang行[1]

在bash脚本里面第一行我们一般写成#!/bin/bash,有些程序使用perl来运行的话,就写成#!/bin/perl

一个#!/bin.sh的脚本示例:

etc/init.d/policykit
#! /bin/sh
### BEGIN INIT INFO
# Provides:          policykit
# Required-Start:    $local_fs
# Required-Stop:     $local_fs
# Default-Start:     2 3 4 5
# Default-Stop:
# Short-Description: Create PolicyKit runtime directories
# Description:       Create directories which PolicyKit needs at runtime,
#                    such as /var/run/PolicyKit
### END INIT INFO

# Author: Martin Pitt <martin.pitt@ubuntu.com>

case "$1" in
  start)
        mkdir -p /var/run/PolicyKit
        chown root:polkituser /var/run/PolicyKit
        chmod 770 /var/run/PolicyKit
    ;;
  stop|restart|force-reload)
    ;;
  *)
    echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
    exit 3
    ;;
esac

:

Shell注释

在脚本里面#号后面的代码会被忽略,这行代码我们成为注释,注释可以帮助我们理解代码并且便于修改:

#!/bin/bash
# A Simple Shell Script To Get Linux Network Information
# Vivek Gite - 30/Aug/2009
echo "Current date : $(date) @ $(hostname)"
echo "Network configuration"
/sbin/ifconfig

多行注释可以使用HERE DOCUMENT 特性来进行注释:

#!/bin/bash
echo "Adding new users to LDAP Server..."
<<COMMENT1
    Master LDAP server : dir1.nixcraft.net.in 
    Add user to master and it will get sync to backup server too
    Profile and active directory hooks are below
COMMENT1
echo "Searching for user..."

设置脚本权限

一个刚编辑完的脚本无法直接执行,你需要使用chmod命令给与其可执行权限或者直接调用对应的命令来执行,下面的操作具有同样的效果:

chmod +x script.sh && ./script.sh
chmod 777 script.sh && ./script.sh

sh script.sh

使用ls -l可以查看一个文件的权限:

new@Chevy-PC:~$ ls -l first.sh
-rwxrwxrwx 1 new new 61 Jul 15 14:24 first.sh

更多chomd的操作可以使用man chmod查看

为什么不直接使用 scriptname 来调用脚本?为什么当工作目录$PWD正好是scriptname 所在目录时也不起作用?因为一些安全原因,当前目录./并不会被默认添加到用户的$PATH路径中。因此需要用户显式使用 ./scriptname 在当前目录下调用脚本。

脚本debug

在运行脚本的时候需要加上-x参数或者-xv参数,又或者是将shebang行改成#!/bin.bash-x

使用内置命令

bash shell提供了debug选项,可以使用set命令打开或者关闭:

  • set -x:当脚本被执行的时候展示命令及参数
  • set -v:当脚本被读入的时候展示输入行
  • set -n:读入命令但不执行(在检查脚本是否有变量名重合的时候)
#!/bin/bash
### Turn on debug mode ###
set -x

# Run shell commands
echo "Hello $(LOGNAME)"
echo "Today is $(date)"
echo "Users currently on the machine, and their processes:"

### Turn OFF debug mode ###
set +x

# Add more commands without debug mode
#!/bin/bash
set -n # only read command but do not execute them
set -o noexec
echo "This is a test"
# no file is created as bash will only read commands but do not executes them 

本章节复习题

练习题1

按照下面代码写一个脚本并运行,观察输出:

# Script to print currently logged in users information, and current date & time.
clear
echo "Hello $USER"
echo -e "Today is \c ";date
echo -e "Number of user login : \c" ; who | wc -l
echo "Calendar"
cal
exit 0

​ 输出结果:

Hello new
Today is Tue Jul 16 15:34:58 CST 2019
Number of user login : 0
Calendar
     July 2019
Su Mo Tu We Th Fr Sa
    1  2  3  4  5  6
 7  8  9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31

练习题2

写一个程序,打印出你最喜欢的电影名称,同时在下一行打印出导演的名称(以下是我自己的答案):

#!/bin/bash
# print moive and director

set -e

my_favorite_moive="gone_with_the_wind"

moive_director="not_known"

echo -e "my_favorite_moive is \c"; 
echo $my_favorite_moive
echo -e "the moive's director is \c"; 
echo $moive_director

exit 0
练习题3

写一个shell脚本,打印你的名字,在用户按<ENTER>键之前保持等待状态:

#!/bin/bash
echo "Vivek Gite"
read -p "Press [Enter] key to continue..." fakeEnterKey
练习题4

列出十个内置命令和外部命令:

# builtin commands
history
break
cd
continue
eval
exit
grep
kill

# external commands
ls
gzip
练习题5

使用cd命令进入/etc/init.d目录下,查看各种系统启动脚本:

new@Chevy-PC:/bin$ cd /etc/init.d/
new@Chevy-PC:/etc/init.d$ ll
total 156
-rwxr-xr-x 1 root root 2269 Apr 22  2017 acpid*
-rwxr-xr-x 1 root root 4335 Mar 23  2018 apparmor*
-rwxr-xr-x 1 root root 2802 Nov 21  2017 apport*
-rwxr-xr-x 1 root root 1071 Aug 22  2015 atd*
-rwxr-xr-x 1 root root 1232 Apr 19  2018 console-setup.sh*
-rwxr-xr-x 1 root root 3049 Nov 16  2017 cron*
-rwxr-xr-x 1 root root  937 Mar 18  2018 cryptdisks*
-rwxr-xr-x 1 root root  978 Mar 18  2018 cryptdisks-early*
-rwxr-xr-x 1 root root 2813 Nov 16  2017 dbus*
-rwxr-xr-x 1 root root 4489 Jun 29  2018 ebtables*
-rwxr-xr-x 1 root root 3809 Feb 15  2018 hwclock.sh*
-rwxr-xr-x 1 root root 2444 Oct 25  2017 irqbalance*
-rwxr-xr-x 1 root root 1503 Feb 22  2018 iscsid*
-rwxr-xr-x 1 root root 1479 Feb 16  2018 keyboard-setup.sh*
-rwxr-xr-x 1 root root 2044 Aug 16  2017 kmod*
-rwxr-xr-x 1 root root  695 Dec  3  2017 lvm2*
-rwxr-xr-x 1 root root  571 Dec  3  2017 lvm2-lvmetad*
-rwxr-xr-x 1 root root  586 Dec  3  2017 lvm2-lvmpolld*
-rwxr-xr-x 1 root root 2378 Jun 17  2018 lxcfs*
-rwxr-xr-x 1 root root 2240 Jun  6  2018 lxd*
-rwxr-xr-x 1 root root 2653 Jun 26  2018 mdadm*
-rwxr-xr-x 1 root root 1249 Jun 26  2018 mdadm-waitidle*
-rwxr-xr-x 1 root root 2503 Feb 22  2018 open-iscsi*
-rwxr-xr-x 1 root root 1846 Mar 22  2018 open-vm-tools*
-rwxr-xr-x 1 root root 1366 Jan 17  2018 plymouth*
-rwxr-xr-x 1 root root  752 Jan 17  2018 plymouth-log*
-rwxr-xr-x 1 root root 1191 Jan 18  2018 procps*
-rwxr-xr-x 1 root root 4355 Dec 13  2017 rsync*
-rwxr-xr-x 1 root root 2864 Jan 15  2018 rsyslog*
-rwxr-xr-x 1 root root 1222 May 22  2017 screen-cleanup*
-rwxr-xr-x 1 root root 3837 Jan 26  2018 ssh*
-rwxr-xr-x 1 root root 5974 Apr 21  2018 udev*
-rwxr-xr-x 1 root root 2083 Aug 16  2017 ufw*
-rwxr-xr-x 1 root root 1391 Jul 18  2018 unattended-upgrades*
-rwxr-xr-x 1 root root 1306 May 16  2018 uuidd*

  1. SBCL - Shebang Scripts

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容