分享

《shell编程指南》读书笔记(一)——文件权限及查找

 happy123god 2013-01-07
    近日在读《linux与unix shell编程指南》这本书,为防止读完后又
抛之脑后而遗忘,在此记录一下。需要说明的是,除了自己学习,当
要使用某个命令但对其用法不熟时,除了baidu, google,在shell里面
使用man命令,或者[command] --help 是很有帮助的。要想学好shell
编程,多尝试,多使用。
           由于不方便制作目录及索引, 本文开篇将讲述文章主体内容。

           本节主要讲述文件权限(如chmod),find / xargs命令及后台执行命令crontab 。 
 
            至少要掌握如下内容(shell命令示例):

     find ./src/mw/ -type f | xargs grep "io_init"
     chmod og-w myfile
     chmod -R 664 /usr/local/home/dave/*

 
第一章   文件安全与权限
 
关于ls命令及输出相关的文件类型,权限相关的比较简单,在此不做赘述。
 
1.1. 我们可以用 touch 命令创建一个文件:
$ touch myfile
 
1.2. chmod改变文件的访问权限。有较短的绝对模式和较长的符号模式。
 
1.2.1 符号模式
 
chmod命令的一般格式为:
chmod [who] operator [permission] filename
who的含义是:
u 文件属主权限。
g 同组用户权限。
o 其他用户权限。
a 所有用户(文件属主、同组用户及其他用户)。
operator的含义:
+ 增加权限。
- 取消权限。
= 设定权限。
permission的含义:
r 读权限。
w 写权限。
x 执行权限。
s 文件属主和组s e t - I D。
t 粘性位。
l 给文件加锁,使其他用户无法访问。
这种方式在对文件添加或去除某种权限的情况下使用比较方便。
 
假定myfile文件最初具有这样的权限: rwx rwx rwx ,那么
 
输入命令            命令执行后的文件访问权限            说明
chmod og-w myfile   rw- r-- r--            收回同组用户和其他用户的写权限
 
1.2.2 绝对模式
 
chmod命令绝对模式的一般形式为:
chmod [mode] file
其中mode是一个八进制数。
 
有一个计算八进制权限表示的更好办法,
 
文件属主       同组用户        其他用户
r   w   x    r   w   x     r   w   x
4 + 2 + 1    4 + 2 + 1     4 + 2 + 1
 
对于chmod的绝对模式,是不需要知道当前文件的访问权限,通过绝对模式的设置,
就可以获得设置后的文件访问权限,如下:chmod 744 rwx r-- r- -
赋予文件属主读、写和执行的权限,所有其他用户读的权限
 
还可以通过使用- R选项连同子目录下的文件一起设置:
chmod -R 664 /usr/local/home/dave/*
这样就可以一次将/usr/local/home/dave目录下的所有文件连同各个子目录
下的文件的权限全部设置为文件属主和同组用户可读和写,其他用户只读。
使用- R选项一定要谨慎,只有在需要改变目录树下全部文件权限时才可以使用。
 
1.2.3  关于目录的执行权限
 
 目录权限
r w x
可以列出该目录中的文件,如ls 命令
可以在该目录中创建或删除文件,
如可使用touch创建,或rm删除 
 可以搜索或进入该目录,
  如可通过cd进入,通过
cat读取目录中的文件等

如果把同组用户或其他用户针对某一目录的权限设置为--x,那么他们将无法列出该目录
中的文件。如果该目录中有一个执行位置位的脚本或程序,只要用户知道它的路径和文件名,
仍然可以执行它。用户不能够列出该目录并不妨碍他的执行。

目录的权限将会影响目录中文件的权限。如果目录都无执行权限,那么即使目录中的文件权限
为7 (读写可执行),也是无法被执行的。
 
1.2.4  suid/guid
 
suid意味着如果某个用户对属于自己的shell脚本设置了这种权限,那么其他用户在执行这
一脚本时也会具有其属主的相应权限。于是,如果根用户的某一个脚本设置了这样的权限,
那么其他普通用户在执行它的期间也同样具有根用户的权限。同样的原则也适用于guid,执
行相应脚本的用户将具有该文件所属用户组中用户的权限。
 
为什么要使用这种类型的脚本?这里有一个很好的例子。我管理着几个大型的数据库系
统,而对它们进行备份需要有系统管理权限。我写了几个脚本,并设置了它们的guid,这样
我指定的一些用户只要执行这些脚本就能够完成相应的工作,而无须以数据库管理员的身份
登录,以免不小心破坏了数据库服务器。通过执行这些脚本,他们可以完成数据库备份及其
他管理任务,但是在这些脚本运行结束之后,他们就又回复到他们作为普通用户的权限。
 
有相当一些UNIX命令也设置了suid和guid。如果想找出这些命令,可以执行下面的命令:
$ ls -l  /bin | grep '^...s'
上面的命令是用来查找suid文件的;可以看到ping ,traceroute,mount/umount 命令设置了suid。
$ ls -l  /bin | grep '^...s..s'
上面的命令是用来查找suid和guid的。
 
现在我们明白了什么是suid,可是如何设置它呢?下面就来介绍这个问题。如果希望设置
suid,那么就将相应的权限位之前的那一位设置为4;如果希望设置guid,那么就将相应的权限
位之前的那一位设置为2;如果希望两者都置位,那么将相应的权限位之前的那一位设置为4+2。
一旦设置了这一位,一个s将出现在x的位置上。记住:在设置suid或guid的同时,相应的
执行权限位必须要被设置。例如,如果希望设置guid,那么必须要让该用户组具有执行权限。
如果想要对文件login设置suid,它当前所具有的权限为rwx rw- r-- (741),需要在使用
chmod命令时在该权限数字的前面加上一个4,即chmod 4741,这将使该文件的权限变为
rws rw- r - -。
$ chmod 4741 login
 
也就是说属主或用户组对应的执行位被设置为了s。所以,上面我们使用grep命令查找设置了
suid,guid的文件时,是在属主和属主用户组的执行权限位上搜索s。
附带说明: 那个^表示字符串的开头。
 
设置suid/guid的示例:
chmod 4764 rws rw- r- -
文件被设置了suid,文件属主具有读、写和执行的权限,同组用
户具有读和执行的权限,其他用户具有读权限。
 
还可以使用符号方式来设置suid/guid。如果某个文件具有这样的权限: rwx r-x r- x,那么
可以这样设置其suid:
chmod u+s <filename>
于是该文件的权限将变为: rws r-x r-x
 
1.2.5  umask
 
当最初登录到系统中时, umask命令确定了你创建文件的缺省模式。这一命令实际上和
chmod命令正好相反。你的系统管理员必须要为你设置一个合理的umask值,以确保你创建的
文件具有所希望的缺省权限,防止其他非同组用户对你的文件具有写权限。
 
一般来说,umask命令是在/etc/profile文件中设置的,每个用户在登录时都会引用这个文
件,所以如果希望改变所有用户的umask,可以在该文件中加入相应的条目。如果希望永久性
地设置自己的umask值,那么就把它放在自己$HOME目录下的.profile或.bash_profile文件中。
 
umask命令允许你设定文件创建时的缺省模式,对应每一类用户(文件属主、同组用户、
其他用户)存在一个相应的umask值中的数字。对于文件来说,这一数字的最大值分别是6。系
统不允许你在创建一个文本文件时就赋予它执行权限,必须在创建后用chmod命令增加这一
权限。目录则允许设置执行权限,这样针对目录来说,umask中各个数字最大可以到7。
该命令的一般形式为:
umask nnn
其中nnn为umask置000-777。
 
我们只要记住u m a s k是从权限中“拿走”相应的位即可。
 
        umask值与权限
umask       文件     目录
0                  6             7
1                  6             6
2                  4             5
3                  4             4
4                  2             3
5                  2             2
6                  0             1
7                  0             0
 
这就是上面的例子,其中u m a s k值为0 0 2:
1) 文件的最大权限rwx rwx rwx (777)
2) umask值为0 0 2 - - - - - - -w-
3) 目录权限rwx rwx r-x (775) 这就是目录创建缺省权限
4) 文件权限rw- rw- r-- (664) 这就是文件创建缺省权限
下面是另外一个例子,假设这次u m a s k值为0 2 2:
1) 文件的最大权限rwx rwx rwx (777)
2 ) u m a s k值为0 2 2 - - - -w- -w-
3) 目录权限rwx r-x r-x (755) 这就是目录创建缺省权限
4) 文件权限rw- r-- r-- (644) 这就是文件创建缺省权限
 
如果想知道当前的umask 值,可以使用umask命令:
umask (获取当前的umask)
umask [mask_num] 设置新的umask
 

 
1.3.  符号连接
分为软连接和硬连接。
 
1.3.1  软连接 (soft link )
实际上就是一个指向文件的指针,如:windows系统里面文件的快捷方式。
用途:实现一个文件被多个用户或目录共享访问,或者文件的“快捷”访问。
 
该命令的一般形式为: ln [-s] source_path target_path
其中的路径可以是目录也可以是文件。
 
不管是否在同一个文件系统中,都可以创建链接(可跨越文件系统)。在创建
链接的时候,不要忘记在原有目录设置执行权限。链接一旦创建,链接目录将
具有权限7 7 7或rwx rwx rwx,但是实际的原有文件的权限并未改变。
 
例如:dir_test目录的访问权限为d-wxrwxrwx,那么我们使用ln [-s] dir_test link_test
([-s]表示-s可选)后,link_test的权限虽然为lrwxrwxrwx,但是如果你通过ls 命令去
查看link_test,实际上是要去访问源目录文件dir_test,所以会发现"permission denied"。
因为此外的dir_test不具有属主读权限,不能列出此目录中的文件。
 
 
第2章   使用find和xargs
 
Find是一个非常有效的工具,它可以遍历当前目录甚至于整个文件系统来查找某些文件或目录。
 
在运行一个非常消耗资源的find命令时,很多人都倾向于把它放在后台执行,因为遍历一
个大的文件系统可能会花费很长的时间(这里是指30G字节以上的文件系统)。
Find命令的一般形式为:
find pathname -options [-print -exec -ok]
pathname find命令所查找的目录路径。例如用.来表示当前目录,用/来表示系统根目录。
-print find命令将匹配的文件输出到标准输出,默认是输出到标准输出
-exec find命令对匹配的文件执行该参数所给出的shell命令。相应命令的形式为' command' {} \;,
注意{ }和\;之间的空格。
-ok 和- exec的作用相同,只不过以一种更为安全的模式来执行该参数所给出的shell命令,
在执行每一个命令之前,都会给出提示,让用户来确定是否执行。
 
 
 
2.1.Find命令

(1) -perm 选项
如果希望在当前目录下查找所有用户都可读、写、执行的文件(要小心这种情况),我们
可以使用find命令的-perm选项。在八进制数字前面要加一个横杠-。在下面的命令中-perm代
表按照文件权限查找,而'007’和你在chmod命令的绝对模式中所采用的表示法完全相同。
$ find . -perm -007 -print

(2) -name 选项
如果想在当前目录查找文件名以两个小写字母开头,跟着是两个数字,最后是*.txt的文
件,下面的命令就能够返回名为ax37.txt的文件:

$ find . -name "[a-z][a-z][0--9][0--9].txt" -print

(3) -newer 选项
如果想使用find命令的这一选项来查找更改时间在两个小时以内的文件,除非有一个现成
文件其更改时间恰好在两个小时以前,否则就没有可用来比较更改时间的文件。为了解决这一
问题,可以首先创建一个文件并将其日期和时间戳设置为所需要的时间。这可以用touch命令来实现。

touch -t 05042140 dstamp
ls -l dstamp
-rw-r--r-- 1 dave  admin  - May 4 21:40 dstamp

这里假设今天是五月四日,当前时间为23:40 。

假设现在的时间是23:40,希望查找更改时间在两个小时以内的文件,可以首先创建这样
一个文件:一个符合要求的文件已经被创建;这里我们假设今天是五月四日,而该文件的更改时间
是21:40,比现在刚好早两个小时。

现在我们就可以使用find命令的-newer选项在当前目录下查找所有更改时间在两个小时以
内的文件:
$ find . -newer dstamp -print


(4) -depth 选项
先从当前目录查找,之后再从子目录查找。

(5) -exec 选项
当匹配到一些文件以后,可能希望对其进行某些操作,这时就可以使用-exec选项。
命令之后需要{},\,;这几个符号。 如:
find -name "core" -exec rm {} \;
 
2.2.xargs命令
find命令的-exec选项在某些系统中有命令参数长度限制,并且有些系统的实现
是对find命令匹配的每一项的命令执行都是通过一个进程实现,这样耗费系统资源;
所以xargs命令就出现了。其针对输入参数的每一个执行后面的命令,如find,grep。
使用示例:
find ./src/mw/ -type f | xargs grep "io_init"
 
 
第3章  后台执行命令
 
当你在终端或控制台工作时,可能不希望由于运行一个作业而占住了屏幕,因为可能还
有更重要的事情要做,比如阅读电子邮件。对于密集访问磁盘的进程,你可能希望它能够在
每天的非负荷高峰时间段运行。为了使这些进程能够在后台运行,也就是说不在终端屏幕上
运行,有几种选择方法可供使用。
 
设置crontab文件,并用它来提交作业。
使用at命令来提交作业。
在后台提交作业。
使用nohup命令提交作业。
 
cron 系统调度进程。可以使用它在每天的非高峰负荷时间段运行作业,或在一周或一月
中的不同时段运行。
At at命令。使用它在一个特定的时间运行一些特殊的作业,或在晚一些的非负荷高峰时
间段或高峰负荷时间段运行。
& 使用它在后台运行一个占用时间不长的进程。
Nohup 使用它在后台运行一个命令,即使在用户退出时也不受影响。
 
3.1 cron和crontab
cron是系统主要的调度进程,可以在无需人工干预的情况下运行作业。有一个叫做crontab
的命令允许用户提交、编辑或删除相应的作业。每一个用户都可以有一个crontab文件来保存
调度信息。可用于服务器维护等情况。
 
3.1.1 crontab的域
下面是crontab的格式:
分<>时<>日<>月<>星期<>要运行的命令
其中<>表示空格。
 
第1列  分钟1~59
第2列  小时1~23(0表示子夜)
第3列    日1~31
第4列    月1~12
第5列  星期0~6(0表示星期天)
第6列  要运行的命令
 
在这些域中,可以用横杠-来表示一个时间范围,例如你希望星期一至星期五运行某个作
业,那么可以在星期域使用1-5来表示。还可以在这些域中使用逗号“,”,例如你希望星期一
和星期四运行某个作业,只需要使用1,4来表示。可以用星号*来表示连续的时间段。如果你
对某个表示时间的域没有特别的限定,也应该在该域填入*。该文件的每一个条目必须含有5
个时间域,而且每个域之间要用空格分隔。该文件中所有的注释行要在行首用#来表示。
 
3.1.2 crontab条目举例
示例: 45 4 1,10,22 * * /apps/bin/backup.sh
上面的例子表示每月1、10、22日的4:45运行/apps/bin目录下的backup.sh。
 
0,30 18-23 * * * /apps/bin/dbcheck.sh
上例表示在每天18:00至23:00之间每隔30分钟运行/apps/bin目录下的dbcheck.sh。
 
你可能已经注意到上面的例子中,每个命令都给出了绝对路径。当使用crontab运行shell
脚本时,要由用户来给出脚本的绝对路径,设置相应的环境变量。
 
3.1.3 crontab命令选项
crontab命令的一般形式为:
Crontab [-u user] -e -l -r
其中:
-u 用户名。
-e 编辑crontab文件。
-l 列出crontab文件中的内容。
-r 删除crontab文件。
如果使用自己的名字登录,就不用使用-u选项,因为在执行crontab命令时,该命令能够
知道当前的用户。
 
3.1.4 创建一个新的crontab文件
在考虑向cron进程提交一个crontab文件之前,首先要做的一件事情就是设置环境变量
EDITOR。cron进程根据它来确定使用哪个编辑器编辑crontab文件。99%的UNIX和LINUX用
户都使用vi,如果你也是这样,那么你就编辑$HOME目录下的.profile文件,在其中加入这样
一行:
EDITOR=vi; export EDITOR
然后保存并退出。
不妨创建一个名为<user>cron的文件,其中<user>是用户名,例如,davecron。在该文件
中加入如下的内容:
 
#(put your own initials here) echo the date to the console every
# 15 minutes between 6 p.m and 6 a.m
 
0,15,30,45  18-06 * * * /bin/date > /dev/console
 
保存并退出。
 
上面的例子表示在0,15,30,45 分钟, 18-06 这几个小时内,每天输出。 即每隔15分钟向
控制台输出一次当前时间。
 
为了提交你刚刚创建的crontab文件,可以把这个新创建的文件作为cron命令的参数:
$ crontab davecron
现在该文件已经提交给cron进程,它将每隔15分钟运行一次。
同时,新创建文件的一个副本已经被放在/var/spool/cron目录中,文件名就是用户名(即,
dave)。
 
3.1.5 列出crontab文件
为了列出crontab文件,可以用:$ crontab -l
 
 
3.1.6 编辑crontab文件
加了新的条目,那么在保存该文件时, cron会对其进行必要的完整性检查。如果其中
的某个域出现了超出允许范围的值,它会提示你。
 
 
3.1.7 删除crontab文件
 
 
3.2 at命令
 
at命令允许用户向cron守护进程提交作业,使其在稍后的时间运行。这里稍后的时间可能
是指10min以后,也可能是指几天以后。如果你希望在一个月或更长的时间以后运行,最好还
是使用crontab文件。

一旦一个作业被提交, at命令将会保留所有当前的环境变量,包括路径,不象crontab,
只提供缺省的环境。该作业的所有输出都将以电子邮件的形式发送给用户,除非你对其输出
进行了重定向,绝大多数情况下是重定向到某个文件中。

和crontab一样,根用户可以通过/etc目录下的at.allow和at.deny文件来控制哪些用户可以使
用at命令,哪些用户不行。不过一般来说,对at命令的使用不如对crontab的使用限制那么严格。
a t命令的基本形式为:
at [-f script] [-m -l -r] [time] [date]
其中,
-f script 是所要提交的脚本或命令。
-l 列出当前所有等待运行的作业。a t q命令具有相同的作用。
-r 清除作业。为了清除某个作业,还要提供相应的作业标识(ID);有些UNIX变体只
接受at rm作为清除命令。
-m 作业完成后给用户发邮件。
time at命令的时间格式非常灵活;可以是H、HH.HHMM、HH:MM或H:M,其中H和M
分别是小时和分钟。还可以使用a.m或p.m。
date 日期格式可以是月份数或日期数,而且a t命令还能够识别诸如today、tomorrow这样的词。
 
3.2.1 使用at命令提交命令或脚本
 如果你想提交若干行的命令,可以在at命令后面跟上日期/时间并回车。然后就进入了at命
令提示符,这时只需逐条输入相应的命令,然后按'<CTRL-D>’退出。下面给出一个例子:
 
$at 21:10
at> find / -name "passwd" -print
at> <EOT>
warning: commands will be executed using /bin/sh
job 1 at 2010-05-04 21:10
 
其中, < EOT>就是<CTRL-D>。在21:10系统将执行一个简单的find命令。你应当已经注
意到,我所提交的作业被分配了一个唯一标识job 1。该命令在完成以后会将全部结果以邮件
的形式发送给我。
 
3.2.2 使用at -l命令列出所提交的作业
$at -l
2 2010-05-04 21:20 a
3 2010-05-05 10:00 a
1 2010-05-04 21:10 a
 
其中,第一行是作业标识,后面是作业运行的日期/时间。最后一列a代表at。还可以使用
atq命令来完成同样的功能,它是at命令的一个链接。
 
 
3.2.3 使用at -r命令删除所提交的作业
清除作业的命令格式为:
atrm [job no]或 at -r [job no]
要清除某个作业,首先要执行at -l命令,以获取相应的作业标识,然后对该作业标识使用
at -r 命令,清除该作业。
 
示例如下:
$at -l
2 2010-05-04 21:20 a
3 2010-05-05 10:00 a
1 2010-05-04 21:10 a
 
$atrm 3
$at -l
2 2010-05-04 21:20 a
1 2010-05-04 21:10 a
 
 
3.3 &命令
命令&
为什么要在后台执行命令?因为当在后台执行命令时,可以继续使用你的终端做其他事
情。适合在后台运行的命令有find、费时的打印作业、费时的排序及一些shell脚本。在后台运
行作业时要当心:需要用户交互的命令不要放在后台执行,因为这样你的机器就会在那里傻等。

不过,作业在后台运行一样会将结果输出到屏幕上,干扰你的工作。如果放在后台运行
的作业会产生大量的输出,最好使用下面的方法把它的输出重定向到某个文件中:
command >out.file 2>&1 &
在上面的例子中,所有的标准输出和错误输出都将被重定向到一个叫做out.file 的文件中。
当你成功地提交进程以后,就会显示出一个进程号,可以用它来监控该进程,或杀死它。
 
 
3.3.1 用ps命令查看进程
当一个命令在后台执行的时候,可以用提交命令时所得到的进程号来监控它的运行。在
前面的例子中,我们可以按照提交ps1时得到的进程号,用ps命令和grep命令列出这个进程:
 
记住,在用ps命令列出进程时,它无法确定该进程是运行在前台还是后台。
 
3.3.2 杀死后台进程
 
如果想杀死后台进程可以使用kill命令。当一个进程被放到后台运行时,shell会给出一个
进程号,我们可以根据这个进程号,用k i l l命令杀死该进程。该命令的基本形式为:
kill -signal [process_number]
现在暂且不要考虑其中的各种不同信号;我们会在后面的章节对这一问题进行介绍。
在杀进程的时候,执行下面的命令(你的进程号可能会不同)并按回车键。系统将会给出相
应的信息告诉用户进程已经被杀死。
 
3.4 nohup命令
 
如果你正在运行一个进程,而且你觉得在退出帐户时该进程还不会结束,那么可以使用
nohup命令。该命令可以在你退出帐户之后继续运行相应的进程。No hup就是不挂起的意思
(no hang up)。
该命令的一般形式为:
nohup command &
 
3.4.1 使用nohup命令提交作业
 
如果使用nohup命令提交作业,那么在缺省情况下该作业的所有输出都被重定向到一个名
为nohup.out的文件中,除非另外指定了输出文件:
nohup command > myout.file 2>&1
在上面的例子中,输出被重定向到myout.file文件中。
 
 
其中,关于《后台执行命令》章节的内容,大部分直接取自原文。
 
 
欢迎转载,转载请注明地址: http://www.360doc.com/showweb/0/0/258767901.aspx

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多