[非常粗糙,没太多时间整理细致]
Shell指南笔记
一 文件安全与权限
目的就是设置文件和目录权限。顺便可以了解下UNIX文件管理方面的知识,比如文件属性等。
文件的访问方式分为:读写和执行,文件的用户分为文件属主,同组用户,其他用户。注意必须要理解这个区分。
1.1文件相关
系统当然知道文件的全部信息,通过ls命令可以获得想要的信息。这里就不解释ls输出的代表的意思了。
其实很重要,尤其是ls –l的表示rwxrwxrwx这9个字符,每三个一组,分别对应owner,group和other组。
total—该目录占用的全部空间。
文件类型在ls –l最前面的那个标示,分为:
l 目录 d
l 符号链接 l
l 套接字文件 s
l 块设备文件 b
l 字符文件 c
l 命名管道文件 p
l - 普通文件
可以用touch命令创建一个文件。创建的时候,不会自动附上执行权限。注意,目录的执行权限意思和文件不一样(其实就是浏览的功能)。
只读权限的文件可通过重定向方式写入,很奇怪。
那怎么修改权限位啊?命令是chmod。
1. chmod
chmod格式有两类,一个是绝对模式,另外一个是长点的符号模式。
符号模式很简单,就是一些字符代表特定的含义。如 u/g/o/a +- rwxstl。
绝对模式是用八进制数表示权限位。那么一个八进制位就可代表整个rwx的组合。
1.2 目录相关
目录的权限意思不太一样。
l 读权限表示可以列出其中内容
l 写权限表示可以创建文件
l 执行权限表示可以搜索和访问该目录。奇怪,访问目录和读的列出内容有啥区别?后面有个表格就说了,x是搜索或进入该目录。
另外,目录的权限会覆盖到目录文件中的权限。
另外,suid和guid的作用。目的是如果属主设置了suid权限,那么其他用户在执行的时候也会自动获得属主的权限。有什么特殊情况需要这个呢?因为有些命令必须让用户以root权限执行,但又不能用root登陆。
如何设置就不说了,4对应suid,2对应guid。如果都设置为6。位置在哪?对应权限位的前一位。实际上只能是设置u的位。
1.3 更改文件属主等命令
l chown/chgrp。一旦交出所有权,将没办法要回来,只能管理员帮忙了。
l 找出其他用户所属组:group(FC11没有)
l umask:掩码位,这个和0777~就得到真实的权限。这个对文件和目录还不太一样,反正知道是个反的意思即可。
1.4 符号链接
软链接就是一个快捷方式,硬链接不知道是什么,以后再说。链接的命令:
ln [-s] source_path target_path
其中,targetpath是链接名,sourcepath是真正的文件,这个地方很容易混淆。
二 find和xargs命令
2.1 find
find命令用来查找,有些选项能够很强大。
find格式为:find path –option [-print, -exec,-ok]
后面的中括号中为一些可选项。
find选项很多,但我用的比较多的就是按名字查找,文件类型
-name, -type bdcplf –size 递归搜索用-depth
1. name选项
name选项 后跟文件名,可以为模式匹配,但是得用引号。
前面那个path是查找路径。
2. 其他
按时间选项,-mtime -5 表示更改时间在5天以内,+5表示5天以前。
实际在Win下很少用其他选项。
用!表示非逻辑。size选项表示指定大小。Nc表示字节,大于用+,小于用-。
3. depth
先查找本目录,再到子目录去查找之意。宽度优先。
4. exec
意思为找到后执行的命令。
find xxx –exec/-ok cmd {} / ; //必须是这种格式,好像不用加反引号。-ok是一种安全的方式,带提示的那种。
2.2 xargs命令
find在加exec的时候 是把找到的文件一起传给了后续的命令(FT,这样得有多少个参数啊),所以太多参数了有些命名没法处理。所以就出现了xargs命令。find将匹配结果传给xargs,而xargs根据配置(根据选项或者系统内核中的参数)来选择一个或一批结果来传递给后续的命令处理(这样就减少了参数个数)。
find xxx | xargs cmd
这么说,find+xargs确实非常方便。
三 后台执行命令
后台执行其实意味着没有终端也可以执行,或者那些和系统相关的(类型Win下的系统服务程序),可以设置定时执行。
3.1 cron
cron是系统的主要调度进程,用于无需人工干预的自动运行作业(例如自动更新程序),cron是个进程,他来运行任务,运行任务的信息由crontab添加到系统数据库中。
crontab也是一个文件,这里边每项条目就是一个要执行的任务。当然里边条目的列信息很重要。
1 2 3 4 5 6
分钟小时日 月 星期 命令
1 22 30 3 3 copy 各个域空格分开。时间段可用,和-来表示。
*表示任意。注释由#表示。
注意,后边的命令必须给出绝对路径,因为cron不清楚环境。
crontab –e –l –r
创建完毕后,一个副本在/var/spool/cron中,文件名就是用户名。
测试了下,还没见到它执行啊。每5分钟一次。
3.2 at命令
at命令用于向cron进程提交任务。指定一个时间,如果时间大于几天最好还是用crontab来做。
at命令不再多叙。
3.3 &后台运行
就是腾出一个终端出来可用干别的事情,最好重定向输入输出,否则后台运行的程序仍会把输出发到终端上来,这样很烦。
确实,例如后台运行gedit,老是输出到终端。
后台运行后,想要关掉它就得知道进程ID,一般用ps x命令查看。杀死一个进程用kill命令
kill – signal ID
有时候退出账户了进程还想继续运行,则需要用nohup command & 来实现这个功能。
四 文件名替换
其实说的是shell中的字符串模式匹配规则,这个非常重要。又叫元字符。
元字符:元的概念就是基本字符。类似元数据,就是能表示其他数据的数据。shell中哪些是元字符呢?*?[][!]
l *为任意字符串,包括空
l ?单个任意字符
l [...]匹配[]中所包含的任何字符,中间搞个-表示一个范围。
l [!]匹配[]非!之后的字符
那么如果想表示元字符怎么处理?加上转义符号即可。/? /*等。
这一节内容较少,较详细的内容在后续章节。
五 shell的输入和输出
标准输入是键盘,标准输出是终端相关的屏幕,标准错误输出也是。一般来说能够接受标准输入的命令也可以接受文件做为输入。(这里的文件应该指的是文件的内容。)
5.1 echo & read
echo命令用得很多,一般能想到的控制就是换行/n,和不换行/c或–n选项。类似printf。
echo string中的string可以非常灵活,通过各种转义字符能执行很多功能。(linux下用-e选项使能转义字符)。
美元$号是特殊字符,包括``抑音符。
通过>(复写) >>(追加)重定向到文件。
echo是输出,read是从输入中读取信息并赋给一个变量。
这么看来,read后一定是一个什么东西来接收输入了,如果只有一个变量则一直输入到文件结束符未知。这么讲的话完全可以把一个文件的内容赋给一个变量。如果有多个变量的话,则输入的空格就是代表变量的切换。
5.2 cat
cat可用于显示文件内容,创建文件,显示控制字符。注意cat不会分页,它会一下把整个文件内容全部显示出来,所以只能你自己通过more等命令分页显示了。
cat默认不显示控制字符,通过选项-v来显示。cat f1 f2 f3...能一次显示多个文件。
一个窍门是可以用cat做简易的文本编辑器,cat >/>>file,ctrl+d结束输入即可。
5.3 管道
管道的作用,在这里正是说明是将一个命令的输出传递给另外一个命令做为输入。这个和重定向没有什么关系。但有功能相似之处,在具体命令上可能不能用重定向。例如
ls | grep “^[x]” 这么做是正确的,但 ls > grep “^[x]” 将错误,因为 > 后面的东西需要在ls中做为一个输出文件打开。这个显然是不能打开的。
5.4 tee
tee很形象,有两个输出,一个是标准输出屏幕,另一个是某个文件。
tee –a 表示追加。 who | tee who.out 即会输出到屏幕,又写道文件。如果是普通的>的话将只重定向到文件而没有屏幕输出。
5.5 标准IO和重定向
对应文件描述符是012,在重定向的时候对于文件描述符得用&表示。
如 command > file 2>&1,解释如此:先通过第一个>将标准输出重定向到file,这样1其实就转变为file了,然后将2重定向到1。
可否 command > file 2>file? 这么做事OK的。为何2前面没有&??
command < &-关闭标准输入。
重定向输入比较少用。
sort < name.txt 这样也行。
command << delimiter 这个其实想法很简单,就是2个分界符之间的内容作为输入的界限。
shell解释命令的顺序是从左到右,所以上面comm > file 2>&1 的这个1是可以直接代表file的。
5.6 exec
exec表示执行一个命令,但是不会启动子shell,而只是替代当前shell并且所有环境都会被清空。
暂时没搞清楚它的应用场景。似乎比较常用,在使用文件描述符上。再研究下例子。
shell的内建命令exec将并不启动新的shell,而是用要被执行命令替换当前的shell进程,并且将老进程的环境清理掉,而且exec命令后的其它命令将不再执行。
因此,如果你在一个shell里面,执行exec ls那么,当列出了当前目录后,这个shell就自己退出了,因为这个shell进程已被替换为仅仅执行ls命令的一个进程,执行结束自然也就退出了。为了避免这个影响我们的使用,一般将exec命令放到一个shell脚本里面,用主脚本调用这个脚本,调用点处可以用bash a.sh,(a.sh就是存放该命令的脚本),这样会为a.sh建立一个sub shell去执行,当执行到exec后,该子脚本进程就被替换成了相应的exec的命令。
source命令或者".",不会为脚本新建shell,而只是将脚本包含的命令在当前shell执行。
不过,要注意一个例外,当exec命令来对文件描述符操作的时候,就不会替换shell,而且操作完成后,还会继续执行接下来的命令。
exec 3<&0:这个命令就是将操作符3也指向标准输入。
终于看明白了例子了。原来是先保存再恢复的意思。
exec x<&- 关闭描述符
1 #!/bin/bash
2 # 使用'exec'重定向标准输入.
3
4
5 exec 6<&0 # 将文件描述符#6与stdin链接起来.
6 # 保存了stdin.
7
8 exec < data-file # stdin被文件"data-file"所代替.
9
10 read a1 # 读取文件"data-file"的第一行.
11 read a2 # 读取文件"data-file"的第二行.
21 exec 0<&6 6<&-
22 # 现在将stdin从fd #6中恢复, 因为刚才我们把stdin重定向到#6了,
23 #+ 然后关闭fd #6 ( 6<&- ), 好让这个描述符继续被其他进程所使用.
24 #
25 # <&6 6<&- 这么做也可以.
26
27 echo -n "Enter data "
28 read b1 # 现在"read"已经恢复正常了, 就是从stdin中读取.
29 echo "Input read from stdin."
有个奇特的地方,难道一定得区分标准输入和输出吗?因为><这两个符号用得很多,如果仅仅是保存作用的话,那么指定一个<符号不就OK了?
另外一个例子,实现拷贝的。
不提供参数时,它将标准输入输出到标准输出;提供一个文件名参数时,将该文件输出到标准输出;提供两个文件名参数时,它将提一个文件复制到第二个文件。
#! /bin/sh
case $# in
0)
exec 3<&0 4>&1 #why这里要区分标准输入和输出啊
;;
1)
exec 3<$1 4>&1
;;
2)
exec 3<$1 4>$2
;;
*)
echo "Usage: `basename $0` [source [dest]]"
exit 1
;;
esac
cat <&3 >&4
exec 3<&- 4<&-
exit 0
如何关闭文件描述符
n<&-
关闭输入文件描述符n.
0<&-, <&-
关闭stdin.
n>&-
关闭输出文件描述符n.
1>&-, >&-
关闭stdout.
六 命令执行顺序
这个有很多内容吗?其实就是命令组合执行的。
C1&&C2 C1执行成功了才执行C2
C1 || C2 只有C1执行失败,C2才会执行。
如何在一个shell中执行多个命令。
l 在当前shell中执行一组命令,用(C1;C2;...)
l 如果用{C1;C2;...}将在子shell中一起执行。
这个{}方法还有点特殊,必须所有命令输出都被整体重定向时候才放到子shell中。
这个没搞清楚。
第十三 登陆环境
登陆的时候检查用户名和密码,这个是在/etc/passwd里边的。登陆成功后执行/etc/profile,第二个是.profile环境设置文件。有啥子用?
13七 正则表达式
这个非常重要。关键是掌握模式匹配的规则。先介绍grep中的基本元字符。
元字符的含义掌握了,正则表达式差不多就如此了。
l ^ 匹配行首,$匹配行尾
l * 一个单字符后紧跟*,匹配0个或多个此单字符(有点不太一样,应该是后续任何字符都可以)
l []
l / 转义字符
l . 匹配任意单字符
l pattern/{n/}用来匹配前面pattern出现的次数,n为次数
l pattern/{n,m/}同上,出现次数在n与m间
注意,没有?号表示,find中有?在grep中用.,而没有?,在其他中有?。.是正则表达式,?是模式匹配,有点不一样的说。
匹配所有空行,用^$表示。
^放在[]中表示!的意思。[A-Za-z]*表示任意字母。
怎么感觉怪怪的?应该在后续章节里边大量测试。
八 grep
grep格式为 –option 表达式 文件。
关于引号的使用:一般字符串和变量都用双引号,如果是模式匹配则使用单引号。
选项比较多,关键看做什么。
例如:-c 输出匹配行技术,-n显示匹配行和行号等,-v显示不匹配行,关闭大小写敏感是-i
查询多个文件的话,看来对文件名也要用匹配方式了。
精确匹配/>是什么意思?
这些匹配模式不能做到非常精确,例如[48]表示4或者8或者48。
grep使用与/或模式。加上-E选项,支持|表示或。还支持[[:upper:]]等类方式表示的模式匹配。
一些常用例子。egrep是grep的扩展命令程序,一个比较大的特征是用一个文件作为输入字符串,需要-f开关。
[]这个是匹配一个单字符的范围之意。
grep命令好像没什么,关键是正则表达式弄清楚了就好。
看来正则表达式还是需要花其他点时间仔细总结下的。
九 AWK介绍
awk是一个根据发明人的名字来命名的一种解释性语言。它的功能就是在文件或字符串中基于指定规则浏览和抽取信息,抽取信息后才能进行其他文本操作。
l 使用命令如下:awk [-F field-separator] ‘commands’ input-files 其中field-seperator:预分隔符,这个很重要啊,默认是空格
l 将awk写成脚本文件,首行得是#!/bin/awk
l 用awk调用awk脚本 awk –f awk-script-file inputfiles
awk解释是一行一行的,每一行通过域分隔符来区分域。有点像列表控件。
command分为模式和动作,模式决定如何动作,动作即对数据进行操作的意思。
模式中的两个特殊字段 BEGIN/END,BEGIN语句使用在浏览动作之前,END用于完成浏览动作后打印输出,实际动作在{}指明,还可输入代码。
9.1 /etc/profile域和记录
此文件干啥用的?包括全局或局部环境变量,PATH信息。
13$1,$2是awk解析出来的域,其中$0为所有域的意思。
9.2 $HOME/.profile正则表达式
这个是登陆后执行的,用户可以覆盖profile内定义的值。
修改成功后,通过.或source命令来执行。
awk中的正则表达式用//括起来。
有几个地方比grep要多:
l +匹配一个或多个
l ?匹配模式出现的频率
还有些条件操作符,如<,<=,==,!=,>=,~(匹配正则表达式),!~
除了使用~外,还可使用if()语句,AND,OR,!判断等。
从它的几个例子来看,如果是字符串的话就用双引号,如果需要搞那种模式匹配的话就用//
9.3 内置变量及其他
内置变量可以很好得完成某些功能,如ARGC,ARGV,ENVIRON,FILENAME,FNR,FS等。
awk可定义变量名。直接定义并赋值即可,例如name=$n;belts=$2,中间和最后得用分号隔开。
l NR:已经读取的记录条数(一行是一个记录)
l NF:每行的域个数,$NF是最后一行最后一个域的值
注意,任何awk修改的只是复本,原输入文件不会修改。
修改数值域,修改文本域,创建新域,内置字符串函数等操作,这里不讲了。
后边的内置字符串函数,数组等内容不再讲述,否则东西太多了,相当于又学习了一门新语言。
十 sed
sed是一个非交互的文本流编辑器。sed并不修改源文件,所以只能你自己保存修改后的文件了。由于是非交互式的,所以得告诉sed的行号或匹配模式好让他知道处理什么内容。
sed –p 命令 文件,实际命令要加单引号,和awk很像。
sed定位文本的方式为
l 指定行号xx,y
晕,就是一个非交互式的文本编辑器,功能得差不多和交互式的,不过完全是用命令来做罢了。有难度。
sed命令一般用途是修改或删除文件或字符串中的文本。
先不讲述了。
十一 合并与分割
处理文本文件分类,合并和分割。
11.1 sort系列命令
sort选项太多了。就是向列表控件那样排序的功能。它的列表域从0开始。如果要按数值来排序则要指定-n,否则就按字母排序了。按指定域的话用 –kn来表示。这个时候列表域从1开始与awk一样。
head和tail命令显示头或尾的几行。
实际sort是排序,排序完了可以对几个文件进行合并。
uniq命令,uniq去除连续重复行,而sort去除所有重复行。
join命令,将几个排序文件行连在一起。
cut/paste命令
split拆分文件。
十二 tr命令
tr用来替换或删除操作进行字符替换,主要用于删除文件中控制字符或进行字符转换。用法:
tr –c –d –s “s1” “s2” file
这个s1和s2的有要求。s1模式转换成s2模式。如 tr “[a-z]” “[A-Z]” 从小写转换成大写。
十四 环境变量和shell变量
14.1 本地变量
本地变量为用户现在的shell生命期脚本中使用,使用时候尽量用花括号弄起来。设置时候用:
V1=value/${V1},等号两边可有空格,如果取值含空格,则需用双引号引起来。变量设置的不同模式:
=/+/:?/?/:=/:-等,用echo命令通过$显示变量取值。用unset消除变量。变量并排可以结合变量。${V1}${V2}。有什么用?
关于echo这个双引号或者$问题,如果是变量,则用花括号即可,如果是值的话,最好加双引号。
l 测试变量是否赋值:v1:-value意味如果v1存在则使用旧值,否则用value,但是不赋值。
l v1:=value,这个当v1不存在的时候会赋新值
l v1:+value,如果未设置则返回空串
设置只读变量,利用readonly v1命令。
14.2 环境变量
环境变量和一般变量无二,但环境变量能在所有子进程中使用,所以需要通过export命令导出环境变量。
l env显示所有环境变量
l unset清除环境变量
l set –a 将脚本中的所有变量全部导出(相当于每变量写一个export语句)
另外,export的另外一个作用就是导出的变量能在子脚本中使用。
export导出的作用还不仅仅是环境变量。应该这么理解,export导出的东西在所有脚本中都可以使用,但是要使得成为环境变量,还得调用source命令进行处理。
14.3 位置变量和特定变量参数
shell变量共分四种:
l 一般变量(本地变量)
l 环境变量(可以认为是全局变量)
l 位置变量,即$0,$1等等
l 特定变量,见后续讲解
shell中没有类似main(int argc,char*argv[])这些表示外界传入参数的东西,但是它有自己的表示方法,这就是位置变量参数。
l shell脚本的参数可以任意多,但只有前9个可以被访问,后续的必须通过shift命令来访问,前9个分别是$0.$1...$8,$9其中$0默认都是脚本文件的名字。参数间以空格隔开
1.特定变量
共7个特定变量(其实就是有他特殊含义的变量)。
l $#:传递到脚本的参数个数
l $*:以一个单字符串显示所有脚本参数,可超过9个(就是一个参数列表字符串,无附加引号)
l $$:当前进程ID号
l $!:后台运行的最后一个进程的ID号
l $@:与$*相同,但使用时加引号,在引号中返回每个参数(每个参数都有引号)
l $-:显示shell当前使用的选项,与set命令功能相同
l $?:显示脚本退出返回值,0表示正确
十五 引号
确实,shell中引号到底怎么用,用法是什么需要特定强调一下。
分为双,单,反引号和反斜线。
15.1 双引号
双引号可引用除$,`,/外的任意字符或字符串(也就是说,双引号里边的内容如果包含这三个特色符号的话,shell将按特殊符号处理)。
15.2 单引号
单引号忽略如何引用(即忽略任何特殊字符)
15.3 反引号
shell将反引号中的内容做为一个系统命令,也就是说会先执行这个命令,将它的结果作为其他命令的输入。