Shell编程
文章平均质量分 74
Shell编程基础
吴声子夜歌
个人学习记录
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
Shell编程实例——命令行处理
shell 并不会生成分页文件列表,而是将 | 和 more 视为 ls的参数,ls 会抱怨没有这种名称的文件存在。要想成为真正的 shell 脚本编程专家(或者为了调试一些棘手的问题),你需要理解命令行处理过程涉及的各个步骤,尤其是这些步骤的先后顺序。如果不确定在 shell 编程的某个时刻到底是该用单引号还是双引号,最稳妥的做法就是使用单引号,除非你需要执行参数、命令或算术替换操作。对于读入的管道,shell 会将其分解成命令,设置管道的I/O,然后对每个命令执行下列操作。,其值为 2357(记住,原创 2026-09-19 21:32:28 · 164 阅读 · 0 评论 -
Shell编程实例——参考(二)
除了 \f,这些转义序列的行为差不多都能预测,在有些显示器上,\f 会清理屏幕,而在另一些显示器上,它会产生换行,而且在大多数打印机上会弹出纸张。%b 和 %q 是对 bash(以及其他 POSIX 兼容 shell)的补充,其提供实用特性的代价是,无法移植到其他 shell 和Unix 中的 printf 命令。如果格式要求的参数多于现有的参数,多出的那些格式说明符就假定提供的参数是 0 值或空串(视情况而定)。主要的格式说明符有两种,分别是用于字符串的 %s 和用于十进制整数的 %d。原创 2026-09-19 18:34:34 · 194 阅读 · 0 评论 -
Shell编程实例——参考(一)
下表展示了可用的提示符自定义格式代码,其中,\[和\]在 bash 1.14 之前不可用,\a\e\H\T\@\v\V在 bash 2.0 之前不可用。\A\D\j\l\r仅可用于bash 2.0 之后以及 bash 3.0+。原创 2026-09-19 14:45:22 · 185 阅读 · 0 评论 -
Shell编程实例——窍门与陷阱:新手常见错误
shell 脚本是按照自上而下的线性方式读取并执行的,因此必须在使用函数前先定义函数。有些其他语言(如 Perl)会经历一些中间步骤,在此过程中,整个脚本将被解析为一个单元。这允许你在编写代码时将 main() 置于开头,将函数(或子例程)定义放在随后。相比之下,shell 脚本是被读入内存,并一次一行执行的,因此函数不能先使用再定义。原创 2026-09-19 13:23:51 · 225 阅读 · 0 评论 -
Shell编程实例——写得少,干得快
用!$ 指明上一个命令中的最后一个参数。!:1 表示第一个参数,!:2 表示第二个参数,以此类推。多个命令使用相同的文件名为参数是司空见惯的事情。最常见的场景之一就是程序员编辑源代码文件,然后编译、再编辑,再编译……有了!$,事情就方便多了。原创 2026-09-19 11:25:13 · 175 阅读 · 0 评论 -
Shell编程实例——内务及管理任务(二)
其中最重要的一点是,使用 sudo 时,你需要输入自己的密码,确认身份之后才允许执行命令。这种限制可能很棘手,因为许多应用程序允许用户启动额外的 shell,以执行其他操作(因此,如果你能够通过 sudo 进入 vi,就可以启动一个不受限制的 root shell)。如果你知道 PID(假设是从锁文件或环境变量中得知的),直接根据 PID 搜索即可(要仔细地将 PID 与其他可识别的字符串一并拿来匹配,以免出现冲突,因为你用来进行匹配的 PID 可能正好与某些随机进程的陈旧 PID 相同)。原创 2026-09-19 00:16:36 · 230 阅读 · 0 评论 -
Shell编程实例——内务及管理任务(一)
当然,惯常的做法是将脚本输出重定向成一个新文件,就像 sed -e ‘$r data’ header > new_file 一样,但要注意,这会改变文件的 i 节点(inode),也许还会改变其他的文件属性,如权限或所有权。这里的问题是,你可能无法修改该作业,或者作业本身要做的事情超出了这些方法的解决能力(例如,如果需要用户输入,它会在提示符出现之前一直干等着)。注意,从理论上讲,相同的文件在不同的机器或 diff 版本上得到的结果会略有不同,因为 hunk 的数量是由 diff 所使用的算法决定的。原创 2026-09-18 21:52:43 · 144 阅读 · 0 评论 -
Shell编程实例——bash的配置与自定义(二)
12、使用辅助提示符:$ PS2、$ PS3、$ PS413、在会话间同步shell历史记录14、设置shell的历史选项15、创建更好的cd命令16、一次性创建并切换到新目录17、直达底部18、用可装载的内建命令为bash添加新特性19、改善可编程补全20、正确使用初始化文件21、创建自包含的可移植rc文件。原创 2026-09-18 18:23:29 · 168 阅读 · 0 评论 -
Shell编程实例——bash的配置与自定义(一)
1、bash启动选项2、自定义提示符3、在程序运行前出现的提示符4、永久修改$PATH5、临时修改$PATH6、设置$CDPATH7、当找不到命令时8、缩短或修改命令名称9、调整shell行为及环境10、用.inputrc调整readline的行为11、通过添加~/bin来存放个人工具默认的 bash 提示符通常以 $ 结尾,但信息不够丰富,传达不出太多的东西。你希望能够自定义提示符,以展现出更多实用的信息。根据需要自定义 $PS1 和 $PS2 变量。默认的提示符随系统而异。原创 2026-09-18 15:09:57 · 167 阅读 · 0 评论 -
Shell编程实例——高级脚本编程(二)
对于通过 cron 运行的脚本(不仅如此,很多人认为这包括所有的脚本或者 Unix 工具),正确的设计方法是使其安安静静的,除非碰到警告或错误。注意,mailto 针对 mail 升级了多媒体和 MIME 处理能力,这样一来,发送附件时就不需要 uuencode 了,但mailto 的使用率没有 mail 或 mailx 那么高。logger 还有其他一些值得注意的选项,你可以好好阅读一下相应的手册页,但要清楚,部分选项可能会随年代、版本、发行版而异,因此得考虑你的脚本是不是要大范围运行。原创 2026-09-18 14:10:50 · 156 阅读 · 0 评论 -
Shell编程实例——高级脚本编程(一)
另外,你所在的公司也许会构建或提供自己的虚拟机映像以供内部使用。如果前面提到的程序你一个都没有,但使用的是 2.04+ 版本的 bash,而且编译时使用了选项 --enable-net-redirections(在 Debian 及其衍生发行版中,bash 4.0 之前的版本并未使用该编译选项),你也可以依靠 bash。如果目标平台运行在 x86 架构上,要么在众多的免费和商业虚拟化解决方案中选择一种,构建自己的测试虚拟机,要么在操作系统厂商的网站或者 Internet 上搜索预先构建好的虚拟机。原创 2026-09-18 13:46:04 · 295 阅读 · 0 评论 -
Shell编程实例——编写安全的shell脚本(二)
为简化起见,你可以将 SSH 看作是将本地的 STDOUT 连接到远端的 STDIN,同时将远端的 STDOUT 连接到本地的 STDIN,因此,诸如 scp 或 rsync 的所有操作都是将本地主机的一个个字节送往远程主机,就好像二者之间有条管道一样。如果试图使用类似于 chmod -R 0644 some_directory 的命令递归设置目录中所有文件的权限,那你会后悔的,因为你将所有的子目录都设置成了不可执行,这意味着无法访问目录中的内容,无法使用 cd 进入,也无法遍历其中。原创 2026-09-18 01:09:41 · 159 阅读 · 0 评论 -
Shell编程实例——编写安全的shell脚本(一)
尤其要注意的是,Debian 和 Ubuntu 目前使用的都是 dash,因为相较于 bash,dash 的体积更小,运行速度更快,有助于加快系统引导速度。如果输入ls,恰好 /tmp 中也有一个同名文件(/tmp/ls),那么执行的就是该文件,而不是你原本打算执行的 /bin/ls。有些程序(如 InfoZip)使用环境变量(如 $ZIP 和 $UNZIP)向自身传递设置,如果使用了 ZIP=‘/usr/bin/zip’,那就等着抓耳挠腮吧,苦思冥想为什么在命令行上还好好的,但到了脚本里就不行了。原创 2026-09-17 22:47:08 · 147 阅读 · 0 评论 -
Shell编程实例——与解析相关的任务(二)
在 sed 中,替换运算符右侧(righthand side,RHS)的 & 会被左侧(lefthand side,LHS)的整个正则表达式所匹配到的字符串替换掉,第一行结尾处的 \ 用于转义换行符,否则会出现类似于“sed: -e expression #1,char 11: unterminated‘s’”这样的错误。为此,通过指定制表符为字段分隔符并将 OFS 设置为“,”,我们用 awk 分割输入行,这样就可以在每个字段的结尾和下一个字段的起始位置加上引号,同时在两者之间添加逗号。原创 2026-09-17 21:54:18 · 194 阅读 · 0 评论 -
Shell编程实例——与解析相关的任务(一)
你正在使用 getopts 解析 shell 脚本选项,但是不喜欢它在遇到错误输入时显示的错误信息。能不能在使用getopts 的同时编写自己的错误处理?如果只是想让 getopts 安安静静,不报告任何错误,那么在开始解析前执行赋值操作 OPTERR=0 即可。但如果希望 getopts 在不显示错误消息的情况下提供更多信息,可以在选项列表之前加上一个冒号,如下例中的脚本所示。(选项列表两边的引号是可选的。)# 实例文件:getopts_custom# 解析参数时使用自定义错误消息aflag=原创 2026-09-17 17:37:25 · 106 阅读 · 0 评论 -
Shell编程实例——帮助最终用户完成任务的shell脚本
(顺便说一下,在这个例子中,因为是在函数内部,所以修改的仅仅是函数的位置参数,而不是所调用脚本的位置参数。在命令行上,使用 cd 进入想要创建相册的目录(通常就是保存照片的地方),然后执行命令(如 ls *.jpg,也可以参见 9.5 节),生成要包含在相册内的照片列表,再将输出通过管道传给例 12-2 中的 shell 脚本 mkalbum(随后我们会解释)。毕竟,你就是该脚本唯一的用户,很清楚适合的用法,也没打算乱用,如果脚本出错,显示错误信息时也用不着考虑是否美观。>)之前各插入一个换行符。原创 2026-09-17 16:09:24 · 56 阅读 · 0 评论 -
Shell编程实例——处理日期和时间
如果用的是其他cron 程序,可能得根据 cron 使用的调度方式将星期几的名称转换成数字(0-6 或 1-7),并用 +%w(数字形式的星期几)代替 +%a(所在语言环境下的缩写形式的星期几)。这比听起来要难得多。在4.2 版本中,空参数被视为空(null),然后返回 Unix 纪元的当地时间,这肯定不是你想要的。如果你自己算不出结果,那就需要使用 date 命令(参见3 节)将已有的日期和时间转换成纪元秒(参见 4节),执行相关运算,然后将得出的纪元秒转换成你需要的格式(参见 5 节)。原创 2026-09-17 14:21:18 · 174 阅读 · 0 评论 -
Shell编程实例——脚本编程的附加特性
你想在 shell 脚本的几处地方为用户显示用法信息(描述正确的命令语法),但又不愿意重复同样的 echo 语句。有办法只写一次代码,然后多次引用吗?如果可以将用法信息作为单独的脚本,那就可以在原始脚本的任意位置调用了,但这样的话,本来一个脚本就能搞定的事,现在则需要两个。而且,将一个脚本的用法信息作为另一个脚本的输出看起来怪怪的。有没有更好的解决方法?你需要的是 bash 函数。原创 2026-09-17 13:32:29 · 131 阅读 · 0 评论 -
Shell编程实例——查找文件:find、locate、slocate
这里的问题不在于文件存在时,而在于文件不存在时。要是在 NetBSD 上尝试上面这行,你会得到 no myfile in /sbin /usr/sbin/bin /usr/bin /usr/pkg/sbin /usr/pkg/bin /usr/X11R6/bin /usr/ local/sbin /usr/local/bin,这不会是你想看到的。两者的顺序并不影响最终结果,但将 -type d 放在谓词列表的最前面能略微提高搜索效率:对于碰到的每个文件,先测试其是否为目录,如果是,才测试名称是否符合模式。原创 2026-09-17 00:20:20 · 195 阅读 · 0 评论 -
Shell编程实例——中级shell工具(二)
使用 sort 实用工具。通过在命令行上指定文件名,你可以对一个或多个文件进行排序。原创 2026-09-16 22:03:01 · 151 阅读 · 0 评论 -
Shell编程实例——中级shell工具(一)
可以通过管道将 ls 的输出传给 awk,并从中挑选出你需要的字段。原创 2026-09-16 16:49:46 · 112 阅读 · 0 评论 -
Shell编程实例——逻辑与算术(二)
但要注意,switch/case 中使用的是 shell 变量(通常包含字符串值),分支中使用的是模式(不仅仅是常量值)。参数可以多于 3 个,但总数始终应该是奇数(一开始是 3个参数,然后是下一个操作数和运算符,共计 2 个,以此类推,始终要再添加 2 个参数。第二个脚本更有 shell 的范儿,既不用 grep 进行搜索(使用的是 if 语句),也没用 cut 剪切(使用的是 read 语句)。因此,我们剔除了 $0 中的部分内容,只留下脚本的基本名称(类似于使用 basename 命令)。原创 2026-09-16 09:54:00 · 218 阅读 · 0 评论 -
Shell编程实例——逻辑与算术(一)
如果 $V1 为空,那就完全不用再对 if 语句中的第二个条件(检查 $V2 是否为空)求值了,但 $V2 的值也许已经被修改了(对 $V2 进行变量替换的副作用)。在 bash 中,while 语句的语法是这么定义的:该语句的条件是一系列要执行的命令(就像 if 语句),最后一个命令的退出状态决定了条件是真还是假。双括号仅限于算术表达式,方括号还可以测试文件特性,但后者的算术测试语法远不如前者方便,尤其是用括号将表达式划分成若干子表达式时(在方括号中,需要给括号加上引号或将其转义)。原创 2026-09-16 08:49:11 · 174 阅读 · 0 评论 -
Shell编程实例——shell变量(二)
如果将第一个 / 换成 //,则会替换变量中所有指定的内容,最后就成了 subashdon.bash,这也并非我们所愿。如果变量中保存的是 /usr/local/bin/mycmd,我们希望得到的是 /usr/local/bin,同时丢弃最后一部分(文件名)。因为 basename 命令会忽略路径结尾的 /,所以 $(basename /usr/local/bin/) 会返回 bin,而我们用 bash 所实现的版本则返回空串(因为模式*/ 所能匹配的最长内容就是整个字符串)。如果找到,则将其删除;原创 2026-09-15 22:54:31 · 196 阅读 · 0 评论 -
Shell编程实例——shell变量(一)
将希望传给其他脚本的变量导出。原创 2026-09-15 20:54:39 · 136 阅读 · 0 评论 -
Shell编程实例——执行命令
更重要的是,向不存在的位置写入信息会产生错误。在6 节中,&& 告诉 bash 如果第一个表达式为假,则不再评估第二个表达式,与此类似,|| 告诉 bash 如果第一个表达式为真(成功),则不再评估第二个表达式。这是因为主目录下有一个名为 ls 的空文件,你执行的其实就是这个 ls(什么都不做,本来就是个空文件),而不是位于 /bin 下正常的 ls 命令。在第二种解决方案中,只有第一个命令成功执行后第二个命令才会执行,第二个命令成功执行后第三个命令才会执行,以此类推,命令行中出现的命令均是如此。原创 2026-09-15 12:57:43 · 143 阅读 · 0 评论 -
Shell编程实例——标准输入
如果要将密码读入环境变量,那就要小心了,因为密码在内存中是以明文形式存放的,有可能通过核心转储或/proc/core(如果你所用的操作系统提供了 /proc/)访问到。我们发现,除非你真的要扩展数据,否则坚持转义终止符(就像 <<‘EOF’ 或 <<\EOF)是一种不错的做法,这样能够避免产生出乎意料的结果。这看起来也许并不起眼,如果你之前接触过 DOS 命令行,一定也不会陌生,但这是 shell 脚本编程的一项重要特性(DOS 命令行也借鉴了),对 shell 的功能性和简单性必不可少。原创 2026-09-15 10:28:28 · 125 阅读 · 0 评论 -
Shell编程实例——标准输出
Unix 和 Linux 中的每个进程通常一开始都有 3 个已打开的文件描述符:一个用于输入(标准输入STDIN),一个用于输出(标准输出 STDOUT),一个用于错误消息(标准错误 STDERR)。至于是否遵循这种约定,将错误消息写入标准错误,将正常输出写入标准输出,那真的就得看程序员了,因此,无法确保所有的错误消息都会进入标准错误。可以在shell 中打开任意数量的文件描述符,令其指向各种文件,这样一来,随后在命令行上调用的程序就不用再费事了,直接就可以使用这些已打开的文件描述符。原创 2026-09-15 01:06:13 · 243 阅读 · 0 评论 -
Shell编程实例——bash入门
为什么本书要介绍 bash,而不是别的 shell?因为 bash无处不在。它未必是最时髦的,可以说也不是最炫或最厉害的(就算不是,也差不多了),更不是唯一一个作为开源软件发布的 shell,但 bash 的大名尽人皆知。究其原因,和历史发展有关。第一批 shell 算得上相当不错的编程工具,但不便于日常使用。C shell 中加入了大量的用户便利功能(例如,可以重复用户输入过的命令),但作为编程语言,它又太诡异了。原创 2026-09-14 13:18:53 · 205 阅读 · 0 评论 -
Shell编程——信号及trap命令
运行Shell脚本程序时,如果按下快捷键Ctrl+c或Ctrl+x(x为其他字符),程序就会立刻终止运行。在有些情况下,我们并不希望Shell脚本在运行时被信号中断,此时就可以使用屏蔽信号手段,让程序忽略用户输入的信号指令,从而继续运行Shell脚本程序。简单地说,Linux的信号是由一个整数构成的异步消息,它可以由某个进程发给其他的进程,也可以在用户按下特定键发生某种异常事件时,由系统发给某个进程。原创 2026-09-14 00:39:52 · 66 阅读 · 0 评论 -
Shell编程——调试
网络上有很多实用的脚本,作为初学者,可以先将这些脚本拿过来,将其改写为适合自己服务器的脚本,然后再慢慢熟悉,慢慢尝试开发新的脚本。Linux系统上本来就有很多适合阅读的规范脚本,如果想要更加深入地掌握Shell脚本编程,最好的方法就是阅读系统的这些脚本,然后仔细研究每一行都是什么作用,为什么这样写,久而久之,你的Shell开发水平就会得到大幅度提高。在一个比较长的脚本中,你会看到很多的执行跟踪的输出,有时候阅读起来非常费劲,此时,可以在每一行的前面加上内容的行号,这会非常有用。原创 2026-09-14 00:22:44 · 86 阅读 · 0 评论 -
Shell编程——开发规范
全局变量也称环境变量,它的定义应全部大写,如APACHE_ERR或APACHEERR,名字对应的语义要尽量清晰,能够正确表达变量内容的含义,对于过长的英文单词可用前几个字符代替。多个单词间可用“_”号连接,全局变量的定义一般放在系统的全局路径中,并且最好采用export来定义,全局变量一般可以在任意子Shell中直接使用(特殊情况除外,例如:定时任务执行Shell时就最好在Shell里重新定义这些全局变量,否则可能会出现问题)。范例:全局变量的定义示例。hello。原创 2026-09-13 22:34:27 · 85 阅读 · 0 评论 -
Shell编程——数组
通常在开发Shell脚本时,定义变量采用的形式为“a=1;b=2;c=3”,可如果有多个变量呢?这时再逐个地定义就会很费劲,并且要是有多个不确定的变量内容,也会难以进行变量定义,此外,快速读取不同变量的值也是一件很痛苦的事情,于是数组就诞生了,它就是为了解决上述问题而出现的。如果读者有过其他语言的编程经历,那么想必会熟悉数组的概念。简单地说, Shell的数组就是一个元素集合,它把有限个元素(变量或字符内容)用一个名字来命名,然后用编号对它们进行区分。原创 2026-09-13 22:01:30 · 154 阅读 · 0 评论 -
Shell编程——循环控制及状态返回值
根据执行结果可以看到,当进入循环里的if语句后遇到return 119,就没有打印3以下的数字,说明return跳出了循环体,程序也没有执行for循环体done外的echo命令,而是直接执行了函数test外的if语句及打印ok的命令,可见return的作用是退出当前函数。可以看到,只有i等于3这层循环没有被执行,其他循环全部执行了,循环外的echo也执行了,说明执行到continue时,终止了本次循环,而继续下一次的循环,直到循环正常结束,接着继续执行了循环外面的所有语句。首先,给网卡配置额外的IP。原创 2026-09-13 20:54:49 · 173 阅读 · 0 评论 -
Shell编程——for和select循环
select循环语句的主要作用可能就是创建菜单,在执行带select循环语句的脚本时,输出会按照数字顺序的列表显示一个菜单项,并显示提示符(默认是#?),同时等待用户输入数字进行选择,下面就来带大家看看生成菜单项的语法及具体案例实践。select 变量名 [ in 菜单取值列表 ]do指令...done。原创 2026-09-13 17:48:52 · 191 阅读 · 0 评论 -
Shell编程——while循环和until循环
方式1:采用exec读取文件,然后进入while循环处理。方式2:使用cat读取文件内容,然后通过管道进入while循环处理。方式3:在while循环结尾done处通过输入重定向指定读取的文件。done<FILE范例:开发一个Shell脚本实现Linux系统命令cat读文件的基本功能。原创 2026-09-13 01:36:23 · 226 阅读 · 0 评论 -
Shell编程——case条件语句
说明:当变量的值等于值1时,执行指令1;如果都不符合,则执行“*)”后面的指令,即指令3。此外,注意不同行内容的缩进距离。当用户输入对应的数字选择水果的时候,告诉他选择的水果是什么,并给水果单词加上一种颜色(随意),要求用case语句来实现。如果用户输入的是1~9的任意数字,则输出对应输入的数字;在Linux脚本中,可以通过echo的-e参数,结合特殊的数字给不同的字符加上颜色并显示。内容的颜色可用数字表示,范围为30~37,每个数字代表一种颜色。字的背景颜色对应的数字范围为40~47,代码如下。原创 2026-09-13 00:35:52 · 87 阅读 · 0 评论 -
Shell编程——函数
在讲解Shell函数之前,先来回顾Linux系统中别名的作用。[root@oldboy ~]# ssh restart #<==执行ssh就相当于执行了/etc/init.d/sshd,最直接的好处就是简化了输入。停止 sshd: [确定]正在启动 sshd: [确定]函数也有类似于别名的作用,例如可简化程序的代码量,让程序更易读、易改、易用。原创 2026-09-12 23:12:10 · 113 阅读 · 0 评论 -
Shell编程——if条件语句
因此,请大家重视分析问题和程序设计的思想,而不要一上来就开始编码,这也是老男孩常说的,技术的提升仅是量的积累,思想的提升才是质的飞跃!在监控Nginx和监控数据库端口时,除了端口不同,其他的命令方法都是一模一样的,想要了解详细注释,可参见前文监控数据库的代码注释。前文已经说过,if条件语句(包括双多分支if)的“<条件表达式>”部分可以是test、[]、[[]]、(())等条件表达式,甚至还可以直接使用命令作为条件表达式,具体的语法如下。”,而if条件语句的双分支结构主体则为“如果…原创 2026-09-12 22:24:14 · 110 阅读 · 0 评论 -
Shell编程——条件测试与比较
在书写测试表达式时,可以使用表中的整数二元比较操作符。“=”和“!=”也可在[]中做比较使用,但在[]中使用包含“>”和“<”的符号时,需要用反斜线转义,有时不转义虽然语法不会报错,但是结果可能会不对。也可以在[[]]中使用包含“-gt”和“-lt”的符号,但是不建议这样使用。比较符号两端也要有空格。范例:二元数字在[]中使用“<”、“>”非标准符号的比较。11 #<==这里的结果逻辑不对,条件不成立,则应该返回0,可见,“<”操作符在[]里使用时会带来问题。原创 2026-09-12 15:31:43 · 62 阅读 · 0 评论
分享