Linux网络、文本处理工具与 Shell 脚本

简介: 7月更文挑战第8天

初学者都会对以下这些问题感到迷惑:
• 如何把命令的输出放到文件里?如何把命令的输出作为其他命令的输入?
• 在命令行黑乎乎的窗口,我要怎么下载文件?
• 在命令行下,下载任务可以放在后台吗?如果我在命令行下结束下载任务,会不会使已下载部分全部白费?
• 在命令行下怎么查找与替换文件中的字符串?
• Bash 语法和 C 语言类似吗?和 Powershell 类似吗?
• Bash script 出 bug 的时候我该如何调试呢
I/O 重定向与管道
重定向
一般情况下命令从标准输入(stdin)读取输入,并输出到标准输出(stdout),默认情况下两者都是你的终端。使用重定向可以让命令从文件读取输入/输出到文件。下面是以 ​​echo​​ 为例的重定向输出:
$ echo "Hello Linux!" > output_file # 将输出写入到文件(覆盖原有内容)
$ cat output_file
Hello Linux!
$ echo "rewrite it" > output_file
$ cat output_file # 可以看到原来的 Hello Linux! 被覆盖了。
rewrite it
$ echo "append it" >> output_file # 将输出追加到文件(不会覆盖原有内容)
$ cat output_file
rewrite it
append it无论是 ​​>​​​ 还是 ​​>>​​,当输出文件不存在时都会创建该文件。
重定向输入使用符号 ​​<​​:
command < inputfile
command < inputfile > outputfile除了 stdin 和 stdout 还有标准错误(stderr),他们的编号分别是 0、1、2。stderr 可以用 ​​2>​​ 重定向(注意数字 2 和 > 之间没有空格)。
使用 ​​2>&1​​ 可以将 stderr 合并到 stdout。
管道
管道(pipe),操作符 ​​|​​,作用为将符号左边的命令的 stdout 接到之后的命令的 stdin。管道不会处理 stderr。
管道是类 UNIX 操作系统中非常强大的工具。通过管道,我们可以将实现各类小功能的程序拼接起来干大事。
示例如下:
$ ls / | grep bin # 筛选 ls / 输出中所有包含 bin 字符串的行
bin
sbin网络下载
为何使用 wget 和 cURL
在 Windows 下,很多人下载文件时会使用「迅雷」、「QQ 旋风」(停止运营)、「IDM」之类的软件来实现下载。那么在 Linux 环境下呢?在终端下,没有可视化软件提供点击下载。即使有桌面环境,有 Firefox 可以很方便地下载文件,硬件资源也会被很多不必要的服务浪费。通过以下内容讲述的 wget (​​wget​​​) 和 cURL (​​curl​​) 工具,我们可以 Linux 上进行轻量的下载活动。
Wget
​​wget​​ 是强力方便的下载工具,可以通过 HTTP 和 FTP 协议从因特网中检索并获取文件。
Wget 的特点
• 支持以非交互方式工作,能够在用户注销后在后台进行工作。
• 在不稳定的连接中依旧可以正常工作,支持断点续传功能。
• 支持 HTML 页面以及 FTP 站点的递归检索,您可以使用它来获取网站的镜像,或者像爬虫一样遍历网络。
• 在文件获取时可以增加时间标记,因此可以自动识别远程文件自上次检索后是否发生更改,并自动检索新版本。
• 支持代理服务器,以减轻网络负载,加快检索速度。
使用 Wget
使用 ​​man wget​​​ 得到的结果为 ​​wget [option]... [URL]...​​​,其中的更多参数可以通过查看帮助 ​​wget -h​​ 来获取。
常用的选项
选项
含义
​​-i​​​, ​​--input-file=文件​​
下载本地或外部文件中的 URL
​​-O​​​, ​​--output-document=文件​​
将输出写入文件
​​-b​​​, ​​--background​​
在后台运行 wget
​​-d​​​, ​​--debug​​
调试模式,打印出 wget 运行时的调试信息
范例
cURL
cURL (​​curl​​) 是一个利用 URL 语法在命令行下工作的文件传输工具,其中 c 意为 client。虽然 cURL 和 Wget 基础功能有诸多重叠,如下载。但 cURL 由于可自定义各种请求参数,所以在模拟 web 请求方面更擅长;wget 由于支持 FTP 协议和递归遍历,所以在下载文件方面更擅长。
使用 cURL
同 ​​wget​​​ 部分,我们可以查看帮助 ​​curl -h​​ 了解其用法。
常用的选项
选项
含义
​​-o​​
把远程下载的数据保存到文件中,需要指定文件名
​​-O​​
把远程下载的数据保存到文件中,直接使用 URL 中默认的文件名
​​-I​​
只展示响应头内容
范例
其他
除了 Wget、cURL,还有 mwget(多线程版本 wget)、Axel、Aria2(支持 BT 协议、支持 JSON-RPC 和 XML-RPC 接口远程调用)之类下载工具,其中 Aria2 在 Windows 下使用也很广泛。
文本处理
在进行文本处理时,我们有一些常见的需求:
• 获取文本的行数、字数
• 比较两段文本的不同之处
• 查看文本的开头几行和最后几行
• 在文本中查找字符串
• 在文本中替换字符串
下面介绍如何在 shell 中做到这些事情。
文本统计:wc
​​wc​​ 是文本统计的常用工具,它可以输出文本的行数、单词数与字符(字节)数。
$ wc file
427 2768 20131 file统计中文文本时的问题
​​wc​​ 在统计中文文本时,会出现一些问题,比如:
$ echo '中文测试' | wc
1 1 13这里显示文本只有 1 个单词,但是有 13 个字符,这显然是不对的。
对于字符数统计结果,可以使用 ​​wc -m​​​ 命令要求 ​​wc​​ 考虑宽字符:
$ echo '中文测试' | wc -m
5换行符也是一个符号,所以结果为 5(而非 4)。
由于中文文本的单词统计涉及分词算法问题,​​wc​​ 无法准确统计。
文本比较:diff
diff 工具用于比较两个文件的不同,并列出差异。
$ echo hello > file1
$ echo hallo > file2
$ diff file1 file1
$ diff file1 file2
1c1

