Linux shell编程学习笔记14:编写和运行第一个shell脚本hello world!

* 20231020 写这篇博文断断续续花了好几天,为了说明不同shell在执行同一脚本文件时的差别,我分别在csdn提供线上Linux环境 (使用的shell是zsh)和自己的电脑上(使用的shell是bash)做测试。功夫不负有心人,在其中一些实例中可以体现出zsh和bash的对脚本文件支持的差别,收获匪浅......

一、第一个shell脚本:hello world!

前面我们陆续介绍了与Linux shell编程有关的数据类型、数据运算、流程控制语句等基础知识,今天我们正式开始写shell脚本了。

我们学习某种编程语言,通常写的第一个程序就是输出hello world!,今天我们就编写和运行第一个shell脚本写的hello world!,假定脚本文件名为hello.sh

二、 录入脚本文件hello.sh

脚本文件本质上是一个文本文件,我们有很多种方法可以来创建它,比如可以用vi或vim之类的文本编辑器,这类编辑器,对于用过DOS下编辑器的用户来说,上手起来比较容易,而对于只有windows使用经历的用户而言,刚开始用起来未必顺手。

所以我们这里直接在命令行来创建。

(一)使用 echo 命令 和 输出重定向 来创建脚本文件hello.sh

具体命令如下:

1.在zsh中测试

csdn @ edu in ~ [20:28:14]

$ ++echo "#! /bin/bash" > hello.sh++

csdn @ edu in ~ [20:31:32]

$ ++echo 'echo "My first shell script file:Hello world!"' >> hello.sh++

csdn @ edu in ~ [20:32:28]

$ ++echo "# My first shell script file ends." >> hello.sh++

csdn @ edu in ~ [20:32:53]

$

2.在bash中测试

user @ host : ~ $ ++echo '#! /bin/bash' > hello.sh++

user @ host : ~ $ ++echo 'echo "My first shell script file:Hello world"' >> hello.sh++

user @ host : ~ $ ++echo '# My first shell script file ends.' >> hello.sh++

3.需要注意的地方

使用这种方法创建脚本文件时,有一点不方便的地方是需要注意双引号和单引号的使用,有时需要使用转义符。

(二)使用cp命令 和 /dev/stdin 来创建脚本文件hello.sh

我们也可以使用命令 :

bash 复制代码
cp /dev/stdin hello.sh

来录入hello.sh的内容。/dev/stdin 是Linux 系统中一个特殊的符号链接文件,指向当前进程的标准输入文件描述符,代表标准输入,比如键盘。

在输完所有shell脚本内容后,我们按Ctrl+Z键来结束。

但是用这种方法创建的脚本文件在执行时通常会遇到问题:

1.在zsh中测试

csdn @ edu in ~ [23:11:12]

$ ++cp /dev/stdin hello.sh++
++#! /bin/bash++
++echo "My first shell script file:Hello world!"++
++# My first shell script file ends.++
++^Z++

1\] + 148 suspended cp /dev/stdin hello.sh # csdn @ edu in \~ \[23:12:26\] C:20

csdn @ edu in ~ [12:33:07] C:127

$ ++./hello.sh++

zsh: text file busy: ./hello.sh

2.在bash中测试

user @ host : ~ $ ++cp /dev/stdin hello.sh++

#! /bin/bash

echo "My first shell script file:Hello world!"

My first shell script file ends.

++^Z++

1\]+ 已停止 cp /dev/stdin hello.sh

user @ host : ~ $ ++./hello.sh++

bash: ./hello.sh: /bin/bash: 解释器错误: 文本文件忙

这是因为cp命令执行后,对应的进程并没结束,hello.sh仍处于被cp进程打开操作的状态。

解决的方法我们以后会介绍。

二、查看脚本文件hello.sh的内容

要查看脚本文件hello.sh的内容,方法同样有很多种。

(一)使用cat命令查看

我们可以使用命令

bash 复制代码
cat hello.sh

来查看刚才输入的hello.sh 的内容:

1.在zsh中测试

csdn @ edu in ~ [23:12:26] C:20

$ ++cat hello.sh++

#! /bin/bash

echo "My first shell script file:Hello world!"

My first shell script file ends.

csdn @ edu in ~ [23:12:36]

2.在bash中测试

user @ host : ~ $ ++cat hello.sh++

#! /bin/bash

echo "My first shell script file:Hello world!"

My first shell script file ends.

user @ host : ~ $

(二)使用cp命令 和 /dev/stdout来查看

/dev/stdout 是Linux 系统中一个特殊的符号链接文件,指向当前进程的标准输出文件描述符,代表标准输出,比如显示器屏幕。

1.在zsh中测试

csdn @ edu in ~ [21:11:30]

$ ++cp hello.sh /dev/stdout++

#! /bin/bash

echo "My first shell script file:Hello world!"

My first shell script file ends.

csdn @ edu in ~ [21:11:46]

$

2.在bash中测试

user @ host : ~ $ ++cp hello.sh /dev/stdout++

#! /bin/bash

