Linux命令行与脚本编程大全:https://pan.baidu.com/s/1WaIdrL4H8UmVBDdqN9ogtg
linux
- Linux系统的组成:linux系统可以包含以下四个部分,Linux内核、GNU工具、图形化桌面环境、应用软件;
- Linux内核的功能:Linux内核主要负责以下四种功能,系统内存管理、软件程序管理(进程管理)、硬件设备管理、文件系统管理;
- 内存管理:主要是物理内存管理和虚拟内存管理,内存被分成页面进行管理;
- 进程管理:内核创建第一个进程init,其他进程由该进程创建;自启动进程由/etc/inittab文件管理,有的用/etc/rcX.d目录管理,不同的运行级别运行不同级别下的进程;
- 硬件设备管理:内核充当应用程序和硬件驱动之间的中间人,硬件驱动分两种,编译进内核的设备驱动代码和可插入内核的设备驱动模块;硬件设备被当作设备文件来操作,分为字符型设备文件、块设备文件、网络设备文件;
- 文件系统管理:
- GNU工具:命令行工具coreutils软件包,用于文件处理的工具、操作文本的工具、管理进程的工具;
基本bash命令
- shell:/etc/passwd文件定义了账户登录时启动的shell类型;
- man:查看命令工具的具体说明
- 文件系统:第一块硬盘被称为根驱动器,包含虚拟目录的核心,其他目录都从这里开始;根驱动器上有一些特别的目录,称为挂载点,这些挂载点会连接到其他驱动器,即该目录下的所有文件是存在其他驱动器上的;
- 浏览文件系统
- 文件列表:ls -F 目录名后面有斜线,-a 展示所有文件 包括隐藏文件;-R 递归展示子目录下的所有文件;-l 长列表 详细信息;可以进行简单文本匹配的字符串 ? * [] 范围 ! 排除 ls -l [!a]* 不以a开头的文件;
- 处理文件:
- touch 创建空文件 同时也可以用来更新修改时间;
- 复制 cp:cp origin destination,destination可以是文件(修改文件名称)也可以是目录(同名文件),-i 强制询问是否需要覆盖同名文件;-R 递归复制整个目录到另一个目录中 cp -R scripts/ mod_scripts/ 将origin目录中的所有文件复制到destination目录下;也可以使用简单通配符;
- 链接文件:不用完全创建新的文件副本,就像快捷方式;
- 符号链接:符号链接是一个新文件指向目标文件路径,符号链接文件和源文件是两个不同的文件;ln -s origin linkfile 为origin文件创建linfile 符号链接;
- 硬链接:创建虚拟文件,和源文件是同一个文件node号相同;去除-s选项;
- 移动、删除:mv,rm -i 强制提示;
- 目录操作:创建 mkdir -p,删除空目录 rmdir,rm -r 删除目录;
- 查看文件内容:
- 查看文件类型:file
- 查看文件内容:cat -n 添加行号 -b 只有文本的行才有行号 -T 忽略制表符,more,less,tail,head;
- 查看进程:
- ps:常用的e 所有进程 f 完整格式,输出格式,UID 启动进程的用户uid、PID 进程id、PPID父进程id、C cpu的利用率、STIME 进程启动时的系统时间、TTY 启动的终端设备、 TIME 运行进程需要的累计CPU时间、CMD 启动的进程名称;-l 添加更多参数;
- 实时检测 top:
- 第一行 显示系统概况:当前时间、系统运行时间、登录用户数、系统的平均负载 1 分钟内 5分钟内 15分钟内,平均负载越高 系统越繁忙 就需要检查什么程序占用着cpu;
- 第二行 进程概况:任务总数、运行、休眠、僵化(进程完成但父进程没有响应)
- 第三、四、五行:cpu、内存、交换分区 使用情况;
- 最后一部分:进程的详细列表,VIRT 进程占用的虚拟内存总量、RES 进程占用的物理内存总量、SHR 进程和其他进程共享的内存总量、S 进程状态(D 可中断的休眠状态、R 运行状态、S 休眠、T 跟踪或停止、Z 僵化);
- q 退出,d 修改轮询间隔,f 允许选择对输出进行排序字段;
- 杀死进程:kill 发送进程信号 支持进程id,但必须时root用户或进程的属主;killall 支持进程名和通配符;
- 监测磁盘空间
- 挂载,Linux我呢见系统将所有的磁盘都并入一个虚拟目录下,使用新的存储媒体前需要将它放到虚拟目录下,这个操作被称为挂载;mount 输出当前系统上挂载的设备列表,mount -t type device directory,设备文件名、挂载到虚拟目录的挂载点、文件系统类型、已挂载媒体的访问状态,mount -t vfat /dev/sdb1 /media/disk;-o 可以添加特殊选项 ro rw;
- 卸载:umount [directory | device]
- df:查看所有已挂载磁盘的使用情况;输出格式 设备文件位置、能容纳多少个1kb块、已使用的块、剩余块、已用的空间比例、设备挂载到的挂载点;-h 给空间添加单位;
- du:查看特定目录的磁盘使用情况,用来判断系统上某个目录下是否有大文件,输出格式为磁盘块; -h 易读模式,-s 显示每个输出参数的总计;
- 处理数据文件:以上命令很多都输出大量数据,使用以下命令可以对数据进行筛选;
- 排序 sort:默认按照文本排序,-n 将文本转成数字执行排序,-M 将文本解释为时间戳,还有其他选项 -r 反序,-m 合并两个已排序数据文件合并,-o 将排序结果输出到指定文件中,-b 忽略起始的空白,-k 排序重POS1开始 如果指定了POS2 到POS2结束,-t 指定字段分隔符;sort -t ':' -k 3 -n /etc/passwd 数据按:分隔,并按第三个字段(用户id的数值排序);du -sh * | sort -nr 查看目录下哪个文件占用空间最多
- 搜索数据 grep:grep [options] pattern [file];-v 反向搜索 grep -v t file1 搜索文件名中不含t的文件;-n 显示匹配模式的行所在的行号 grep -n t file1;grep -c t file1 显示有多少行还有匹配的模式;-e 添加多个匹配模式;grep -e t -e f file1 显示含有字符t或字符f的所有行;pattern可以使用正则表达式;
- 压缩文件:gzip 压缩文件 可以指定多个文件名 使用通配符(每个文件都压缩一遍),gzcat 查看压缩文件的文本内容,gunzip 解压文件;
- 归档数据:将多个文件合成一个文件,tar function [options] object1 object2;
- function:-A 将一个已有tar归档文件追加到另一个tar归档文件,-c 创建一个新的归档文件,-r 将一个文件追加到已有的tar归档文件末尾,-t 列出归档文件中的内容,-x 从归档文件中提取文件;
- 常用选项:-C dir 切换到指定目录,-f file 将输出结果到文件,-j 将输出重定向给bzip2命令来压缩内容,-z 输出重定向给gzip命令来压缩内容;tar -cvf test.tar test1/ test2/;将test1、test2目录中的内容添加到test.tar中;tar -tf test.tar 列出test.tar中的内容;提取内容 tar -xvf test.tar;
shell
- shell有父子关系,可以在shell中启动另一个shell,-c string 从string中读取命令并进行处理,-i 启动一个能接受用户输入的交互shell,-l 以登录shell形式启动,-r 启动一个受限shell 用户会被限制在默认目录中,-s 从标准输入中读取命令;exit退出shell;
- 进程列表:通过;号隔开多个命令可以形成命令列表,添加括号形成进程列表,生成一个子shell来执行对应的命令;子shell相当于一个进程 开销太大;
- 后台模式:在命令末尾添加 & 创建子shell并让子shell在后台运行,jobs显示后台作业信息 -l 显示更多信息;可以将进程列表放入后台进程中;
- 协程:在后台生成一个子shell,并在这个子shell中执行命令,coproc 命令;jobs可以显示后台协程作业,coproc my_name (进程列表);
- shell内建命令:内建命令不会生成新shell,外部命令会生成子shell;type 命令,识别命令是否内建;
- 命令历史:history,!命令编号;历史在.bash_history中;
- 环境变量:全局和局部,env或printenv输出所有全局变量;set 显示局部变量和当前进程的局部变量;用户自定义变量 name=value 不要有空格 $name 得到name变量的值,通过export name 将用户变量name输出到当前shell全局变量,所有的子shell都可以获得父shell的全局变量,但是zishell修改不会影响到父shell;unset删除环境变量;shell有很多默认的shell环境变量;设置PATH环境变量;登录shell时,系统从以下几个启动文件中读取命令,并设置环境变量 /etc/profile home/.bash_profile home/.bashrc home/.bash_login home/.profile,etc/下的文件设置的环境变量每个用户都会有,用户自定义的环境变量再用户家目录下;
- 数组变量:给某个环境变量设置多个值,可以把值放在括号里,值与值之间用空格分隔;mytest=(one two three),访问mytest[1],mytest[*]获取整个数组变量;
文件权限
- 用户账户信息在/etc/passwd,除了用户账户 里面还有许多后台服务专用的系统账户;信息包括 用户名 密码 UID GID 备注 home目录位置 默认shell;密码通常保存在另一个文件中/etc/shadow 只有特定程序才能访问这个文件,很多程序都可以访问/etc/passwd,信息包括 登录名 加密的密码 上次修改密码后过去的天数 多少天后修改密码 多少天后必须更改密码 过期前多少天提醒用户修改密码 密码过期多少天后禁用账户 用户账户被禁用的日期 预留的字段
- 添加用户:useradd有很多默认参数创建用户,-D可以查看这些默认值 包括home目录 是否禁用账户 默认shell;通过添加参数可以覆盖默认的参数值 -m会创建家目录 -d homedir 创建指定的家目录 -g group 指定组 -G group1 gourp2 指定附加组 -r 创建系统账户 -p passwd 指定默认密码 -s shell 指定默认登陆shell;-D 后面跟上指定值可以修改创建新账户的系统默认参数;useradd -D -s /bin/tsch -g defaultgroup;
- 删除用户 userdel:-r 删除家目录;
- 修改用户:usermod passwd 修改已有用户的密码 chpasswd 跟新密码 chage 修改密码的过期日期 chfn 修改用户账户的备注信息 chsh 修改默认登陆shell;
- usermod:修改passwd文件中的大部分字段,-c 修改备注 -e 过期日期 -g 默认登陆组 -l 登录名 -L 锁定账户 -p 密码 -U 解锁账户
- passwd和chpasswd:chpasswd可以从标准输入中自动读取登录名和密码对(用冒号分隔)列表;chpasswd < users.txt;
- 组:用来账户之间共享资源;/etc/group
- 创建新组:groupadd groupname,只能将通过usermod来将用户加入组中;usermod -G groupname user;
- 修改组:groupmod -n newgroupname oldgroupname 修改组名;
- 默认文件权限:umask设置默认权限;umask 026 设置权限掩码,umask显示默认权限 0026 第一位时粘着位
- 改变权限:chmod options mode file;chmod [ugoa] [+-=] [rwxXstugo];-R 递归作用到文件和子目录;
- 改变所属关系:修改属主或属组chown options owner.[group] file;chown dan.shared newfile或 chown dan. newfile;chgrp shared newfile修改文件组;
- 共享文件:粘着位,SUID 当文件被用户使用时,程序以文件属主的权限运行;SGID 对文件来说 程序会以文件属组的权限运行,对目录来说 目录中创建的新文件会以目录的默认属组作为默认属组;粘着位 进程结束后文件还驻留在内存中;
chgrp shared dir
chmod g+s dir
之后任何用户在该目录中创建的文件,文件的默认属组和该目录相同;
文件系统
- 文件系统演进过程:
- ext文件系统,使用虚拟目录来操作硬件设备,在物理设备上按定长的块来存储数据;采用名为索引节点的系统来存储虚拟目录所存储文件信息,索引节点系统在每个物理设备中创建一个单独的表称为索引节点表来存储这些文件的信息,存储在虚拟目录中的每一个文件在索引节点表中都有一个条目,条目包含的数据有文件名、文件大小、文件属组、属主、访问权限、指向存有文件数据的每个硬盘块的指针;使用唯一数值称为索引节点号来引用索引节点表中的每个索引节点;
- ext2文件系统:ext文件系统的限制在于每个文件不能超过2g;ext2文件系统拓展了节点表格式添加创建时间、修改时间、最后访问时间,能够容纳更大的文件;改变了文件在数据块中存储的方式,解决数据块的碎片化导致的文件系统的性能下降的问题,ext2文件系统按照组分配磁盘块来减轻碎片化的问题;问题在于索引节点和硬盘写入之间不同步的问题;
- 日志文件系统:先将文件的更改写入到临时文件中,成功后再写到存储设备和索引节点中,再删除对应的日志条目;有三种使用日志的方式,数据模式、有序模式、回写模式;最安全的方式是索引节点数据和文件数据写入日志;
- ext3文件系统:添加了命令行选项设定日志模式;
- ext4文件系统:支持数据压缩和加密,支持区段;区段在存储设备上按快分配空间,但在索引节点表中只保存起始块的位置,更节省空间;引入预分配技术,为文件预先分配所有需要用到的块;
- reiser文件系统:在线调整已有文件系统的大小,尾部压缩 将一个文件的数据填进另一个文件的数据块的空白空间;
- JFS文件系统:采用有序日志;
- XFS文件系统:采用回写模式;
- 写时复制文件系统:在修改数据时,使用克隆或快照,修改过的数据并不会直接覆盖当前数据,二十放入文件系统的另一个位置上;
- ZFS文件系统:写时复制的一种
- BRRF文件系统:B树文件系统
- 操作文件系统:
- 创建分区:fdisk,在存储设备上创建分区来容纳文件系统,分区可以是整个硬盘,也可以是部分硬盘;fdisk /dev/sdb;硬件设备/dev/sdx /dev/sda sdb sdc来对应各个驱动器,/dev/hdx;通过交互式命令来创建,d 删除分区、n 添加新分区、p 显示存储设备的详细信息 w 将修改保存在存储设备上;可以按照主分区或逻辑分区创建,一个存储设备可以有一个主分区和多个逻辑分区;
- 格式化分区:格式化分区工具有很多个,可以同type去试,如mkfs.ext4 /dev/sdb1格式化分区 sdb1 是sdb驱动器上的第一个分区;
- 挂载:挂载分区到虚拟目录下的某个挂载点;mount -t ext4 /dev/sdb1 /mnt/my_partition;
- 逻辑卷管理:支持动态地添加存储空间;逻辑卷管理器LVM
- 布局:硬盘称为物理卷PV,每个物理卷都会映射到硬盘上特定的物理分区;多个物理卷可以组成一个卷组;逻辑卷管理系统将一个卷组视为一个物理硬盘;逻辑卷为Linux提供了创建文件系统的分区环境;一个硬盘对应一个物理卷,多个物理卷形成一个卷组,在卷组上创建逻辑卷,一个逻辑卷就是一个分区,给逻辑卷格式化文件系统,再给逻辑卷挂载到虚拟目录上,可以将未用的存储空间添加到卷组中,然后在卷组的新空间上添加新逻辑卷或者拓展已有的逻辑卷;
- LVM:提供快照功能和条带化,快照用于备份数据,条带化是将数据分散到多个物理设备上,有助于提高硬盘性能;镜像,作为一个实时更新的逻辑卷的完整副本,快照不是实时更新的,镜像会使得在写操作时写入两次数据,一次写道逻辑卷 一次写道镜像中,会降低性能;
- 创建物理卷:fdisk创建分区,只不过分区类型为8e,或者通过t来修改分区类型;
- 创建实际的物理卷:pvcreate /dev/sdb1 将物理卷分区转换成LVM的物理卷;
- 查看创建的物理卷信息:pvdisplay /dev/sdb1
- 创建卷组:vgcreate vo1 /dev/sdb1 将物理卷创建为一个卷组,卷组名为vo1;
- 查看卷组信息:vgdisplay vo1;
- 创建逻辑卷:lvcreate -l 100%FREE -n lvtest vo1,-l 指定使用卷组空间的百分比来创建逻辑卷;-L 指定空间大小 20M;
- 查看逻辑卷:lvdisplay vo1;
- 为逻辑卷格式化文件系统:mkfs.ext4 /dev/vo1/lvtest 为vo1卷组的lvtest逻辑卷格式化成ext4文件系统;
- 挂载:mount /dev/vo1/lvtest /mint/my_partition
- 修改LVM:vgchange 激活或禁用卷组 vgremove 删除卷组 vgextend 将物理卷添加到卷组中 vgreduce 从卷组中删除物理卷 lvextend 增加逻辑卷大小 lvreduce 减小逻辑卷大小;
安装软件程序
- 包管理工具PMS:red hat 对应的有yum urpm zypper
- 列出已安装包:yum list installed, yum list packagename,查看特定文件所属的软件包 yum provides filename;
- 安装:yum install packagename;本地安装 yum localinstall packagename.rpm;
- 更新:yum list updates;yum update packagename;yum update;
- 卸载:yum remove packagename;yum erase packagename;前者卸载,后者包括所有相关配置文件;
- 处理碎花的包依赖关系:yum clean all; yum delist packagename, yum update --skip-broken;
- 软件仓库:yum repolist; 仓库文件 /etc/yum.repos.d
- 源码安装:解压tar.gz文件,通过阅读readme文件,了解所有配置选项,./configure检测依赖关系,make编译源码,make install安装软件;
编辑器vim
- 移动:h j k l;ctrl + f 下翻一屏,ctrl + b 上翻一屏,G 最后一行,n G 移动到第n行,gg 第一行;
- 保存和退出:w filename 另存到filename文件中;wq保存退出,q!强制退出;
- 模式:普通模式和插入模式;
- 编辑数据:x 删除光标所在位置的字符,dd 删除整行,dw 删除单词,d$删除到行尾,u 撤销,a 追加;
- 复制粘贴:编辑的数据会在缓冲区中,通过p可以取出缓冲区中的数据;yy 复制整行 yw复制单词 y$ 复制到行尾;
- 可视模式v,进入可视模式后按下y复制文本,p粘贴文本
- 查找和替换:/ 进行查找,按n可以查找下一个;s/old/new 替换old;s/old/new/g 替换所有old;n ms/old/new/g 替换行号从n到m;%s/old/new/g 替换文件;%s/old/new/gc替换所有old,每次都提示;
shell脚本
- 同一行可以写入多条命令,用分号隔开;echo 显示消息;单引号和双引号表示字符串,-n 取消末尾换行;
- 变量:使用变量对应的值,美元符,在字符串中美元符需要转义 key=this; echo 'this is $key';或者${}
等号两边不能有空格,变量值默认为字符串
var1=test
变量值里面需要有空格则用单引号或双引号括起来,美元符解释为变量值,需要转义成普通美元符字符串
var2='this is a varible \$var1'
echo $var2 输出 this is a variable $var1
var3='this is a variable $var1'
echo $3 输出 this is a variable test
- 命令替换:将字符串解释为shell命令,输出命令的输出结果;使用反引号 ` ,或$()
test1=`date`
test2=$(date)
echo $test1 输出 mon jan 31
echo $test2 输出 mon jan 31
- 重定向输入和输出:常用是将命令的输出结果重定向到另一个位置(如文件),或将文件的内容重定向到命令输入; 覆盖输出,command > outputfile;date > test6.txt;追加输出 command >> test7.txt,date >> test6;输入重定向, command < inputfile,wc < test6 统计文本的行数 文本词数 字节数;*内联输入重定向,可以通过在命令行中输入数据向命令行输入数据,command << marker,marker作为输入数据的结束符号;
$ wc << EOF
> test string 1
> test string 2
> test string 3
> EOF
- 管道:将一个命令的输入作为另一个命令的输出
-
执行数学运算
- expr命令:能识别少数运算符,不能识别星号,需要使用命令替换将命令的输出结果赋值给变量,test=$(expr 5 * 2);
- 方括号:可以执行更多运算,将方括号中的内容解释为数学运算内容;var1=5 var2=6 var3=12 var4=var1 * (var3)];不支持浮点运算;
- bc命令:专门用于复杂数学运算的命令,交互式命令;交互式的scale用于设置结果的小数点位数,默认为0;-q 忽略掉欢迎信息;需要使用命令替换才能在脚本中使用bc命令;
var1=$(echo 'scale=4; 3.455 * 2 | bc'); echo $var1 输出 6.910 var7=$(bc << EOF scale=3 var1= (12 * 3) var2= (3.2 * 4) var3= ($var1 * $var2) var3 + var2 EOF) echo $var7 输出var3 + var2的结果
- 查看退出状态码:$? 查看上个已经执行的命令的退出状态码,成功为0;
条件语句
- if: 其中的condition可以是命令,如果命令的退出码是0 表示true 其他位false;condition可以有多个命令,所有命令的退出状态码都为0才能为true;
if condition
then
command
fi
if grep 'test' /etc/passwd
then
echo 'it worked'
elif grep 'test1' /etc/passwd
echo 'it still worked'
else
echo 'it is not work'
fi
grep 找到了输输出0,没找到输出非0
- 条件测试
- test命令:test condition,不写condition则返回false;判断变量值是否有内容,有内容返回true,没内容包括空字符串的情况;
variable='' if test $variable then echo 'variable is not empty' fi
- 方括号测试:第一个方括号之后和第二个方括号之前必须添加一个空格;
if [ $variable ] then echo 'variable is not empty' fi
-
三类条件测试:数值比较、字符串比较、文件比较;
- 数值比较:n1 -eq n2, n1 -ge n2, n1 -gt n2, n1 -le n2, n1 -lt n2, n1 -ne n2;不能用来测试浮点
if [ $var1 -ne $var2 ] then echo 'var1 is not equal to var2' fi
- 字符串比较:str1 = str2, st1 != str2, str1 < str2, -n str1 是否非0, -z str1 长度是否为0;大于小于符号需要使用转义符;
if [ -n $var1 ] then echo 'var1 is not equal to var2' fi
- 文件比较:-d 测试一个路径是否是一个目录,-e 测试路径是否存在,-f 测试路径是否是文件,-r 测试路径是否可读,-s 测试是否存在并且非空,-w 测试存在并可写,-x 测试存在并可执行,-O 测试存在并属于当前用户,-G 测试存在并属于当前用户的组,file1 -nt file2 检查file1是否比file2新,file1 -ot file2 比旧;
file1=/home/root/file1 file2=/home/root/file2 if [ $file1 -nt $file2] then echo 'newer' fi
- 复合条件测试:&& ||
if [ -d $HOME ] && [ -w $HOME/testing ] then echo 'the file exist and can be written' fi
- 用于数学表达式的测试:双括号
var1=12 if (( $var1 ** 2 > 90 || $var1 ** 2 < 25 )) then echo 'tesst succeed' fi
- 用于模式的字符串的测试:双中括号,可以使用正则表达式
if [[ $USER == r* ]] then echo 'hello $USER' fi
- case命令:可以使用模式匹配
case variable in
pattern1 | pattern2) command1;;
pattern3) command2;;
*) default;;
esac
case $USER in
rich | bariaria)
echo 'welcome user1'
echo 'welcome user2'
;;
jessica)
echo 'welcome user3'
;;
*)
echo 'welcome user default'
循环指令
- for命令:有特殊符号 需要转义或用引号;循环默认用空格分隔每个单项,如果数值有空格则需要用引号解决;常用方式是用命令替换解析命令的输出结果
for var in list
do
commands
done
list='I "don't" know what\'ll happen'
list=$list' another'
for test in $list
do
echo 'for test $test'
done
for a in $(cat $file)
do
echo $a
done
- 更改字段分隔符:循环指令的分隔符默认为空格、制表符、换行符,脚本中可以使用IFS环境变量来修改;
IFS=$'\n'
for state in $(cat $file)
do
echo 'visit $state'
done
这里只对换行符进行分隔
- 指定多个换行符:IFS=$'\n':;",使用换行符、冒号、分号、双引号作为分隔符;
- 使用通配符读取目录:可以有多个通配符
for file in /home/rich/test/* /home/rich/badtest
do
if [ -d '$file' ];then
echo '$file is a directory'
else
echo '$file is a file'
fi
done
if条件判断中文件名可能有空格,需要将file变量给引起来才行,-d选项后面的变量不能有空格
- while命令:可以有多个测试命令,以最后一个测试命令为准
while condition
do
command
done
while echo $var1
[ $var1 -ge 0 ]
do
echo 'this is inside'
var1=$[ $var1 - 1 ]
done
多个命令需要换行
- until命令
until test
do
command
done
- 控制循环:continue, break n 跳出多个循环体;
- 重定向循环输出和输入:在done命令后进行重定向
重定向输出
for file in /home/rich/*
do
if [ -d '$file' ];then
echo '$file'
else
echo "'$file' done"
fi
done > output.txt
重定向输入
input='users.csv'
while IFS=',' read -r userid name
do
echo 'add user $userid'
useradd -c '$name' -m $userid
done < '$inupt'
在done后面添加重定向输入,使用read指令读入数据,读入到两个变量里面;
其他
- 处理用户输入:命令行参数 # 存储变量参数个数;@存储整个命令行,命令行作为一个数组存储;shift命令变量命令行,将第一个变量删除,删除后不可恢复和访问,同时所有其他变量向左;
$*和$@
count=1
for param in '$*'
do
echo 'parameter #$count=$params'
count=$[ $count + 1 ]
done
count=1
for param in '$@'
do
echo 'parameter $count=$params'
count=$[ $count + 1 ]
done
./script one two three
输出结果为
parameter #1=one two three
parameter #1=one
parameter #1=two
parameter #1=three
shift命令
while [ -n '$1' ]
do
echo 'parameter #$count=$1'
count=$[ $count + 1 ]
shift
done
- 处理选项:带破折号的选项通常作为功能选项,有的带参数,有的不带参数,通过case和shift命令来实现;
- getopt命令提供合并选项,getopt optstring parameters,optstring定义有效的命令行字母 有效选项字母需要的参数值,在需要参数值选项字母后面添加一个冒号,如 getopt ab:cd -a -b test1 -cd test2 test3 定义了无参数功能选项a c d 带参数选项b 带参数选项cd;
set -- $(getopt -q ab:cd "$@") while [ -n "$1" ] do case "$!" in -a) echo "found the -a option";; -b) param="$2" echo "found the -b option, with parameter value $param" shift;; -c) echo "found the -c option";; --) shift break;; *) echo "$1 is not an option";; esac shift done count=1 for param in "$@" echo "parameter #$count: $param" count=$[ $count + 1 ] done ./test.sh -a -b test1 -cd test2 test3 test4 输出结果为: found the -a option found the -b option with paramter value 'test1' found the -c option parameter #1: 'test2' parameter #2: 'test3' parameter #3: 'test4'
- getopts:用法相同,定义了两个环境变量OPTIND 保存了参数列表中getopts正在处理的参数位置,OPTARG用来保存选项后面所跟的参数;
while getopts :ab:c opt do case '$opt' in a) echo "found the -a option";; b) echo "found the -b option, with value $OPTARG";; c) echo "found the -c option";; *) Unknow option:$opt esac done shift $[ $OPTIND - 1 ] count=1 for param in "$@" do echo "parameter $count: $param" count=$[ $count + 1 ] done ./test20.sh -a -b test1 -d test2 test3 test4 输出: found the -a option found the -b option, with value test1 found the -d option parameter 1: test2 parameter 2: test3 parameter 3: test4
- 获取用户输入
- read:read name,从标准输入中获取一个输入并存在name中,
- read -p "please enter:" age,在输入前添加一段文字作为提示符;可以输入多个变量用空格隔开 多余的输入全部给最后一个变量;不写变量则将输入全部存在环境变量REPLY中;
- -t指定输入等待的时间,超时则返回一个非零退出码;
- -n1 n和1一起使用表示从输入中只获取一个字符;
- -s可以避免输入的信息显示在屏幕上 用于输入密码;
- 从文件中读取,可以一次读取一行
count=1 cat test | while read line do echo "line $count: $line" count=$[ $count + 1 ] done echo "finished" cat test this is line1 this is line2 ./test28.sh line 1: this is line1 line 2: this is line2 line 3: this is line3
输入和输出
- 文件描述符:linux用文件描述符来标识每个文件对象,三个标准文件描述符,0 STDIN 标准输入 用 < 标识重定向输入、1 STDOUT 标准输出 用 > 标识重定向覆盖输出 >> 标识重定向追加输出、2 STDERR 标准错误;很多命令如果没有指定输入文件的话都默认使用标准输入 如cat,cat < testfile;用数字代替文件描述符,&文件描述符的形式代表文件描述符所关联的文件 如 1>&2;
- 重定向:描述符加重定向符号 ls -al badfile 2> test4 1> test5 将错误文件描述符重定向到test4文件中;&>test 重定向标准文件和错误文件;
- 在脚本中重定向:echo "error direct" >&2;
- 永久重定向:每次都用 >&2会很繁琐,可以使用一次性的方式;exec 1>testout 接下来的输出全部输出到testout文件中;
- 脚本中重定向输入:exec 0< testfile
exec 0< testfile
count=1
while read line
do
echo "line #$count: $line"
count=$[ $count + 1 ]
done
- 创建输出文件描述符:使用exec命令给输出分配文件描述符;
exec 3>test.out
echo 'this will display on the monitor'
echo 'this will display in the file' >&3
- 重定向是文件描述符和输出文件的联系,可以将任意文件联系到一个文件描述符,也可以将当前文件描述符关联到的文件替换为其他描述符关联到的文件,如exec 3>&1 将文件描述符1的文件关联到文件描述符3上,但是1的关联到的文件仍然是monitor,1>testfile, 1>&3;
- 创建输入文件描述符:输入文件描述符同理,也是将描述符和文件关联,从文件中读取数据;exec 6<&0,exec 0 < testfile,exec 0<&6;
- 创建读写文件描述符:exec 3<>testfile,shell维护一个内部指针,每次读写都是从内部指针的上一次位置开始;
- 关闭文件描述符:重定向到特殊符号 -,exec 6>&-
- 列出文件描述符:lsof 显示系统内的所有文件描述符 root命令显示, -p 允许显示进程id,-d 显示指定的文件描述符编号 -d 1 2 3;显示的信息有 正在运行的命令 进程id号 进程属主 文件描述符号 文件类型 设备号 文件大小 文件节点 文件名;
- 不显示输出,重定向到/dev/null;也可用来清除文件内容 cat /dev/null > logfile;
- 创建临时文件:mktemp 在目录/tmp中创建一个唯一的临时文件;在命令后面添加文件名称可以 创建本地临时文件,mktemp testing.XXXXXX,XXXXX由系统自动生成,命令输出生成的文件名filename=$(mktemp test.XXXXX),-d 创建一个临时目录;
- 记录消息:将输出同时发送到显示器和日志文件 将stdin传过来的数据同时发送到std out和tee命令指定的文件名;-a 追加到文件中;如 tail -f logfile | tee tempfile;
控制脚本
- 发送信号:通过键盘组合键发送进程信号 ctrl + z ctrl + c;
- 捕获信号:trap commands signals,在信号出现时捕获信号并执行指定的命令;
trap "echo trap ctrl + c signal" SIGINT
echo this is a test script
count=1
while [ $count -le 5 ]
do
echo 'loop #$count'
sleep 1
count=$[ $count + 1 ]
done
echo "it's done"
输出:
loop #1
loop #2
trap ctrl + c signal
loop #3
loop #4
loop #5
捕获退出
trap 'echo goodbye...' EXIT
脚本正常退出时执行输出goodbye
- 修改或移除捕获:只要对同一个信号重新捕获即可,移除捕获 trap -- SIGINT
- 以后台模式运行脚本
- &符:将命令作为系统中的一个独立后台进程运行,输出后台进程的作业号和进程号;仍然使用终端显示器作为标准输入和标准输出 最好将后台运行脚本重定向;后台进程都是和终端会话绑定在一起的,会随着终端会话的退出而结束
- nohup 命令:命令运行了另外一个命令来阻断素有发送给进程的sigup信号,这会在退出终端时阻止进程退出;也就是说该命令使得后面要运行的命令不再接收sigup信号,但是他本身并不支持后台运行进程,因此可以将其和&符一起使用,让后台进程不再接收其他信号;输入和输出也不再和stdin stdout关联,而是重定向到nohup.out文件中
- 作业控制:ctrl + z会将作业放到后台中,并处于暂停状态;
- 查看作业 jobs,-l 显示进程号和作业号,-p 只显示进程号,-r 只列出运行中的作业 -s列出停止的作业;输出中的有一个+标识,表示默认作业,使用作业命令没有指定任何作业号就会将其作为作业控制命令的操作对象;带减号的作业表示下一个默认作业;
- 重启作业:bg 作业号,在后台模式下启动处于停止状态的作业;fg 作业号 以前台模式启动作业;
-
定时运行作业:at和cron表
- at命令:at [-f filename] time,通过将作业提交到队列中,at的守护进程atd以后台模式运行检查作业队列来运行作业,Linux系统在启动时会运行此作业;默认情况下at命令会见stdin的输入放到队列中;at 的输出为sendmail应用程序 向用户发送邮件 所以最好重定向 或者添加-M选项来屏蔽输出信息 at -M -f test.sh tommorow;atq命令会列出等待的作业;atrm taskno 删除等待中的作业;
- cron时间表:在一个文件中指定作业何时运行:min hour dayofmonth month dayofweek command;crontab -l 列出时间表,-e 启动编辑器添加任务;
- 编辑cron目录:如果对脚本执行的时间精度不高可以使用cron目录,在/etc/cron.*ly,有hourly daily monthly weekly;在指定时间主机处于关机状态则下次开机不会运行;
- anacron程序:可以在下次开机时立即运行没有运行的任务;常用来执行日志维护;只会处理/etc/*ly目录下的时间戳文件,通过时间戳来决定是否要运行;/etc/anacrontab来处理任务表;
- 使用bash启动脚本,在bash启动时要执行的命令,home/.bash_login, $home/.profile,可以在这些脚本文件中添加要执行的命令或要执行的任务,如添加环境变量;
函数
- 函数定义:格式如下
function name {
command
}
name() {
command
}
- 函数调用:调用函数函数在调用时和执行脚本一样名称加参数,name args;函数定义要在函数使用之前;
- 返回值:函数执行结束之后会有一个退出码,即为最后一条命令的执行情况,无法得知其他命令的执行情况;通过return命令返回特定的返回码;
- 函数输出:函数相当于一个小型的脚本,可以在函数中执行echo命令来输出字符串等内容 然后通过命令替换来获得函数输出的字符串 $(funcname arg0);
- 向函数中传递参数:在函数中也是通过$0 1 2 来获取函数的输入;
- 全局变量和局部变量:局部变量使用local关键字;local temp=value * 22 ]
- 创建库:将多个函数定义在同一个脚本文件中;source命令会在当前shell上下文中执行库文件脚本命令,而不是创建一个新shell;通过点操作符运行库文件脚本;
. $HOME/etc/script.sh
执行script.sh脚本,并且可以使用脚本中定义的所有函数和变量;
- 在shell启动脚本中定义要执行的脚本和定义的库文件;使用点操作符加载脚本文件即可;可以下载shtool中下载各种开源的库函数工具;
文本处理
sed
- 流编辑器,定义一个规则对输入进行编辑处理;每次执行以下操作:一次从输入中读取一行数据,根据所提供的编辑器命令匹配数据,按照命令修改流中的数据,将新的数据输出到STDOUT中;
- 命令格式:sed options script file;选项包括
- -e scrpt 将脚本中指定的命令添加到已有命令中,常用来执行多条命令 如 sed -e 's/brown/green/; s/dog/cat' detail.txt 两条命令都作用到每行数据中 命令之间必须使用分号隔开 并且在末尾和分号之间不能有空格
- -f file 将file中指定的命令添加到已有的命令中
- -n不产生命令输出 使用print命令完成输出;
替换命令
- 命令格式:s/pattern1/replacement/falg,flag有四种,数字 表明新文本将替换第几处模式匹配的地方,g 全部匹配都替换,p将原先行的内容打印出来,w file 将替换的结果写道文件中;未指定flag默认只替换第一个匹配的模式;
- 替换字符:一般使用斜线来作为替换字符,这样需要将pattern中的斜线用反斜线转义,也可以使用感叹号作为替换字符;
寻址
- 寻址:用来设置所有命令要作用于的文本行数据,也就是说 在执行命令之前 先对数据进行一次过滤;
- 完整的命令格式:[address]command;address就是寻址,寻址有两种,数字形式和文本模式
- 数字方式寻址:使用行号,单个行号 行号范围,使用美元符表示最后一行的行号;直接用数字即可,示例如下
单行
sed '2s/test/trial' data.txt
多行
sed '2,4s/test/trial' data.txt
sed '4,$s/test/trial' data.txt
单个寻址对应多个命令
sed '23,% {
s/test/trial
s/ns/switch
}' test.txt
- 文本模式寻址: 格式如下 /pattern/command 需要在pattern前后添加斜线,sed '/$adam/s/bash/csh/' /etc/passwd;pattern可以使用正则表达式;
删除命令
- 完整命令:[addresss]d,使用d,将寻址到的所有行删除;行号 sed '2,3d' data.txt; 特定文本 sed '/adam/,/$rache/d' /etc/passwd;
插入和附加命令
- 命令格式:i在寻址行之前添加一个新行,a在寻址行后添加一个新行;完整格式 [address]command\new line;示例如下:
echo 'test' | sed 'i\test1'
输出
test1
test
echo 'test' | sed 'a\test1'
输出
test
test1
插入内容到文件内容末尾
sed '$a\end of file'
修改行
- 命令格式:c\new line,将寻址到的行替换成new line,也可以使用两个文本模式来匹配,将两个模式之间的所有行都替换成new line,而不是每行逐一替换
cat data.txt
line1
line2
line3
line4
sed '/line1/,/line2/c\end line' data.txt
输出
line1
end line
line4
转换命令
- 命令格式:[address]y/inchars/outchars,将单个字符进行替换,sed 'y/123/789/' data8.txt,将1 2 3分别换成7 8 9
- 打印命令:p 打印文本行,= 打印行号,l 列出行;
- p 打印已有的行,-n 可以禁止输出其他行,只打印匹配文本模式的行;sed -n '/number3/p' data5.txt 只输出那一行;替换命令的p只会打印替换后的行要查看替换前的行可以使用如下命令
cat data.txt 输出 number 1 number 2 number 3 number 4 sed -n '/number 3/{' p s/number/test/p }' data.txt 输出 number 3 test 3
- 打印行号:示例如下
sed '=' data.txt 输出 1 number 1 2 number 2 3 number 3
处理文件
- 写入文件命令:[address]w filename,将匹配行输出到文件中;将前两行写入文件中 sed '1,2w test.txt' data.txt
- 读取文件命令:[address]r filename;sed '3r data.txt' data5.txt;将data.txt中的内容读取出来插入data5.txt文件的第三行后面;
sed进阶
- 多行命令:N 将数据流中的下一行加进来创建一个多行组,D 删除多行组中的一行,P 打印多行组中的一行
- 单行的next命令:n 将指针移至下一行
cat data.txt
this the header
this is middle
this is end
sed '/header/{n; d}' data.txt
输出:
this the header
this is middle
this is end
寻址到带有header那一行,n命令将指针移至下一行,执行删除命令
- 多行版本next命令:N 将下一行放到模式空间中, 将当前行和下一行当成一行处理,对这两行执行之后的命令;模式空间一个缓冲区,所有命令都针对于模式空间中的数据;
this is header
this is middle
this is end
sed '/header/{N; s/\n/ /}' data.txt
输出:
this is header this is middle
this is end
寻址到第一行,目前第一行在模式空间中,N命令将第二行加入到模式空间中,后面替换命令处理模式空间中的两行,将这两行当作一行处理,将换行符替换成空格
- 保持空间:也是一个缓冲区,可以将数据行暂存到保持空间;h 模式空间复制到保持空间,H 将模式空间的数据复制到保持空间,g 将保持空间的数据复制到模式空间,G 将保持空间中的内容附加到模式空间,x 交换模式空间和保持空间的内容;
sed '/header/{h;p;n;p;g;p}' data.txt
输出:
this is header
this is middle
this is header
复制header行到保持空间,打印模式空间内容 得到第一行输出,移至下一行,打印第二行,取回保持空间内容覆盖掉模式空间内容,打印模式空间内容
- 排除命令:! 让没有在模式空间中的内容执行命令
sed '/middle/!d' data.txt
输出:
this is middle
sed -n '{1!G;h;$p}' data.txt
输出:
this is end
this is middle
this is header
读入一行到模式空间,不是第一行则将保持空间中的数据附加到模式空间中,将模式空间中的数据复制到保持空间中,打印模式空间最后一行,得到反转的效果
- 改变流:所有命令都是从脚本的顶部开始,到最后一行,每次读取一行,并执行命令;通过改变流可以改变对行内容进行判断从而对不同内容执行不同的命令,就像if语句一样;
- 分支:[address]b [label] 表示要跳转到label脚本行;在脚本行最前面添加 :label 表示分支的脚本行;
echo 'this,is,a,comma' | sed '{:start;s/,/ /1p;/,/b start }' data.txt 输出 this is,a,comma this is a,comma this is a comma 第一行是一个带标签的start脚本行,这一行什么都没做,执行第二行,替换掉第一个逗号,执行第三行 如果带有逗号就跳转到start标签脚本行
- 模式替代:匹配哪些文本会匹配模式,在匹配模式.at的单词两端添加引号,这样是没有效果的 echo there is a cat on that hat | sed 's/.at/".at"/g' 最后输出结果为there is a ".at" on ".at" ".at",第二部分不会被识别成模式;
- 使用&符号,用这个符号可以用来代替被匹配的模式,因此可以写成 echo there is a cat on that hat | sed 's/.at/"&"/g'
- 部分替换修改:echo "that furry cat is pretty" | sed 's/furry (.at)/lazy \1/g',输出that lazy cat is pretty,查找匹配整个模式,但是修改模式中的部分;用转义后的括号将单词模式括起来,后面用转义加数字表示整个模式中的部分
gawk
- 概述:可以使用类似编程的方式来处理文本输入;可以定义变量 使用算术和字符串操作来处理数据 结构化编程概念 格式化输出;常用来生成格式化的报告;
- 命令格式:gawk options program file;options包括
- -F fs 指定输入中的字段分隔符
- -f file 从指定文件中读取程序
- -v 定义一个gawk程序中的一个变量
- -mt N 指定要处理的数据文件中的最大字段数
- -mr N 指定数据文件中最大数据行数
- -W keyword 指定gawk的兼容模式或警告等级
- gawk脚本:编写在花括号中,默认输入为stdin,输出为stdout,如 gawk '{print "hello"}',会重复键盘输入,通过分号分隔在同一行的脚本命令;gawk -F: -f script.gawk /etc/passwd 指定使用script.gawk文件作为gawk脚本;在文本行中会使用预定的分隔符来划分字段;
- 在处理数据前运行脚本:如创建标题,BEGIN关键字;gawk 'BEGIN {print "hello"}
{print $0}' data.txt 在读取数据之前打印hello 之后对数据进行打印操作; - 处理完数据之后运行的脚本:使用end关键字,gawk 'BEGIN {print "this is title"} {print $0} END {print "end of file"}' data.txt;一个完整的示例如下:
cat script.gawk
BEGIN {
print "this is title"
print "user: yesong"
}
{
print $1
}
END {
print "end of file"
}
gawk -f script.gawk /etc/passwd
- 变量:通过美元符加数字对应分隔符分隔后得到的数组中的元素;
- 分隔符变量:通过程序内建的变量来定义分隔符,FIELDWIDTHS 由空格分隔的一段数字 定义了每个数据字段确切的宽度,FS 输入字段分隔符,RS 输入记录分隔符,OFS 输出字段分隔符,ORS 输出记录分隔符;
cat data.txt
data1,data2,data3
data4,data5,data6
data1,data2,data4
gawk 'BEGIN{FS=","} {print $1}' data.txt
输出:
data1
data4
data1
在beegin处定义了分隔符,默认的输出字段分隔符为换行符
cat data2
123454864887
123456789897
gawk 'BEGIN{FIELDWIDTHS="2 4 2 3"} {print $1 $2 $3 $4}'
按照字符宽度来切割字符,输入字段分隔符失效
- 数据变量:可以提取shell的环境变量,
- ARGC 当前命令行参数的个数,ARGV 当前命令行参数数组,引用这些变量不用加美元符,gawk 'BEGIN{print ARGC, ARGV[1]}' data1 输出2 data1;
- ENVIRON,提取shell的环境变量,该变量是一个map 包含了shell所有环境变量, gawk 'BEGIN{print ENVIRON["HOME"]}' data1 输出 /home/yesong;
- FNR和NR:前者记录当前数据文件中已经处理过的记录数,如果有多个文件的话,处理第二个文件时文件数会重置为1;后者则是记录所有处理过的记录数;
- 自定义变量:自定义变量类同于shell变量,类型有字符串和数值,字符串加上引号,数字直接进行符号运算;
- 数组变量,var[index]=element,index可以是数字也可以是字符串;遍历数组遍历,for(var in array);删除数组变量,delete array[index];
- 使用正则表达式:正则表达式必须出现在他要控制的程序脚本的左花括号前;gawk 'BEGIN{FS=","} /11/{print $1}' data1,匹配数据字段中含有字符串11的记录
- 匹配操作符,将正则表达式限定在记录中的特定字段,波浪号~;不匹配在前面添加感叹号!
//用逗号作为分隔符,第二个数据字段匹配以data2开头的行,打印第一个数据字段; gawk 'BEGIN{FS=","} $2 ~ /^data2/{print $0}' data1 //用逗号作为分隔符,第二个数据字段匹配不以data2开头的行,打印第一个数据字段; gawk 'BEGIN{FS=","} $2 !~ /^data2/{print $0}' data1
- 数学表达式:gawk -F: '1}' /etc/passwd,匹配第四个字段为0的行,打印第2个字段;
- 结构化命令
- 条件:if(condition) statement,也可换行;gawk '{if(1}' data4;可以使用else,单行版本必须在第一个if后面添加分号,如果换行则不必加,if(condition) statement1; else statement2,每个statement两端添加花括号;
- while语句同java类似;
- do-while语句
- for语句 for(i=1;i<19;i++);
- 格式化打印:printf "format string", var1, var2 ...;可以使用单字代码指明显示的类型,如 printf 'the answer is %e', x;用科学计数法显示一个数;显示方式同java的格式化相同;
- 内建函数:
- 数学函数 atan2 cos exp int log rand sin sqrt srand等;
- 字符串函数:asort asorti gensub gsub index length match split sub substr tolower toupper
- 时间函数:mktime(dateformat),按照指定的时间格式输出当前时间;strftime(format, timestamp),按照指定的时间格式显示当前时间戳;systime() 返回当前时间的时间戳;
- 自定义函数:
function name([variables]){ statement } 可以使用return返回值; 使用函数的方式同java
- 创建函数库:在一个文件中定义各种函数;在命令中使用-f选项加载文件;
cat funclib function myprint(){ printf '%-16s - %s\n', $1, %4 } function myrand(limit) { return int(limit * rand()) } cat scrip BEGIN {FS='\n'; RS=""} { myprint() } gawk -f funclib -f script4 data2; 注意先后的加载顺序
正则表达式
- 正则表达式的类型:基础引擎BRE和拓展引擎ERE;
- BRE模式:纯文本和特殊文本;
- 特殊文本包括:.*^#{}\+?|();
- 锚字符:定位行首^和行尾$,组合使用表示空白行;
- 点号字符:匹配除了华南虎之外的任意单个字符;必须匹配一个字符;
- 字符组:用来定义模式中的某一个位置的一组字符;如sed -n '/[ch]at/p',显示cat或hat;
- 排除字符组:在字符组中使用脱字符;
- 区间:[0-9], [a-z], 间断区间 [a-ch-z];
- 特殊字符组:[[:alpha:]]
- 星号:在字符后面放置星号表示该字符必须在匹配模式的文本中出现0次或多次;将点号和星号组合表示匹配任意数量的任意字符;
- 拓展的正则表达式:添加了很多额外的gawk程序能识别,sed不能
- 问号:表示模式出现0此或1次;如hats?匹配hat hats,hat[se]?匹配hat hats hate
- 加号:模式出现一次或多次;
- 花括号:模式出现的次数;be{1,3}t 匹配 bet beet beeet;
- 管道符号:代表逻辑或,cat|dog 只匹配两个词;
- 圆括号:表示表达式分组;(c|b)a(a|d) 这里可以用中括号表示
其他
- lynx浏览网页
- 代理服务器:通过代理服务器来请求网页,可以用来保护客户端,过滤不良内容和恶意代码,同时会缓存经常访问的网页,降低带宽;
- 屏幕抓取:dump,lynx -dump 网址;
- mailx发送邮件
- wget下载网页文件
- wget -o out.log 网页;将会话的输出内容存到out.log中,并下载网页文件;
- wget --spider url:测试网页地址有效性;如果网页不存在会得到重定向的网站的404页面;
- 发送消息curl
- -d 添加请求参数,如 curl http://text.com/text -d phonenum=1242342 -d key=dkjig