< hello

hallo小知识
加参数 ​​-w​​​ 可忽略所有空白字符, ​​-b​​ 可忽略空白字符的数量变化。
假如比较的是两个文本文件,差异之处会被列出;假如比较的是二进制文件,只会指出是否有差异。
文本开头与结尾:head & tail
顾名思义,head 和 tail 分别用来显示开头和结尾指定数量的文字。
以 head 为例,这里给出共同的用法:
• 不加参数的时候默认显示前 10 行
• ​​-n ​​​ 指定行数,可简化为 ​​-​​
• ​​-c ​​ 指定字节数
$ head file # 显示 file 前 10 行
$ head -n 25 file # 显示 file 前 25 行
$ head -25 file # 显示 file 前 25 行
$ head -c 20 file # 显示 file 前 20 个字符
$ tail -10 file # 显示 file 最后 10 行除此以外,tail 还有一个非常实用的参数 ​​-f​​​:当文件末尾内容增长时,持续输出末尾增加的内容。这个参数常用于动态显示 log 文件的更新(试一试 ​​tail -f /var/log/syslog​​)。
文本查找:grep
​​grep​​ 命令可以查找文本中的字符串:
$ grep 'hello' file # 查找文件 file 中包含 hello 的行
$ ls | grep 'file' # 查找当前目录下文件名包含 file 的文件
$ grep -i 'Systemd' file # 查找文件 file 中包含 Systemd 的行(忽略大小写)
$ grep -R 'hello' . # 递归查找当前目录下内容包含 hello 的文件不止如此!
grep 事实上是非常强大的查找工具,第九章将在介绍正则表达式语法之后进一步介绍 grep。
文本替换:sed
​​sed​​ 命令可以替换文本中的字符串:
$ sed 's/hello/world/g' file # 将文件 file 中的 hello 全局(global)替换为 world 后输出
$ sed 's/hello/world/' file # 将文件 file 的每一行第一个出现的 hello 替换为 world 后输出
$ echo 'helloworld' | sed 's/hello/world/g' # 管道也是可以的
$ sed -i 's/hello/world/g' file # -i 参数会直接写入文件,操作前记得备份哦!
$ sed -i.bak 's/hello/world/g' file # 当然,也可以让 sed 帮你备份到 file.bak对于大多数用户来说,最常用 ​​sed​​ 的场合是替换软件源的时候。在阅读了上面的示例之后,以下例子就很简单了:
$ sudo sed -i 's/cn.archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
$ sudo sed -i 's/archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
$ sudo sed -i 's/security.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list同样不止如此!
sed 事实上是非常强大的文本操作工具,不仅支持正则表达式,而且能够做的操作也不止是替换。第九章将进一步介绍 sed。
Shell 脚本
什么是 Shell
Shell 是 Linux 的命令解释程序,是用户和内核之间的接口。除了作为命令解释程序外,Shell 同时还提供了一个可支持强大脚本语言的程序环境。
Bash
Bourne Shell (​​sh​​),是 Unix 系统的默认 Shell,简单轻便,脚本编程功能强,但交互性差。
Bourne Again Shell,即 Bash,是 GNU 开发的一个 Shell,也是大部分 Linux 系统的默认 Shell,是 Bourne Shell 的扩展。
Bash 允许用户定制环境以满足自己需要。通过修改环境文件 ​​.bash_profile​​​、​​.bashrc​​​、​​.bash_logout​​,配置合适的环境变量,可以改变主目录、命令提示符、命令搜索路径等用户工作环境。
此外,bash 也支持使用 ​​alias​​​ 别名代替命令关键字(​​alias name='命令'​​​)。输入 ​​alias​​,可以查看目前存在的别名:
$ alias
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s[0-9]+\s//;s/[;&|]\salert$//'\'')"'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
alias ls='ls --color=auto'
$ ll # 执行 ll 相当于执行 ls -alF
总用量 128
drwxr-xr-x 18 ustc ustc 4096 2月 28 00:51 ./
drwxr-xr-x 3 root root 4096 11月 17 20:26 ../
drwxr-xr-x 2 ustc ustc 4096 11月 17 20:45 公共的/
drwxr-xr-x 2 ustc ustc 4096 11月 17 20:45 模板/
(以下省略)其他 shell 的 alias
除了 bash 以外,其他的 shell 也有 alias 的支持。例如在 zsh 中也可以使用 ​​alias​​ 命令查看所有的 alias 列表。
部分 shell 会自带一些 alias,例如 fish 中的 ll 就是 ls -lh 的别名。特别地,Windows 自带的 PowerShell 中的 alias 存在一些争议,例如其对 ​​curl​​​ 的 alias 实际上是 ​​Invoke-WebRequest​​,而这个命令和上文介绍的 curl 的行为完全不同,给用户带来了困惑。
Bash 脚本的运行
可以使用几种方法运行 Bash 脚本:
• 在指定的 Shell 下执行,将脚本程序名作为 Shell 的第一个参数:
$ bash show.sh [option]• 将脚本设置为可执行,然后像外部命令一样执行:
$ chmod a+x show.sh
$ ./show.sh [option]关于 ​​.​​ 命令
与直接执行脚本,或者指定 shell 执行脚本不同,使用 ​​.​​ 命令执行脚本会在当前 shell 中执行脚本,而不是新建一个 shell 去执行脚本。这意味着,脚本中的变量定义、函数定义等都会在当前 shell 中生效。
在 bash 中,​​source​​​ 命令与 ​​.​​​ 命令等价。有些情况下,使用 ​​.​​ 执行脚本是有必要的,例如在激活 Python 的虚拟环境时:
. venv/bin/activate但是绝大多数时候,如果不清楚 ​​.​​​ 或 ​​source​​ 命令的行为,不建议使用这种方式执行脚本。
许多 Bash 脚本会在文件首行加上 ​​#!/bin/bash​​​ 。这里 ​​#!​​​ 符号的名称是 shebang(也叫 sha-bang,即 sharp ​​#​​​ 与 bang ​​!​​)。当一个文本文件首行有 shebang,且以可执行模式执行时,shebang 后的内容会看作这个脚本的解释器和相关参数,系统会执行解释器命令,并将脚本文件的路径作为参数传递给该命令。
例如,某个 ​​foo.sh​​​ 首行为 ​​#!/bin/bash​​​,则执行 ​​./foo.sh​​​ 就等于执行 ​​/bin/bash ./foo.sh​​。
Bash 也支持在同一个行中安排多个命令:
分隔符
说明
​​;​​
按命令出现的先后,顺序执行
​​&&​​
先执行前面的命令,若成功,才接着执行后面命令;若失败,不执行后面命令
​​||​​
先执行前面的命令,若成功,不执行后面命令;若失败,才执行后面命令
后缀 ​​&​​
后台方式执行命令
组命令:
• 使用 ​​{ 命令1; 命令2; … }​​,组命令在 shell 内执行,不会产生新的进程,注意花括号和命令之间的空格。
• 使用 ​​(命令1; 命令2; …)​​,组命令会建立独立的 shell 子进程来执行组命令,这里的圆括号周围并不需要空格。
组命令示例
shell 变量
像大多数程序设计语言一样,shell 也允许用户在程序中使用变量。但 shell 不支持数据类型,它将任何变量值都当作字符串。但从赋值形式上看,可将 shell 变量分成四种形式:用户自定义、环境变量、位置变量和预定义特殊变量。
用户自定义变量
变量定义:​​name=串​​​,其中 ​​=​​​ 两边不允许有空格。如果字串中含空格,就要用双引号括起。在引用时,使用 ​​$name​​​ 或 ​​${name}​​,后者花括号是为了帮助解释器识别变量边界。
已定义的变量可以通过 ​​unset name​​ 来删除。
变量使用示例
变量定义:
for skill in Ada Coffee Action Java; do
echo "I am good at ${skill}Script"
done输出:
I am good at AdaScript
I am good at CoffeeScript
I am good at ActionScript
I am good at JavaScript如果不给 ​​skill​​​ 加花括号标明变量名的边界,写成 ​​echo "I am good at $skillScript"​​​ ,解释器就会把 ​​$skillScript​​ 当成一个变量(其值为空)。
删除变量:
Today=1024
unset Today
echo $Today输出为空。
处理未定义的变量
环境变量
每个用户登录系统后,Linux 都会为其建立一个默认的工作环境,由一组环境变量定义,用户可以通过修改这些环境变量,来定制自己工作环境。在 Bash 中,可用 ​​env​​ 命令列出所有已定义的环境变量。通常,用户最关注的几个变量是:
• ​​HOME​​​:用户主目录,一般情况下为 ​​/home/用户名​​。
• ​​LOGNAME​​:登录用户名。
• ​​PATH​​​:命令搜索路径,路径以冒号分割。当我们输入命令名时,系统会在 ​​PATH​​ 变量中从前往后逐个搜索对应的程序是否在目录中。
• ​​PWD​​:用户当前工作目录路径。
• ​​SHELL​​:默认 shell 的路径名。
• ​​TERM​​:使用的终端名。
可以使用 ​​export​​​ 命令来定义环境变量。在同一个 shell 中使用 ​​export​​ 定义之后,这个环境变量会一直保留,直到这个 shell 退出。
$ export A=1
$ env | grep A=
A=1此外,也可以在命令前加上环境变量的定义。此时只有这一条命令的环境变量出现变化。
$ B=1 env | grep B=
B=1
$ env | grep B=
$ # B=1 的环境变量定义仅对该命令有效位置变量
• Shell 解释用户的命令时,把命令程序名后面的所有字串作为程序的参数。分别对应 ​​$1​​​、​​$2​​​、​​$3​​​、……、​​$9​​​,程序名本身对应 ​​$0​​。
• 可用 ​​shift ​​​ 命令,丢弃开头的 n 个位置变量,改变 ​​$1​​​、​​$2​​​、​​$3​​ 等的对应关系。
• 可用 ​​set​​​ 命令,重置整个位置变量列表,从而给 ​​$1​​​、​​$2​​​、​​$3​​ 等赋值。
范例
特殊变量
Shell 中还有一组有 shell 定义和设置的特殊变量,用户只能引用,而不能直接改变或重置这些变量。
特殊变量
说明
​​$#​​
命令行上的参数个数,不包括 ​​$0​​
​​$?​​
最后命令的退出代码,0 表示成功,其它值表示失败
​​$$​​
当前进程的 PID
​​$!​​
最近一个后台运行进程的进程号
​​$
​​
命令行所有参数构成的一个字符串
​​$@​​
用双引号括起的命令行各参数拼接构成的一个字符串
特殊字符
• 反斜杠,消除单个字符的特殊含义。
• 包含空白字符(空格和制表符)、反斜杠本身、各种引号,以及 ​​$​​​、​​!​​ 等。
• 与其他语言不同,shell 中反斜杠不会将普通字符转义为其他含义(例如 ​​\n​​ 不会被视作换行符)。
• 使用双引号包裹字符串可以消除空白字符切分参数的特殊含义,但是很多其他特殊字符的特殊含义仍然保留。双引号也被称为「弱引用」。
• 单引号,能消除所有特殊字符的特殊含义,包括反斜杠,因此单引号字符串中不能使用反斜杠转义单引号本身。单引号也被称为「强引用」。
• 反引号(​​​​)括起的字符串,被 shell 解释为命令,执行时用命令输出结果代替整个反引号对界限部分。 • 与反引号相同的语法是 ​​$(command)​​,它的好处是界限更明确,且可以嵌套。因此编写新脚本时,更建议使用此语法。 特殊字符示例 $ ls /mnt/c/Program Files/ ls: cannot access /mnt/c/Program: No such file or directory ls: cannot access Files/: No such file or directory $ # 对于 ls 来说,它接收到了两个参数:/mnt/c/Program 和 Files/,因此会报错。 $ # 可以使用反斜杠来转义空格 $ ls /mnt/c/Program\ Files/ # 输出省略 $ # 或者使用双引号或单引号包裹 $ ls "/mnt/c/Program Files/" $ ls '/mnt/c/Program Files/' $ echo "$PWD" # 双引号中仍然可以使用各种 shell 特殊符号 /home/ustc $ echo '$PWD' # 但是单引号则不行 $PWD $ ls -lhwhich ls` # 查看 ls 命令对应的程序信息,使用反引号语法
-rwxr-xr-x 1 root root 139K Sep 5 2019 /usr/bin/ls
$ ls -lh $(which ls) # 使用 $(command) 语法也是一样的
-rwxr-xr-x 1 root root 139K Sep 5 2019 /usr/bin/ls变量输入与输出
输入
可以使用 ​​read​​​ 命令读取用户输入,并将输入的内容赋值给变量。其中 ​​-p​​ 参数后可以设置输出的提示信息。
$ name=""
$ read -p "Enter your name: " name # 输出提示,然后从输入读取一个值,存储到 $name 中
Enter your name: linux
$ echo $name
linux在使用 ​​read​​​ 时,建议加上 ​​-r​​​ 参数,否则 ​​\​​ 会被视为转义符号。
$ message=""
$ read -p "Enter your message: " message
Enter your message: (^o^)/~
$ echo $message # 可以看到,反斜杠被认为是转义符号,结果被丢弃
(^o^)/~
$ read -r -p "Enter your message: " message
Enter your message: (^o^)/~
$ echo $message # 加上 -r 参数后,反斜杠完好无损
(^o^)/~输出
可以使用 ​​echo​​​ 命令输出变量信息。其中 ​​-n​​​ 参数不会在结尾输出换行符,而 ​​-e​​​ 参数会解析文本中的转义字符(例如 ​​\n​​)。
$ echo -n "hello"
hello$ # 由于这里 echo 结尾不输出换行,shell 就会在这里继续接受用户输入
$ # 这也是为什么在 C 语言中最后的 printf 输出需要加上 \n 的原因
$ name="linux"
$ echo "Hello $name.\nWelcome to bash!" # 可以看到 \n 没有被转义成换行
Hello linux.\nWelcome to bash!
$ echo -e "Hello $name.\nWelcome to bash!" # 加上 -e 之后就被转义了
Hello linux.
Welcome to bash!此外,​​printf​​​ 命令也可以用来输出,它的使用方法类似于 C 中的 ​​printf()​​ 函数。
$ name="linux"
$ printf "Hello %s" "$name"
Hello linux$ # 和 echo 不同,printf 结尾默认不输出换行符
$ printf "Hello %s\n" "$name"
Hello linux
$ # 所以为了正常显示,需要在结尾补上 \n算术运算
在 Bash 中进行算术运算,需要使用 ​​expr​​​ 计算算术表达式值或 ​​let​​​ 命令赋值表达式值到变量。基本运算符是 ​​+​​​、​​-​​​、​​*​​​ (转义)、​​/​​​、​​%​​​。在 ​​expr​​​ 中,运算符两边与操作数之间必须有空格,小括号要转义;但 ​​let​​​ 则没有这个要求,运算符前后有无空格均可,小括号不需转义,但 ​​=​​ 前后不能有空格。
另外,所有标准的 shell 都支持另一种语法 ​​(( 表达式 ))​​​,其中 ​​表达式​​​ 是一个 C 风格的数学表达式,可以计算,也可以赋值。​​(( 表达式 ))​​ 是一条完整的命令,命令的返回值为 0 或 1。若表达式的结果非零,那么 ​​(( 表达式 ))​​ 命令返回零,而当表达式结果为零时命令返回 1。
​​(( 表达式 ))​​ 的返回值
使用 ​​$(( 表达式 ))​​ 可以将计算结果用作为命令行的一部分,就像使用变量一样。
​​expr​​​ 和 ​​let​​ 使用示例
条件表达式
条件表达式写成 ​​test 条件表达式​​​,或 ​​[ 条件表达式 ]​​,注意表达式与方括号之间有空格。
字符串比较
表达式
含义
​​string1 = string2​​
如果两个串相等,则结果为真(true: 0)
​​string1 != string2​​
如果两个串不相等,则结果为真
​​string​​​ 或 ​​-n string​​
如果字符串 string 长度不为 0,则结果为真
​​-z string​​
如果字符串 string 长度为 0,则结果为真
数值比较
表达式:​​int1 [option] int2​​,其中的参数可以用下列替换。
参数
说明
​​-eq​​
等于
​​-ne​​
不等于
​​-gt​​
大于
​​-ge​​
大于等于
​​-lt​​
小于
​​-le​​
小于等于
文件状态
表达式
含义
​​-r file​​
文件存在且可读
​​-w file​​
文件存在且可写
​​-x file​​
文件存在且可执行
​​-f file​​
文件存在且为普通文件
​​-d file​​
文件存在且为目录
​​-s file​​
文件存在且长度大于 0
复合逻辑表达式
表达式
含义
​​! expr​​
否运算
​​expr1 –a expr2​​
与运算
​​expr1 –o expr2​​
或运算
流程控制
条件分支:if
序列中可嵌套 if 语句,在 shell 中也允许有多个 elif ,但 shell 的流程控制不可为空。末尾的 ​​fi​​​ 就是 ​​if​​ 倒过来写,后面还会遇到类似的结束符。
if condition1
then
commands1
elif condition2
then
commands2
else
commands3
fi按值选择:case
选项值必须以右括号 ​​)​​​ 结尾,若匹配多个离散值,用 ​​|​​​ 分隔。这里的 ​​esac​​​ 也是 ​​case​​ 倒着写。
case in
value1|value2)
command1
command2
;;
value3)
command3
;;
*)
command4
;;
esac枚举循环:for
for 循环可以对一个列表中的每个值都执行一系列命令。
for var in list
do
commands $var
done条件循环:while 和 until
while 循环用于不断执行一系列命令,命令通常为测试条件。until 与 while 相反,仅在测试条件失败时循环。
while condition
do
commands
done