echo "My first shell script file:Hello world"

My first shell script file ends.

user @ host : ~ $

三、shell脚本解说

在上面的hello.sh中,共有三行:

bash 复制代码
#! /bin/bash
echo "My first shell script file:Hello world!"
# My first shell script file ends.

我们逐行说明。

(一)第一行:shebang或hashbang语句:指定脚本解释器

第一行是

bash 复制代码
#! /bin/bash

1.shebang或hashbang语句的作用

以#! 开头,通常称为shebang或hashbang,用于指定默认情况下运行指定脚本的解释器路径,在上面的实例中我们指定的解释器是 /bin/bash。

这一行并不是必须的。如果一个脚本没有添加 shebang 行来指定解释器路径,则默认情况下系统会使用默认的 shell 来执行脚本。默认shell可以使用echo 0 或 echo SHELL 查看。

由于目前可以在Linux系统上运行的shell有许多种:sh、bash、cshell、tcsh、zsh......尽管这些shell大多具有共同的语法,但它们确实有不同的语法或不同选项的处理方式,因此,同一个shell脚本文件在不同的shell中运行时可能会产生不同的结果。为了确保脚本文件获得预期的效果,我们建议为脚本指定解释器。

常见的解释器类型有:

#!/bin/sh

#!/bin/bash

#!/usr/bin/perl

#!/usr/bin/tcl

#!/bin/sed -f

#!/usr/awk -f

其中最常用、也是最常见的是 #!/bin/bash。

2.shebang或hashbang语句名称的由来

在Unix行话中,用sharp或hash(有时是mesh)来称呼字符#,用bang称呼字符!,因而shebang或 hashbang合起来就代表了这两个字符。到linux中也传承了这一传统。

(二)第二行:命令或语句

bash 复制代码
echo "My first shell script file:Hello world!"

这一行是echo命令,用来显示字符串。在shell脚本文件中,除了第一行可能是shebang或hashbang语句外,接下来的语句可以是变是赋值命令,或者ls等命令,或者是if等流程控制语句。

(三)第三行:以#开头的注释

bash 复制代码
# My first shell script file ends.

在shell脚本文件中,除了第一行以#! 开头的shebang或hashbang语句外,其他行中以#开始的内容均被视为注释。

关于注释,有两点说明:

1.注释的两种写法

有两种写法。

一种写法是像hello.sh的第3行这样将注释写成一个独立的行。

另一种写法是将注释可以直接写在要注释的命令之后。比如:

bash 复制代码
echo "My first shell script file:Hello world!" # dispaly the string

其中 # dispaly the string 就是我们添加的注释。

2.一个脚本文件中可以有包含多个注释。

我们可以根据需要,在脚本文件中添加许多个注释,可以写在命令之后,也可以单独成行。

三、执行脚本文件hello.sh

通常来说,执行脚本文件有很多种方法 。我们先看看其中三种最常见的方法:

(一)shell解释器名称 脚本文件名

其实就是将脚本文件名作为命令参数传递给 shell解释器执行。

1.使用bash来执行

由于我们在hello.sh的shebang或hashbang语句中指定使用bash作为解释器,所以我们可以用命令

bash 复制代码
bash hello.sh

来执行hello.sh

csdn @ edu in ~ [23:12:36]

$++bash hello.sh++

My first shell script file:Hello world!

csdn @ edu in ~ [23:17:46]

2.使用sh来执行

我们也可以用命令

bash 复制代码
sh hello.sh

来执行:

csdn @ edu in ~ [23:17:46]

$ ++sh hello.sh++

My first shell script file:Hello world!

csdn @ edu in ~ [23:19:27]

(二)脚本文件说明符

脚本文件说明符的格式是:

路径/脚本文件名

其中路径又分为绝对路径和相对路径。所以这种方式又可以细分为两种格式。

1.相对路径/脚本文件名

由于我们是在当前目录下创建了hello.sh,所以hello.sh的相对路径就是./,我们使用命令

./hello.sh

来运行看看。

(1)在zsh中测试

csdn @ edu in ~ [12:27:14] C:127

$ ++./hello.sh++

zsh: permission denied: ./hello.sh

看来是权限问题,我们使用ls -l命令查看 文件hello.sh的详细信息:

csdn @ edu in ~ [12:29:22] C:126

$ ++ls -l hello.sh++

-rw------- 1 csdn csdn 95 10月 20 12:23 hello.sh

我们只有读(r)写(w)权限,还没有执行(x)权限,我们使用命令

chmod a+x hello.sh

增加执行权限。

csdn @ edu in ~ [12:31:53] C:1

$ ++chmod a+x hello.sh++

csdn @ edu in ~ [12:32:53]

$ ++ls -l hello.sh++

-rwx--x--x 1 csdn csdn 95 10月 20 12:23 hello.sh

这下有执行权限(x)了。再试试看:

csdn @ edu in ~ [20:36:35]

$ ++./hello.sh++

My first shell script file:Hello world!

(2)在bash中测试

user @ host : ~ $ ++./hello.sh++

