菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
56
0

Shell 和 Shell 脚本

原创
05/13 14:22
阅读数 958

Shell

Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。
Shell 既是一种命令语言,又是一种程序设计语言。
Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。
Ken Thompson 的 sh 是第一种 Unix Shell,Windows Explorer (文件资源管理器)是一个典型的图形界面 Shell。

Linux 的 Shell 种类众多,常见的有:

  • Bourne Shell(/usr/bin/sh或/bin/sh)
  • Bourne Again Shell(/bin/bash)
  • C Shell(/usr/bin/csh)
  • K Shell(/usr/bin/ksh)
  • Shell for Root(/sbin/sh)
  • ……

Bash,也就是 Bourne Again Shell,由于易用和免费,在日常工作中被广泛使用。同时,Bash 也是大多数Linux 系统默认的 Shell。

Shell 脚本

一般书写

新建一个文件 test.sh,扩展名为 sh(sh代表shell),扩展名并不影响脚本执行。输入一些代码,一般是这样:

#!/bin/bash

echo "Hello World !"

1、#! 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell。
2、一般情况下,人们并不区分 Bourne Shell 和 Bourne Again Shell,所以,像 #!/bin/sh ,它同样也可以改为 #!/bin/bash

运行的两种方法

1、作为可执行程序

将上面的代码保存为 test.sh,并 cd 到相应目录:

chmod +x ./test.sh #使脚本具有执行权限

./test.sh #执行脚本

注意,一定要写成./test.sh,而不是test.sh,运行其它二进制的程序也一样
直接写 test.sh,linux 系统会去 PATH 里寻找有没有 test.sh ,而只有 /bin, /sbin, /usr/bin,/usr/sbin 等在 PATH 里,你的当前目录通常不在 PATH 里,所以写成 test.sh 是会找不到命令的,要用 ./test.sh 告诉系统说,就在当前目录找。

2、作为解释器参数

直接运行解释器,其参数就是 shell 脚本的文件名,如:

/bin/sh test.sh

/bin/php test.php

这种方式运行的脚本,不需要在第一行指定解释器信息,写了也没用

脚本文件参数

在文件内使用 $ 获取。 如下:test.sh

#!/bin/sh

echo "shell脚本本身的名字: $0"

echo "传给shell的第一个参数: $1"

echo "传给shell的第二个参数: $2"

运行:

bash test.sh 1 2

文件包含(文件引入)

Shell 也可以包含(引入)外部脚本。这样可以很方便的封装一些公用的代码作为一个独立的文件。

Shell 文件包含的语法格式如下( .source ):

. filename 
source filename

实例

test1.sh

url="https://segmentfault.com"

test2.sh

. ./test1.sh

# source ./test1.sh

echo "思否:$url"

接下来,我们为 test2.sh 添加可执行权限并执行:

chmod +x test2.sh

./test2.sh 

输出

思否:https://segmentfault.com

注:被包含的文件 test1.sh 不需要可执行权限

变量类型

运行shell时,会同时存在三种变量:局部变量、环境变量、shell变量

局部变量: 在脚本或命令中定义,仅在当前shell实例中有效

环境变量: 所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。

shell变量: shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行

输入/输出重定向

大多数 UNIX 系统命令从你的终端接受输入并将所产生的输出发送回​​到您的终端。

一个命令通常从一个叫标准输入的地方读取输入,默认情况下,这恰好是你的终端。同样,一个命令通常将其输出写入到标准输出,默认情况下,这也是你的终端。

重定向命令列表如下:

命令 说明
command > file 将输出重定向到 file
command < file 将输入重定向到 file
command >> file 将输出以追加的方式重定向到 file
n > file 将文件描述符为 n 的文件重定向到 file
n >> file 将文件描述符为 n 的文件以追加的方式重定向到 file
n >& m 将输出文件 m 和 n 合并
n <& m 将输入文件 m 和 n 合并
<< tag 将开始标记 tag 和结束标记 tag 之间的内容作为输入

需要注意的是文件描述符 0 通常是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。

输出重定向

重定向一般通过在命令间插入特定的符号来实现。特别的,这些符号的语法如下所示:

command > file

1.执行 command 然后将输出的内容存入 file。
2.file内的内容将被替代。如果要将新内容 添加 在文件末尾,请使用>>操作符。

实例 :执行 who 命令,将命令的完整的输出重定向在用户文件中(users):

who > users

输入重定向

和输出重定向一样,Unix 命令也可以从文件获取输入,语法为:

command < file

这样,本来需要从键盘获取输入的命令会转移到文件读取内容。

实例 :统计 users 文件的行数:

一般方法:

wc -l users

# 2 users

重定向方法:将输入重定向到 users 文件:

wc -l < users

# 2

注意,上面两个例子的结果不同:第一个,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容。

同时替换输入和输出

command < infile > outfile

执行command,从文件infile读取内容,然后将输出写入到outfile中。

重定向深入讲解

一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:

  • 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
  • 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
  • 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。

默认情况下,command > file 将 stdout 重定向到 file,command < file 将stdin 重定向到 file。

如果希望 stderr 重定向到 file,可以这样写:

command 2 > file

如果希望 stderr 追加到 file 文件末尾,可以这样写:

command 2 >> file

2 表示标准错误文件(stderr)。

如果希望将 stdout 和 stderr 合并后重定向到 file,可以这样写:

command > file 2>&1

或者

command >> file 2>&1

Here Document(内容重定向)

Here Document 是 Shell 中的一种特殊的重定向方式,用来将输入重定向到一个交互式 Shell 脚本或程序。

它的基本的形式如下,作用是将两个 delimiter (分隔符,EOF等) 之间的内容(document) 作为输入传递给 command。

command << delimiter
    document
delimiter

注意:
1、结尾的delimiter 一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和 tab 缩进。
2、开始的delimiter前后的空格会被忽略掉。

实例:在命令行中通过 wc -l 命令计算 Here Document 的行数:

$ wc -l << EOF
    hello,
    world!
EOF
2          # 输出结果为 2 行

/dev/null 文件

如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出 重定向/dev/null

command > /dev/null

1、/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;
2、如果尝试从该文件读取内容,那么什么也读不到。
3、但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。

如果希望屏蔽 stdout 和 stderr,可以这样写:

command > /dev/null 2>&1

shell 语法

详见 shell 语法学习菜鸟教程

发表评论

0/200
56 点赞
0 评论
收藏