until condition
do
commands
done流程控制样例
除此之外,用于流程控制的还有在 C 语言中同样常见的 ​​break​​​ 和 ​​continue​​​。与 C 语言不同的是,它们还接受一个数字作为参数,即 ​​break n​​​ 和 ​​continue n​​​,其中参数 ​​n​​ 均表示跳出或跳过 n 层循环。
函数
与其他编程语言类似,shell 也可以定义函数。其定义格式为:

POSIX syntax

name() {
commands
[return ]
}

Bash syntax

function name {
commands
[return ]
}其中函数的参数可以像命令一样通过 ​​$1​​​、​​$2​​​、​​$3​​​ 等获取,返回值可以显式用 ​​return​​​ 返回,或以最后一条命令运行结果作为返回值。在函数中使用 ​​return​​​ 会结束本次函数执行,而使用 ​​exit​​ 会直接结束退出包含函数的当前脚本程序。
函数在使用前必须定义,因此应将函数定义放在脚本开始的部分。在调用函数时仅使用其函数名即可。
范例
Bash 脚本调试¶
Bash shell 本身提供了调试方法:
• 命令行中:​​$ bash -x script.sh​​。
• 脚本开头:​​#!/bin/bash -x​​。
• 在脚本中用 set 命令调整(​​set -x​​​ 启用,​​set +x​​ 禁用)。
其中参数选项可以更改,​​-n​​​:读一遍脚本中的命令但不执行,用于检查语法错误;​​-v​​​:一边执行脚本、一边将执行过的脚本命令打印到标准输出;​​-x​​:提供跟踪执行信息,将执行的每一条命令和结果依次打印出来。注意避免几种调试选项混用。
除了 Bash shell 内置的选项,还有 BASH Debugger、shellcheck 等第三方脚本分析工具