bash: ./hello.sh: 权限不够

user @ host : ~ $ ++ls -l hello.sh++

-rw--w---- 1 gxxc gxxc 94 10月 20 18:36 hello.sh

user @ host : ~ $ ++chmod +x hello.sh++

user @ host : ~ $ ++ls -l hello.sh++

-rwx-wx--x 1 gxxc gxxc 94 10月 20 18:36 hello.sh

user @ host : ~ $ ++./hello.sh++

My first shell script file:Hello world

user @ host : ~ $

2.绝对路径/脚本文件名

(1)在zsh中测试

我们先用pwd命令查看当前目录路径:

csdn @ edu in ~ [20:36:40]

$ ++pwd++

/home/csdn

可以看到,当前目录路径是/home/csdn,所以脚本文件的绝对路径文件说明符是/home/csdn/hello.sh。

那么我们可以通过命令:/home/csdn/hello.sh 来执行脚本:

csdn @ edu in ~ [20:38:39]

$ ++/home/csdn/hello.sh++

My first shell script file:Hello world!

(2)在bash中测试

user @ host : ~ $ ++pwd++

/tmp

user @ host : ~ $ ++/tmp/hello.sh++

My first shell script file:Hello world

user @ host : ~ $

在上面的例子中,当前目录的路径是/tmp,所以脚本文件的绝对路径文件说明符是/tmp/hello.sh。

所以我们可以通过命令:/tmp/hello.sh 来执行脚本。

(3)需要的注意地方

不管使用相对路径还是绝对路径来执行脚本文件,我们都要使用chmod 命令来为脚本文件增加执行(x)权限。

(三)利用source命令来执行。

有没有不用修改脚本文件权限又能执行脚本文件的方法呢?除了上面介绍的第一种方法:将脚本文件名作为命令参数传递给 shell解释器执行 外,我们还可以使用source命令来实现。

source 是 Shell 内置命令的一种,它会忽略脚本文件的权限,读取脚本文件,并依次执行其中的命令语句。

使用source命令执行脚本文件的格式是:

source 脚本文件说明符

也可以简写为:

. 脚本文件说明符

注意:简写命令格式中. 和 脚本文件说明符之间要用空格分隔。

1.在zsh中测试

csdn @ edu in ~ [20:38:50]

$ ++source ./hello.sh++

My first shell script file:Hello world!

csdn @ edu in ~ [20:47:56]

$ ++. ./hello.sh++

My first shell script file:Hello world!

csdn @ edu in ~ [20:48:25]

$ ++source hello.sh++

My first shell script file:Hello world!

csdn @ edu in ~ [20:49:07]

$ ++. hello.sh++

.: no such file or directory: hello.sh

csdn @ edu in ~ [20:49:15] C:127

可见,在zsh中,使用"source 脚本文件说明符"来执行脚本文件时,如果脚本文件在当前目录中,那么文件说明符中的路径可以省略。

使用". 脚本文件说明符" 这种简写格式来执行脚本文件时,脚本文件说明符的路径不能少。

2.在bash中测试

user @ host : ~ $ ++source hello.sh++

My first shell script file:Hello world

user @ host : ~ $ ++source ./hello.sh++

My first shell script file:Hello world

user @ host : ~ $ ++. hello.sh++

My first shell script file:Hello world

user @ host : ~ $ ++. ./hello.sh++

My first shell script file:Hello world

可见,在bash中,不管使用"source 脚本文件说明符"还是". 脚本文件说明符" 这种简写格式来执行脚本文件时,如果脚本文件在当前目前下,那么文件说明符中的路径都可以省略。

对比可见bash用起来更方便一些,bash能成为最流行的shell,这是其中的原因之一。

相关推荐
无敌小茶19 分钟前
Linux学习笔记之环境变量
linux·笔记
Harbor Lau32 分钟前
Linux常用中间件命令大全
linux·运维·中间件
꧁坚持很酷꧂1 小时前
Linux Ubuntu18.04下安装Qt Craeator 5.12.9(图文详解)
linux·运维·qt
凉、介2 小时前
PCI 总线学习笔记(五)
android·linux·笔记·学习·pcie·pci
电鱼智能的电小鱼2 小时前
EFISH-SBC-RK3588无人机地面基准站项目
linux·网络·嵌入式硬件·机器人·无人机·边缘计算
电鱼智能的电小鱼2 小时前
基于 EFISH-SBC-RK3588 的无人机环境感知与数据采集方案
linux·网络·嵌入式硬件·数码相机·无人机·边缘计算
小诸葛的博客3 小时前
详解Linux中的定时任务管理工具crond
linux·运维·chrome
一默19913 小时前
CentOS 7.9升级OpenSSH到9.9p2
linux·运维·centos
keep intensify3 小时前
Linux常用指令
linux·服务器·php
带电的小王4 小时前
sherpa-ncnn:Linux(x86/ARM32/ARM64)构建sherpa-ncnn --语音转文本大模型
linux·语音识别·实时音视频·sherpa-ncnn