,可视化shell调试?shell函数库?智能提示shell补全的vscode插件?这全都有,还不快到碗里来,当你遇到了服务器内存占用过多导致卡死的情况,你会怎么办?度娘 or 谷歌,你得到了这样的答案。,对啊,占用多了就干掉啊!,但怎么干?习惯图形化界面的咱们找不到删除图标啊!没关系,度娘 or 谷歌,你得到了这样的答案(下面命令执行后会删除占用内存最多的两个进程)。,看懂是不可能看懂的,这辈子是不可能看懂的。,抱着试试的态度,你登陆了 shell 并且执行了,然后你惊喜的发现,成了!腰也不酸了腿也不疼了,比新盖中盖都好使。,至此,你的问题得以解决,好学的同学可能会深入学习一番(关于此命令的详解咱们放在文末),然后随着时间推移,短期记忆海马体突触消散而告终。此文结束。慢着 QAQ,问一句,下次再出现这个情况咋办?再找一遍吗?我们陷入了循环。,显然,我们需要破除循环。怎么破除?想想我们熟悉的高级语言怎么解决这个问题的,封装呀,以 js 为例,各种稀奇古怪的操作被封装在一个又一个的库里,工具库的 lodash、网络请求的 axios 等等,函数名取的清晰易懂,取来即可。这才是我们想要的效果。,可 linux 是命令啊,一个个命令用分号或者管道符链接执行,咋封装?而且对于【批量执行命令】这个需求而言,用这两种方法真的不会感觉很冗长吗?这就迎来了我们的主角:shell 语言。,让我们来看看对于 shell 而言怎么实现上面的需求:删除占用内存最多的两个进程。,shell-libs.sh:,当做完这几步初始动作后,我们要实现需求只需要执行下面命令(执行函数)即可。,函数库很多,但最重要的是,我们的初始动作只需要做一遍,一劳永逸!,其实不只是做一个常用命令的封装,我们还可以做到。,好了,好处显而易见,我们现在对于 shell 有啥念想?兄弟姐妹们,学它!,诱惑了这么久,还是来给个定义吧:shell 是一个命令行解释器,它为用户提供了一个向 Linux 内核发送请求以便运行程序的界面系统级程序;用户可以用 Shell 来启动、挂起、停止或者编写一些程序;Shell 还是一个功能相当强大的编程语言,易编写,易调试,灵活性较强,是解释执行的脚本语言,在 Shell 中可以直接调用 Linux 系统命令。,对于上面【传递进程数 n,杀死占用内存排名前 n 位进程】案例而言。,ps 命令查找与进程相关的 PID 号:,sort 对内容根据指定列进行排序。,head 只显示前指定行的数据,获取默认前 10 行数据。,awk 数据处理神器,这里用于获取第二列(PID,进程 id)。,乱入结束,让我们开始叭!,语言大同小异,核心不过【变量、运算、语句、函数、框架】,shell 也是门语言,所以我们也会根据这个脉络进行学习。,但 shell 又有所不同,因为它的出现强依赖【unix】,unix 的哲学:一条命令只做一件事情;为了组合命令和多次执行,最先是分号;用于同行组合,但不利于展示,于是出现了 shell 脚本文件,用来保存需要执行的命令,所以有别于其他语言又会出【环境变量、配置文件等等概念】,也强依赖 unix 的各个命令,这点是需要贯彻整个 shell 学习脉络的。,注意:本文不会过多的牵扯 linux 的知识,awk、xarg、print 等等等,小伙伴放心,我们学习最核心的语言逻辑,至于工具,多用即可,放心食用。,命令解释器,用于解释用户对操作系统的操作,命令解释器有很多种,具体可见:(默认的是 bash,其中的 a 是指 again,意思是汇总其他 shell 解释器的优点,重写实现)。,
,BIOS - MBR - BootLoader(grub) - kernel - systemd - 系统初始化 - shell。,unix 的哲学:一条命令只做一件事情。,为了组合命令和多次执行,于是出现了 shell 脚本文件,用来保存需要执行的命令。,存在四种执行方式,即变化的量,字母、数字、下划线的组合,且不能以数字开头(shell 变量是弱类型,不区分变量类型)。,非交互式赋值存在四种赋值方式。,注意:变量值如果有空格等特殊字符,可以包含在""或''中。,在 shell 中存在四种引用:单引号、双引号、${}、``。,变量名即对变量的引用,在部分情况下可以缩写为变量名(不产生歧义,比如字符串拼接就不能缩写)。,而查询则可以使用set命令,其会默认查询系统中默认所有已经生效的变量,包括系统变量,也包括自定义变量,结合管道运算符可以精准查询。,举例:查询wzy变量的值,
,删除则是unset命令,使用方式如下:,shell 变量为弱类型并且默认是字符串类型,要想设置变量的类型,可以使用declare命令。,declare 命令用来声明变量类型。,
,举例,将变量设定为整数型从而实现加和,通过配置项-i进行设定。,
,通过配置项-a进行设定。,定义:,
,取第一个值:,
,取第二个值:,
,输出所有:,
,承接上面,此时变量c已经是整型了,我们希望实现取消变量c的类型(即变回字符型),从而实现拼接的效果。,
,通过配置项-r进行设定:,
,此时也可以通过配置项-p查询变量类型。,
,通过配置项-x设置变量为环境变量。,
,由此也可以看到,之前定义全局环境变量的方式export [变量名]其实就是declare -x [变量名]的语法糖。,其中第一条可以使用bash命令创建一个新的 shell 进行测试;第二条就是 export 和 unset 关键字;关键是系统环境变量,重点分析:,环境变量主要根据两个角度进行划分:用户级别是属于系统还是属于用户;shell 级别是属于当前的 shell 还是所有 shell。而这些是通过配置文件进行区分和记录的,不同作用范围和功能的变量分属不同的配置文件中,主要有四个文件/etc/profile、~/.bash_profile、~/.bashrc、/etc/bashrc。系统环境变量的查询:env 和 set。,需要注意的是,加载顺序为:,如果修改了配置文件,是不会立即重新加载的,需要我们重启终端或者执行 source 命令。,在操作系统加载过程中,主要按如下顺序进行加载。,
,而作用范围如下图:,
,其实 expr、let 或者(())都是为了向 shell 声明,我目前在做算数赋值的动作,这也就能理解为什么要把整个式子都放在双圆括号中了。,
,参考文档:,根据程序是否正常执行(程序退出的状态)进行判断。,tesh 命令可以用于检查文件或者比较值,可用于如下功能(可以用man test查看更具体的命令)。,test 测试语句可以简化为[]符号,而[]符号还有扩展写法[[]] ,支持 &&、||、<、>(推荐使用[[]])。,两个字符串是否相等:[str1 = str2] 和 [str1 != str2]。,读取字符串长度是否是 0(空字符串):-z。,实例:,实例:,实例:,实例实现:先判断是不是王志远账户,是则再执行对应文件。,实例实现:先判断是不是王志远账户,是则再执行对应文件。,注意:,实例实现:遍历列表输出。,实例实现:读取命令结果进行取出所有 mp3 文件的文件名(basename [文件路径] [文件后缀])。,实例实现:输出 1-10。,特点:直到输入为非 0 才中止。,实例实现:输出 1-10。,实现死循环。,特点:与 while 相反,直到输入为 0 才中止。,实例实现:输出 1-10。,找出/etc/profile.d 目录下所有可执行文件。,找出/etc/profile.d 目录下所有可执行文件并执行。,找出/etc/profile.d 目录下所有可执行文件并执行。,用于重复命令逻辑的集合,定义:,执行:,实例:,分为内部定义的变量和外部的传参。,调用:,这里有巨坑:,注意点:,其实 shell 的模块化(即函数的导入导出)非常简单,我们知道 shell 会话间的变量是互通的(函数中的 local 变量除外),这时我们只要以当前 shell 会话执行下定义函数的 sh,就能访问到对应的函数了。而如何以当前 shell 执行呢?就是之前讲到的知识:以 source 或者.方式执行 sh 文件。,引入方式很简单。,存在函数库 libs/os.sh。,引入使用时。,linux 系统中存在自带的函数库,地址如下:,在配置文件中也是用了大量的循环判断,可以看/etc/profile或者/etc/.bashrc。,一门语言的出现必然存在其特殊点,java 的 jvm 和面向对象、js 的解释型、python 的自动化等等,shell 也不例外。,cpu 和资源的分配。,当执行如下命令时,系统会进入假死状态。,捕获语句语法如下:,循环监听 15 信号,当此信号被下发时,打印sig 15。,启动之后会首先打印端口口,然后我们执行如下命令像指定进程发送 15 信号。,循环监听 15 信号,当此信号被下发时,打印sig 15。,启动之后我们ctrl+c实现触发。,注意事项:,画一个示意图:,
,
,1 分钟后将在/tmp 目录下创建hello.txt并写入内容hello。,crontab 是根据选项执行对应行为的。,每个用户都有自己的周期性计划任务配置文件,保存在/var/spool/cron/下面,以用户名作为文件名。,每分钟将日期保存在指定文件中。,周一每分钟执行。,周五每分钟执行。,周一和周五每分钟执行。,周一至周五每分钟执行。,7 月 8 日且是周一至周五,每分钟执行。,为了缓解 cron 中一瞬间大量任务并发执行而导致系统压力过大的问题。相关文件。,由四部分组成:,在使用 crontab 管理定时脚本时,如果设定的脚本执行时间间隔较短,例如 5 分钟执行一次,正常情况下,脚本执行耗时 1 分钟,在非正常情况下(如服务器压力较大的情况下,或数据量突然增大),脚本执行时间超过 5 分钟,这时就会造成多个脚本同时执行,严重时甚至拖垮服务器,影响服务器上的其它服务。,当多个进程可能会执行同一个脚本,这些进程需要保证其它进程没有在操作,以免重复执行,这就是 flock 的作用。,通常,这样的进程会使用一个锁文件,也就是建立一个文件来告诉别的进程自己在运行,如果检测到那个文件存在则认为有操作同样数据的进程在工作。,下图是两个终端同时运行这条命令,后执行者会因为抢不到锁而得不到执行,马上退出。,
,当我们单纯的运行多个程序而不需要它们彼此间有互通时,存在如下方式:,而如果需要互通,比如第一个命令的返回传递给第二个命令,就需要用到管道了,管道的本质就是将多个程序进行了一个连接,和信号一样,也是进程通信的方式之一。,注意:因为管道是以子进程方式进行执行的,所以内建命令的执行不会传递给父进程。,重定向的本质就是将文件和输入、输出(包含标准输出、错误输出)进行了一个连接。,多行内容写入。,说了这么多,最后还是要落到写的程度来,【纸上得来终觉浅,绝知此事要躬行】,写自然免不了有问题,当有问题的时候我们就需要一些手段去调试我们的代码了。怎么调呢?对我个人而言经历了三个阶段。,逐一分享啦!,这个很简单,唯一要注意的就是 shell 变量类型导致的奇葩输出,在 shell 中默认变量是字符串类型,而其他类型的输出则有不同,这些就是 的臀部--规定了,踩坑良久,献于诸君。我们来看看我说的那个 vscode 插件支持【一键输出打印语句】,目前支持 js 和 shell。【如需试用可以搜索:weiyi-tools】。,
,set命令用来修改 Shell 环境的运行参数,也就是可以定制环境。一共有十几个参数可以定制,官方手册有完整清单。,使用方式很简单,在脚本的顶部放上 set 命令+对应配置即可。,具体配置如下:,顺便提一下,如果命令行下不带任何参数,直接运行set,会显示所有的环境变量和 Shell 函数。,将下面内容放在脚本顶部可以做到。,补充:其实本人还是喜欢下面这样就好啦,因为我会封装很多函数,如果加上了 e 就会导致中止。,在这,会发现自动化时期其实并没有做到随时随地查看自己想看的运行状态,甚至还会打印很多很多不需要看的内容。有没有一种办法,可以直接图形化的查看当前调试状态下参数的值、卡住程序快照、逐步运行呢?聪明的小伙伴肯定想到了,这不就是 debugger 调试嘛。,js 我们肯定是可以的,shell 呢?其实也可以,只是有几个小要求,这几步的动作原博主写的很赞,我就不赘述了,可见:https://liushiming.cn/article/debug-bash-on-macos.html;唯一有一点补充的就是,记得把 program 替换成${file}(原文复制下面的也可以),这代表要调试当前打开的 shell 文件。,最后,我们来看下效果:,
,直接看效果【如需试用可以搜索:weiyi-tools】。,
,至此,shell 之调试篇,完成。,除此之外的内容,写不动了,到时候另起一文,看下效果吧,对 vscode 插件开发想了解的同学也可以前往我的专栏查看:https://juejin.cn/column/7078626256777904165。,
,救命,内容实在是太多了,而且还有非常非常多踩的坑没有分享【封装shell函数库、vscode智能补全等等等】,开始以为能一文结束,写着写着才发现 shell 的世界浩如烟海,我只是抓住了一个角而已,还好,名字是带你走进这个世界,本文只能作为一个脉络文了,后续会根据本文进行拆分,输出一个专栏。,老规矩,鸡汤一下:,每到一个新世界,都是一片新的美好风景,luck!
© 版权声明
文章版权归作者所有,未经允许请勿转载。