相关文章
|
2天前
|
安全 Linux Shell
Linux上执行内存中的脚本和程序
【9月更文挑战第3天】在 Linux 系统中,可以通过多种方式执行内存中的脚本和程序:一是使用 `eval` 命令直接执行内存中的脚本内容;二是利用管道将脚本内容传递给 `bash` 解释器执行;三是将编译好的程序复制到 `/dev/shm` 并执行。这些方法虽便捷,但也需谨慎操作以避免安全风险。
|
5天前
|
机器学习/深度学习 Linux Perl
Linux文本处理三剑客之sed详解
这篇博客详细讲解了Linux中的文本处理工具sed的使用方法和常用命令。
26 9
Linux文本处理三剑客之sed详解
|
2天前
|
存储 JSON Ubuntu
如何使用 Lua 脚本进行更复杂的网络请求,比如 POST 请求?
如何使用 Lua 脚本进行更复杂的网络请求,比如 POST 请求?
|
2天前
|
Shell Linux 开发工具
linux shell 脚本调试技巧
【9月更文挑战第3天】在Linux中调试shell脚本可采用多种技巧:使用`-x`选项显示每行命令及变量扩展情况;通过`read`或`trap`设置断点;利用`echo`检查变量值,`set`显示所有变量;检查退出状态码 `$?` 进行错误处理;使用`bashdb`等调试工具实现更复杂调试功能。
|
7天前
|
安全 Linux 开发工具
探索Linux操作系统:从命令行到脚本编程
【8月更文挑战第31天】在这篇文章中,我们将一起潜入Linux操作系统的海洋,从最基础的命令行操作开始,逐步深入到编写实用的脚本。无论你是初学者还是有一定经验的开发者,这篇文章都将为你提供新的视角和实用技能。我们将通过实际代码示例,展示如何在日常工作中利用Linux的强大功能来简化任务和提高效率。准备好了吗?让我们一起开启这段旅程,探索Linux的奥秘吧!
|
1天前
|
域名解析 负载均衡 网络协议
Linux网络接口配置不当所带来的影响
总而言之,Linux网络接口的恰当配置是保证网络稳定性、性能和安全性的基础。通过遵循最佳实践和定期维护,可以最大程度地减少配置错误带来的负面影响。
6 0
|
7天前
|
Linux
探索Linux操作系统:命令行与脚本编程基础
【8月更文挑战第31天】在这篇文章中,我们将一起踏上一段旅程,深入探索Linux操作系统的奥秘。通过学习命令行的使用和编写简单的脚本,你将能够更高效地与你的计算机进行交流。无论你是新手还是有经验的用户,本文都将为你打开一扇通往Linux世界的大门。准备好了吗?让我们开始吧!
|
8天前
|
运维 监控 Linux
深入理解Linux系统运维:命令行与脚本的奥秘
【8月更文挑战第30天】在Linux的世界里,命令行是运维人员的灵魂之窗。掌握命令行,就像握住了一把钥匙,能开启系统管理的宝藏箱。本文将带你走进Linux的命令行世界,通过实际代码示例,解锁那些高效管理和维护系统的秘籍。你将学到不仅仅是命令本身,更是如何将这些命令编织成强大的脚本,让日常的运维工作变得游刃有余。准备好跟随我的步伐,一起深入探索Linux命令行与脚本的奥秘吧!
|
14天前
|
存储 Linux 网络安全
【Azure 存储服务】如何把开启NFS 3.0协议的Azure Blob挂载在Linux VM中呢?(NFS: Network File System 网络文件系统)
【Azure 存储服务】如何把开启NFS 3.0协议的Azure Blob挂载在Linux VM中呢?(NFS: Network File System 网络文件系统)
|
14天前
|
存储 Linux 网络安全
【Azure 应用服务】App Service For Linux 如何在 Web 应用实例上住抓取网络日志
【Azure 应用服务】App Service For Linux 如何在 Web 应用实例上住抓取网络日志
下一篇
DDNS