shell bash 是一种解释器、启动器。
将文件中写一些我们常用的命令 如 ll / echo"abcd" echo $$ 然后执行source 文件名称。发现这些命令都执行了 且bash进程号一致。所以说source 是在当前bash进程执行程序(. 文件名称也一样 这时.=source)。所以说bash具有读取文件的能力。
还有一种/bin/bash 文件名 这样虽然也执行但是这种方式是启用子进程完成的 所以进程号不一致。
但是每次如此却有些麻烦 于是这样的写法诞生了直接在文件头部以#!开头后面加上该文件的解释器。如python脚本 上面就要跟python而不是bash了。这样改后想要直接执行文件 还要注意是否有x权限 如果没有执行
chmod +x 文件名 添加权限。
这种文件也就是脚本的本质。解释器的定义+脚本命令。
函数的定义及使用:注意函数就是在当前进程使用。
一、文本流&重定向
Linux一切皆文件,也就是说程序IO流也会以文件形式存在。
例子:查看当前bash进程。在/proc/$$/fd下查看
我们再打开一个bash还是连接当前虚拟机。
我们发现每多一个bash连接 /dev/pts下就会多一位,这其实就是client与server对应的各自的socket连接。而前面的0、1、2分别代表该client的输入流、输出流、错误输出
我们 先在前者中执行 exec 9>& 1 然后在执行exec 1> /dev/pts/1/1
然后我们发现,前者的命令的输出信息居然会在后者屏幕中体现
这就是重定向的例子。也是Linux强大之处之一。再比如我将命令打印到屏幕的信息写入文件怎么写入呢?
ls -l 1> test.txt 执行完成后信息成功写入。此处注意 1、重定向中 >会内容覆盖 >>才是内容追加 >&重定向到流。2、可以多个命令输出到一个文件如 ls -l / /bin 1> test.txt 3、查看错误信息,就将1改为2即可 4、以上都是重定向到文件,流重定向到流
ls -l / /aaa 1>test.txt 2>& 1 注意顺序 顺序不可变 5、重定向不是命令。
输入:read 阻塞输入。read 命令对换行符敏感。
三个<<<后面接字符 转成输入流 两个<< 接首尾呼应的命令间的数据转成输入流 一个< 后面接文件
案例:不安装浏览器,访问百度 并读回来它的主页。
1、简历与百度的cdsocket连接 exec 8<> /dev/tcp/www.baidu.com/80
2、echo -e "GET / HTTP/1.0\n" 1>& 8 发送请求头
3、cat 0<& 8 打印响应信息 如图
二、变量
本地变量:当前shell(线程)拥有的 name=aaa 。
局部变量:local限定变量定义,只能在函数内部出现。
位置变量(参数):文件内部引用 所引用的是外部执行时传入的参数
注意正确取值是${11} 取超过过一位数的顺序值必须加{}
管道注意点:所以说,管道两侧都是新开子进程。更要注意$$的解释优先级高于管道,$BASHPID则低于管道
$? 上一个命令的执行状态 0代表成功
环境变量:父进程环境变量对子进程可见但其中一方改变互不影响。pstree可查看父子进程的层次关系。exit退出当前进程。
将变量用export定义 代表环境变量。
ps.睡觉!明天再写
三、引用&命令替换
双引号:弱引用,参数扩展(既双引号中比如有$会先取值,还有,参数中间有空格可以使用此来达到使空格前后成为整体的一个参数的效果)
单引号:强引用,不可嵌套。单引号内部的无论什么都不会先被bash解析。
例:
花括号不能被引用,因为花括号是bash七步扩展之一。例:
命令执行前引用会删除,若想加引号需用转义。例:
命令替换:
反引号:将反引号内部的执行完再与其他的命令一起使用。例:
$(命令):与反引号功能一致,由于命令替换可以嵌套,而此种方式嵌套时看起来比较直观;例:
四、退出状态&逻辑判断
退出状态:程序执行完后,可以用echo $? 来获取程序的退出状态,一般0为成功,脚本的状态自定义。
逻辑判断:&& || 示例:
五、表达式
算术表达式:
1、定义a=1 b=2 let c=$a+$b 则对a与b的值求和。也可以写为 c=$((a+b)).变量自增写法:((a++)).例:
条件表达式
1、test -a 文件名 该文件是否存在。-a换成-d代表文件是否为目录。命令执行完毕的状态值来判断(可用于和$? 或者直接跟逻辑判断符使用)
2、test -z 字符串: -z代表当字符串为空返回0.-n代表不为空返回0.
3、test 数值1 -gt 数值2 (另一种表达方式:[数值1 -gt 数值2]):表示数值1>数值2则为真(返回0)。-eq表示等于.-ne表示不等于。-ge大于等于。-lt表示小于。-le表示小于等于。
注意[] 左中括号是个命令,所以左中括号一定要接空白符、右括号前也要空白符才可。
练习:写一个脚本,执行命令时输入一个参数,会创建这个参数名的用户、且密码与用户名一致、静默运行脚本、避免程序捕获用户接口、程序自定义输出信息。
1、简易版本:主代码第一句通过重定向让命令静默。第二句passwd --stdin 用户名 输入流实现passwd命令避免捕捉用户接口。同时命令静默。最后打印提示信息。
2、自定义一些输出信息及返回状态:主代码第1句判断参数是否为一个,不为一个进行错误输出,并定义执行状态为1.第二句判断用户是否存在。不存在执行正常代码。存在则错误输出并定义执行状态2.
3、exit为退出当前bash进程。如果使用source来执行 会将交互界面进程退出。所以还是使用./来执行。注意是否有x权限。(chmod +x 文件)
4、当然还有很多小问题。比如非root用户执行此命令会出现问题。这里点到为止不多纠结
六、流程控制
1、if:if开头fi结尾,具体格式:if 命令;then 命令;elif 命令;then 命令;else 命令;fi
2、for循环:正常for循环及增强for循环。
注意:从循环中看$*与$@的区别:脚本执行情况:
由此可见:1、$@ $*打印时看起来一致 但是$@的结果是个以空格切割的列表,后者则是与空格整体为字符串。循环使用时注意这点。还有bash是对空格敏感的,所以$@前后要加引用,否则也不代表列表
3、while循环;不赘诉,如例:
练习 1:写一个脚本,对于给定的参数是一个路径,找出路径下最大的文件。
注意一个点:加强for循环时 words会以空格、换行等将整体切开作为列表,如果想单纯按行遍历(既只以换行符切开从而得到words),需要改变IFS变量。而且换行符的获取使用 $'\n'。
完成脚本代码:
注意:1、改变IFS,在程序结尾要记得改变回来以免影响其他程序使用。
练习 2:循环遍历文件中的行,并且对行数打印。尽量使用所学知识。
几种写法:。
最后,shell bash解析输入命令的七步扩展:
1、解析花括号。参考命令 mkdir -p abc/{bcd,cde}
2、解析波浪线。cd ~god
3、解析变量或参数。$$、$?、$(){}
4、命令替换。ls -l `echo $PATH`
5、算数扩展。num=$((3+4))
6、words拆分。通过$IFS
7、路径 * ?
8、引用删除。既引号去除
9、重定向
ps.Linux学习结束。后面会补上Linux的前几篇