Linux进程管理
每个 Linux 命令都与系统中的程序对应,输入命令,Linux 就会创建一个新的进程。例如使用 ls 命令遍历目录中的文件时,就创建了一个进程。简而言之,进程就是程序的实例。
创建进程
有两种方式来创建进程:前台进程和后台进程。
前台进程:默认情况下,用户创建的进程都是前台进程;前台进程从键盘读取数据,并把处理结果输出到显示器。
查看前台进程的运行过程
[spark@nolonely ~]$ ls *.sh
a.sh b.sh c.sh d.sh e.sh f.sh g.sh
这个程序就运行在前台,它会直接把结果输出到显示器。如果 ls 命令需要数据(实际上不需要),那么它会等待用户从键盘输入。
后台进程
创建后台进程最简单的方式就是在命令的末尾加 &,
spark@nolonely ~]$ ls *.sh & [1] 8196 [spark@nolonely ~]$ a.sh b.sh c.sh d.sh e.sh f.sh g.sh ./a.sh What is your name? yy Hello World!,yy http://www.baidu.com http://www.baidu.com I am good at AdaScript I am good at CoffeScript I am good at ActionScript I am good at JavaScript nihao ./a.sh: line 18: myUrl: readonly variable nihao ./a.sh: line 20: unset: myUrl: cannot unset: readonly variable nihao ./a.sh: line 23: 8197: command not found [1]+ Done ls --color=auto *.sh
查看正在运行的进程
可以使用 ps 命令查看进程的运行状态,包括后台进程,例如:
[spark@nolonely ~]$ ps PID TTY TIME CMD 8114 pts/1 00:00:00 bash 8202 pts/1 00:00:00 ps [spark@nolonely ~]$ ps -f UID PID PPID C STIME TTY TIME CMD spark 8114 8113 0 06:41 pts/1 00:00:00 -bash spark 8203 8114 0 07:21 pts/1 00:00:00 ps -f
每列的含义如下:
列 | 描述 |
---|---|
UID | 进程所属用户的ID,即哪个用户创建了该进程。 |
PID | 进程ID。 |
PPID | 父进程ID,创建该进程的进程称为父进程。 |
C | CPU使用率。 |
STIME | 进程被创建的时间。 |
TTY | 与进程有关的终端类型。 |
TIME | 进程所使用的CPU时间。 |
CMD | 创建该进程的命令。 |
ps 命令还有其他一些选项:
选项 | 说明 |
---|---|
-a | 显示所有用户的所有进程。 |
-x | 显示无终端的进程。 |
-u | 显示更多信息,类似于 -f 选项。 |
-e | 显示所有进程。 |
终止进程
当进程运行在前台时,可以通过 kill 命令或 Ctrl+C 组合键来结束进程。
如果进程运行在后台,那么首先要通过 ps 命令来获取进程ID,然后使用 kill 命令“杀死”进程,例如:
[spark@nolonely ~]$ ps -f UID PID PPID C STIME TTY TIME CMD spark 8114 8113 0 06:41 pts/1 00:00:00 -bash spark 8204 8114 0 07:23 pts/1 00:00:00 ps -f [spark@nolonely ~]$ kill 8113
父进程和子进程:
每个 Linux 进程会包含两个进程ID:当前进程ID(pid)和父进程ID(ppid)。可以暂时认为所有的进程都有父进程。
孤儿进程:但在某些情况下,父进程会在子进程之前被终止,那么这些子进程就没有了“父亲”,被称为孤儿进程。
僵尸进程:如果一个进程被终止了,但是使用 ps 命令仍然可以查看该进程,并且状态为 Z,那么这就是一个僵尸进程。
常驻进程:一般是系统级进程,以 root 权限运行在后台,可以处理其他进程的请求。常驻进程没有终端,不能访问 /dev/tty 文件,如果使用 ps -ef 查看该进程,tty 这一列会显示问号(?)。更确切地说,常驻进程通常运行在后台,等待指定事件发生,例如打印进程是一个常驻进程,它会等待用户输入打印相关的命令并进行处理。
任务和进程的关系:
任务(task)是最抽象的,是一个一般性的术语,指由软件完成的一个活动。一个任务既可以是一个进程,也可以是多个进程。简而言之,它指的是一系列共同达到某一目的的操作。例如,读取数据并将数据放入内存中。这个任务可以由一个进程来实现,也可以由多个进程来实现。 每个任务都有一个数字表示的任务号。
进程(process)常常被定义为程序的执行。可以把一个进程看成是一个独立的程序,在内存中有其完备的数据空间和代码空间。一个进程所拥有的数据和变量只属于它自己。
jobs 命令可以用来查看系统中正在运行的任务,包括后台运行的任务。该命令可以显示任务号及其对应的进程ID。一个任务可以对应于一个或者多个进程号。
$jobs -l #jobs 命令的 -l 选项可以查看当前任务包含的进程ID
[1] + 1903 running ls ch*.doc & #第一列表示任务号,第二列表示任务对应的进程ID,第三列表示任务的运行状态,第四列表示启动任务的命令。
top命令
top 命令是一个很有用的工具,它可以动态显示正在运行的进程,还可以按照指定条件对进程进行排序,与Windows的任务管理器类似。
top 命令可以显示进程的很多信息,包括物理内存、虚拟内存、CPU使用率、平均负载以及繁忙的进程等。
[spark@nolonely ~]$ top
Linux网络通信工具
ping 命令
ping 命令会向网络上的主机发送应答请求,根据响应信息可以判断远程主机是否可用。
ping 命令的语法:
$ping hostname or ip-address
如果网络畅通,很快就可以看到响应信息。
例如,检测是否可以连接到谷歌的主机:
$ping google.com PING google.com (74.125.67.100) 56(84) bytes of data. 64 bytes from 74.125.67.100: icmp_seq=1 ttl=54 time=39.4 ms 64 bytes from 74.125.67.100: icmp_seq=2 ttl=54 time=39.9 ms 64 bytes from 74.125.67.100: icmp_seq=3 ttl=54 time=39.3 ms 64 bytes from 74.125.67.100: icmp_seq=4 ttl=54 time=39.1 ms 64 bytes from 74.125.67.100: icmp_seq=5 ttl=54 time=38.8 ms --- google.com ping statistics --- 22 packets transmitted, 22 received, 0% packet loss, time 21017ms rtt min/avg/max/mdev = 38.867/39.334/39.900/0.396 ms $
如果主机没有响应,可以看到类似下面的信息:
$ping giiiiiigle.com ping: unknown host giiiiigle.com $
ftp 工具
(有的linux系统没有改命令,需要自己安装该命令)
先用命令rpm -q vsftpd检查是否安装了ftp服务器
若显示vsftpd-2.2.2-11.el6_4.1.x86_64这样的信息,说明FTP服务器已安装,那为什么FTP命令不能用呢,那是FTP客户端没安装的缘故。
下载ftp-0.17-51.1.el6.x86_64.rpm,下载地址有:http://rpm.pbone.net/index.php3/stat/4/idpl/15988817/dir/scientific_linux_6/com/ftp-0.17-51.1.el6.x86_64.rpm.html;
安装FTP客户端命令:rpm -ivh ftp-0.17-51.1.el6.x86_64.rpm
这样就可以正常使用ftp命令了。
ftp 是 File Transfer Protocol 的缩写,称为文件传输协议。通过 ftp 工具,能够将文件上传到远程服务器,也可以从远程服务器下载文件。
ftp 工具有自己的命令(类似Linux命令),可以:
- 连接并登录远程主机;
- 查看目录,遍历目录下的文件;
- 上传或下载文件,包括文本文件、二进制文件等。
ftp 命令的用法如下:
$ftp hostname or ip-address
接下来会提示你输入用户名和密码,验证成功后会进入主目录,然后就可以使用 ftp 工具的命令进行操作了。
ftp命令 | 说明 |
---|---|
put filename | 将本地文件上传到远程主机。 |
get filename | 将远程文件下载到本地。 |
mput file list | 将多个本地文件上传到远程主机。 |
mget file list | 将多个远程文件下载到本地。 |
prompt off | 关闭提示。默认情况下,使用 mput 或 mget 命令会不断提示你确认文件的上传或下载。 |
prompt on | 打开提示。 |
dir | 列出远程主机当前目录下的所有文件。 |
cd dirname | 改变远程主机目录。 |
lcd dirname | 改变本地目录。 |
quit | 退出登录。 |
注意,所有的上传和下载都是针对本地主机和远程主机的当前目录,如果你希望上传指定目录下的文件,首先要 cd 到该目录,然后才能上传。
ftp 工具使用举例:
$ftp amrood.com Connected to amrood.com. 220 amrood.com FTP server (Ver 4.9 Thu Sep 2 20:35:07 CDT 2009) Name (amrood.com:amrood): amrood 331 Password required for amrood. Password: 230 User amrood logged in. ftp> dir 200 PORT command successful. 150 Opening data connection for /bin/ls. total 1464 drwxr-sr-x 3 amrood group 1024 Mar 11 20:04 Mail drwxr-sr-x 2 amrood group 1536 Mar 3 18:07 Misc drwxr-sr-x 5 amrood group 512 Dec 7 10:59 OldStuff drwxr-sr-x 2 amrood group 1024 Mar 11 15:24 bin drwxr-sr-x 5 amrood group 3072 Mar 13 16:10 mpl -rw-r--r-- 1 amrood group 209671 Mar 15 10:57 myfile.out drwxr-sr-x 3 amrood group 512 Jan 5 13:32 public drwxr-sr-x 3 amrood group 512 Feb 10 10:17 pvm3 226 Transfer complete. ftp> cd mpl 250 CWD command successful. ftp> dir 200 PORT command successful. 150 Opening data connection for /bin/ls. total 7320 -rw-r--r-- 1 amrood group 1630 Aug 8 1994 dboard.f -rw-r----- 1 amrood group 4340 Jul 17 1994 vttest.c -rwxr-xr-x 1 amrood group 525574 Feb 15 11:52 wave_shift -rw-r--r-- 1 amrood group 1648 Aug 5 1994 wide.list -rwxr-xr-x 1 amrood group 4019 Feb 14 16:26 fix.c 226 Transfer complete. ftp> get wave_shift 200 PORT command successful. 150 Opening data connection for wave_shift (525574 bytes). 226 Transfer complete. 528454 bytes received in 1.296 seconds (398.1 Kbytes/s) ftp> quit 221 Goodbye. $
telnet工具
Telnet 工具可以让我们连接并登录到远程计算机。
一旦连接到了远程计算机,就可以在上面进行各种操作了,例如:
C:>telnet amrood.com Trying... Connected to amrood.com. Escape character is '^]'. login: amrood amrood's Password: ***************************************************** * * * * * WELCOME TO AMROOD.COM * * * * * ***************************************************** Last unsuccessful login: Fri Mar 3 12:01:09 IST 2009 Last login: Wed Mar 8 18:33:27 IST 2009 on pts/10 { do your work } $ logout Connection closed. C:>
finger工具
finger 可以让我们查看本地主机或远程主机上的用户信息。有些系统为了安全会禁用 finger 命令。
例如,查看本机在线用户:
$ finger Login Name Tty Idle Login Time Office amrood pts/0 Jun 25 08:03 (62.61.164.115)
查看本机指定用户的信息:
$ finger amrood Login: amrood Name: (null) Directory: /home/amrood Shell: /bin/bash On since Thu Jun 25 08:03 (MST) on pts/0 from 62.61.164.115 No mail. No Plan.
查看远程主机上的在线用户:
$ finger @avtar.com Login Name Tty Idle Login Time Office amrood pts/0 Jun 25 08:03 (62.61.164.115)
查看远程主机上某个用户的信息:
$ finger amrood@avtar.com Login: amrood Name: (null) Directory: /home/amrood Shell: /bin/bash On since Thu Jun 25 08:03 (MST) on pts/0 from 62.61.164.115 No mail. No Plan.
Linux文件系统
文件系统就是分区或磁盘上的所有文件的逻辑集合。
文件系统不仅包含着文件中的数据而且还有文件系统的结构,所有Linux 用户和程序看到的文件、目录、软连接及文件保护信息等都存储在其中。
不同Linux发行版本之间的文件系统差别很少,主要表现在系统管理的特色工具以及软件包管理方式的不同,文件目录结构基本上都是一样的。
文件系统有多种类型,如:
- ext2 : 早期linux中常用的文件系统;
- ext3 : ext2的升级版,带日志功能;
- RAMFS : 内存文件系统,速度很快;
- iso9660:光盘或光盘镜像;
- NFS : 网络文件系统,由SUN发明,主要用于远程文件共享;
- MS-DOS : MS-DOS文件系统;
- FAT : Windows XP 操作系统采用的文件系统;
- NTFS : Windows NT/XP 操作系统采用的文件系统。
分区与目录
文件系统位于磁盘分区中;一个硬盘可以有多个分区,也可以只有一个分区;一个分区只能包含一个文件系统。
Linux文件系统与Windows有较大的差别。Windows的文件结构是多个并列的树状结构,最顶部的是不同的磁盘(分区),如 C、D、E、F等。
Linux的文件结构是单个的树状结构,根目录是“/”,其他目录都要位于根目录下。
每次安装系统的时候我们都会进行分区,Linux下磁盘分区和目录的关系如下:
- 任何一个分区都必须对应到某个目录上,才能进行读写操作,称为“挂载”。
- 被挂载的目录可以是根目录,也可以是其他二级、三级目录,任何目录都可以是挂载点。
- 目录是逻辑上的区分。分区是物理上的区分。
- 根目录是所有Linux的文件和目录所在的地方,需要挂载上一个磁盘分区。
下图是常见的目录和分区的对应关系:
为什么要分区,如何分区?
- 可以把不同资料,分别放入不同分区中管理,降低风险。
- 大硬盘搜索范围大,效率低。
- /home、/var、/usr/local 经常是单独分区,因为经常会操作,容易产生碎片。
为了便于定位和查找,Linux中的每个目录一般都存放特定类型的文件,下表列出了各种Linux发行版本的常见目录:
目录 | 说明 |
---|---|
/ | 根目录,只能包含目录,不能包含具体文件。 |
/bin | 存放可执行文件。很多命令就对应/bin目录下的某个程序,例如 ls、cp、mkdir。/bin目录对所有用户有效。 |
/dev | 硬件驱动程序。例如声卡、磁盘驱动等,还有如 /dev/null、/dev/console、/dev/zero、/dev/full 等文件。 |
/etc | 主要包含系统配置文件和用户、用户组配置文件。 |
/lib | 主要包含共享库文件,类似于Windows下的DLL;有时也会包含内核相关文件。 |
/boot | 系统启动文件,例如Linux内核、引导程序等。 |
/home | 用户工作目录(主目录),每个用户都会分配一个目录。 |
/mnt | 临时挂载文件系统。这个目录一般是用于存放挂载储存设备的挂载目录的,例如挂载CD-ROM的cdrom目录。 |
/proc | 操作系统运行时,进程(正在运行中的程序)信息及内核信息(比如cpu、硬盘分区、内存信息等)存放在这里。/proc目录伪装的文件系统proc的挂载目录,proc并不是真正的文件系统。 |
/tmp | 临时文件目录,系统重启后不会被保存。 |
/usr | /user目下的文件比较混杂,包含了管理命令、共享文件、库文件等,可以被很多用户使用。 |
/var | 主要包含一些可变长度的文件,会经常对数据进行读写,例如日志文件和打印队列里的文件。 |
/sbin | 和 /bin 类似,主要包含可执行文件,不过一般是系统管理所需要的,不是所有用户都需要。 |
常用文件管理命令
你可以通过下面的命令来管理文件:
Command | Description |
---|---|
cat filename | 查看文件内容。 |
cd dirname | 改变所在目录。 |
cp file1 file2 | 复制文件或目录。 |
file filename | 查看文件类型(binary, text, etc)。 |
find filename dir | 搜索文件或目录。 |
head filename | 显示文件的开头,与tail命令相对。 |
less filename | 查看文件的全部内容,可以分页显示,比more命令要强大。 |
ls dirname | 遍历目录下的文件或目录。 |
mkdir dirname | 创建目录。 |
more filename | 查看文件的全部内容,可以分页显示。 |
mv file1 file2 | 移动文件或重命名。 |
pwd | 显示用户当前所在目录。 |
rm filename | 删除文件。 |
rmdir dirname | 删除目录。 |
tail filename | 显示文件的结尾,与head命令相对。 |
touch filename | 文件不存在时创建一个空文件,存在时修改文件时间戳。 |
whereis filename | 查看文件所在位置。 |
which filename | 如果文件在环境变量PATH中有定义,那么显示文件位置。 |
df命令
管理磁盘分区时经常会使用 df (disk free) 命令,df -k 命令可以用来查看磁盘空间的使用情况(以千字节计),例如:
$df -k Filesystem 1K-blocks Used Available Use% Mounted on /dev/vzfs 10485760 7836644 2649116 75% / /devices 0 0 0 0% /devices $
每一列的含义如下:
列 | 说明 |
---|---|
Filesystem | 代表文件系统对应的设备文件的路径名(一般是硬盘上的分区)。 |
kbytes | 分区包含的数据块(1024字节)的数目。 |
used | 已用空间。 |
avail | 可用空间。 |
capacity | 已用空间的百分比。 |
Mounted on | 文件系统挂载点。 |
某些目录(例如 /devices)的 kbytes、used、avail 列为0,use列为0%,这些都是特殊(或虚拟)文件系统,即使位于根目录下,也不占用硬盘空间。
你可以结合 -h (human readable) 选项将输出信息格式化,让人更易阅读。
du 命令
du (disk usage) 命令可以用来查看特定目录的空间使用情况。
du 命令会显示每个目录所占用数据块。根据系统的不同,一个数据块可能是 512 字节或 1024 字节。举例如下:
$du /etc 10 /etc/cron.d 126 /etc/default 6 /etc/dfs ... $
结合 -h 选项可以让信息显示的更加清晰:
$du -h /etc 5k /etc/cron.d 63k /etc/default 3k /etc/dfs ... $
挂载文件系统
挂载是指将一个硬件设备(例如硬盘、U盘、光盘等)对应到一个已存在的目录上。 若要访问设备中的文件,必须将文件挂载到一个已存在的目录上, 然后通过访问这个目录来访问存储设备。
这样就为用户提供了统一的接口,屏蔽了硬件设备的细节。Linux将所有的硬件设备看做文件,对硬件设备的操作等同于对文件的操作。
注意:挂载目录可以不为空,但挂载后这个目录下以前的内容将不可用。
需要知道的是,光盘、软盘、其他操作系统使用的文件系统的格式与linux使用的文件系统格式是不一样的,挂载需要确认Linux是否支持所要挂载的文件系统格式。
查看当前系统所挂载的硬件设备可以使用 mount 命令:
$ mount /dev/vzfs on / type reiserfs (rw,usrquota,grpquota) proc on /proc type proc (rw,nodiratime) devpts on /dev/pts type devpts (rw) $
一般约定,/mnt 为临时挂载目录,例如挂载CD-ROM、远程网络设备、软盘等。
也可以通过mount命令来挂载文件系统,语法为:
mount -t file_system_type device_to_mount directory_to_mount_to
例如:
$ mount -t iso9660 /dev/cdrom /mnt/cdrom
将 CD-ROM 挂载到 /mnt/cdrom 目录。
注意:file_system_type用来指定文件系统类型,通常可以不指定,Linux会自动正确选择文件系统类型。
挂载文件系统后,就可以通过 cd、cat 等命令来操作对应文件。
可以通过 umount 命令来卸载文件系统。例如,卸载 cdrom:
$ umount /dev/cdrom
不过,大部分现代的Linux系统都有自动挂载卸载功能,unmount 命令较少用到。
用户和群组配额
用户和群组配额可以让管理员为每个用户或群组分配固定的磁盘空间。
管理员有两种方式来分配磁盘空间:
- 软限制:如果用户超过指定的空间,会有一个宽限期,等待用户释放空间。
- 硬限制:没有宽限期,超出指定空间立即禁止操作。
下面的命令可以用来管理配额:
命令 | 说明 |
---|---|
quota | 显示磁盘使用情况以及每个用户组的配额。 |
edquota | 编辑用户和群组的配额。 |
quotacheck | 查看文件系统的磁盘使用情况,创建、检查并修复配额文件。 |
setquota | 设置配额。 |
quotaon | 开启用户或群组的配额功能。 |
quotaoff | 关闭用户或群组的配额功能。 |
repquota | 打印指定文件系统的配额。 |
Linux文件存储结构,包括目录项、inode、数据块
大部分的Linux文件系统(如ext2、ext3)规定,一个文件由目录项、inode和数据块组成:
- 目录项:包括文件名和inode节点号。
- Inode:又称文件索引节点,包含文件的基础信息以及数据块的指针。
- 数据块:包含文件的具体内容。
先说inode
理解inode,要从文件储存说起。文件储存在硬盘上,硬盘的最小存储单位叫做"扇区"(Sector),每个扇区储存512字节(相当于0.5KB)。
操作系统读取硬盘的时候,不会一个扇区一个扇区地读取,这样效率太低,而是一次性连续读取多个扇区,即一次性读取一个"块"(block)。这种由多个扇区组成的"块",是文件存取的最小单位。"块"的大小,最常见的是4KB,即连续八个
sector组成一个 block。
文件数据都储存在"块"中,那么很显然,我们还必须找到一个地方储存文件的元信息,比如文件的创建者、文件的创建日期、文件的大小等等。这种储存文件元信息的区域就叫做inode,中文译名为"索引节点"。
inode包含文件的元信息,具体来说有以下内容:
- 文件的字节数。
- 文件拥有者的User ID。
- 文件的Group ID。
- 文件的读、写、执行权限。
- 文件的时间戳,共有三个:ctime指inode上一次变动的时间,mtime指文件内容上一次变动的时间,atime指文件上一次打开的时间。
- 链接数,即有多少文件名指向这个inode。
- 文件数据block的位置。
可以用stat命令,查看某个文件的inode信息:
stat demo.txt
总之,除了文件名以外的所有文件信息,都存在inode之中。至于为什么没有文件名,下文会有详细解释。
当查看某个文件时,会先从inode表中查出文件属性及数据存放点,再从数据块中读取数据。
请看文件存储结构示意图:
inode的大小
inode也会消耗硬盘空间,所以硬盘格式化的时候,操作系统自动将硬盘分成两个区域。一个是数据区,存放文件数据;另一个是inode区(inode table),存放inode所包含的信息。
每个inode节点的大小,一般是128字节或256字节。inode节点的总数,在格式化时就给定,一般是每1KB或每2KB就设置一个inode。假定在一块1GB的硬盘中,每个inode节点的大小为128字节,每1KB就设置一个inode,那么inode
table的大小就会达到128MB,占整块硬盘的12.8%。
查看每个硬盘分区的inode总数和已经使用的数量,可以使用df -i 命令。
查看每个inode节点的大小,可以用如下命令:
sudo dumpe2fs -h /dev/hda | grep "Inode size"
由于每个文件都必须有一个inode,因此有可能发生inode已经用光,但是硬盘还未存满的情况。这时,就无法在硬盘上创建新文件。
inode号码
每个inode都有一个号码,操作系统用inode号码来识别不同的文件。
这里值得重复一遍,Linux系统内部不使用文件名,而使用inode号码来识别文件。对于系统来说,文件名只是inode号码便于识别的别称或者绰号。表面上,用户通过文件名,打开文件。实际上,系统内部这个过程分成三步:首先,系统找到这个文件名对应的inode号码;其次,通过inode号码,获取inode信息;最后,根据inode信息,找到文件数据所在的block,读出数据。
使用ls -i命令,可以看到文件名对应的inode号码,例如:
ls -i demo.txt
目录项
Linux系统中,目录(directory)也是一种文件。打开目录,实际上就是打开目录文件。
目录文件的结构非常简单,就是一系列目录项(dirent)的列表。每个目录项,由两部分组成:所包含文件的文件名,以及该文件名对应的inode号码。
ls命令只列出目录文件中的所有文件名:
ls /etc
ls -i命令列出整个目录文件,即文件名和inode号码:
ls -i /etc
如果要查看文件的详细信息,就必须根据inode号码,访问inode节点,读取信息。ls -l命令列出文件的详细信息。
ls -l /etc
硬链接和软链接
硬链接
一般情况下,文件名和inode号码是"一一对应"关系,每个inode号码对应一个文件名。但是,Linux系统允许,多个文件名指向同一个inode号码。这意味着,可以用不同的文件名访问同样的内容;对文件内容进行修改,会影响到所有文件名;但是,删除一个文件名,不影响另一个文件名的访问。这种情况就被称为"硬链接"(hard link)。
ln命令可以创建硬链接,语法为:
ln source_file target_file
运行上面这条命令以后,源文件与目标文件的inode号码相同,都指向同一个inode。inode信息中有一项叫做"链接数",记录指向该inode的文件名总数,这时就会增加1。反过来,删除一个文件名,就会使得inode节点中的"链接数"减1。当这个值减到0,表明没有文件名指向这个inode,系统就会回收这个inode号码,以及其所对应block区域。
这里顺便说一下目录文件的"链接数"。创建目录时,默认会生成两个目录项:"."和".."。前者的inode号码就是当前目录的inode号码,等同于当前目录的"硬链接";后者的inode号码就是当前目录的父目录的inode号码,等同于父目录的"硬链接"。所以,任何一个目录的"硬链接"总数,总是等于2加上它的子目录总数(含隐藏目录),这里的2是父目录对其的“硬链接”和当前目录下的".硬链接“。
软链接
除了硬链接以外,还有一种特殊情况。文件A和文件B的inode号码虽然不一样,但是文件A的内容是文件B的路径。读取文件A时,系统会自动将访问者导向文件B。因此,无论打开哪一个文件,最终读取的都是文件B。这时,文件A就称为文件B的"软链接"(soft
link)或者"符号链接(symbolic link)。
这意味着,文件A依赖于文件B而存在,如果删除了文件B,打开文件A就会报错:"No such file or
directory"。这是软链接与硬链接最大的不同:文件A指向文件B的文件名,而不是文件B的inode号码,文件B的inode"链接数"不会因此发生变化。
ln -s命令可以创建软链接,语法为:
ln source_file target_file
Linux用户管理
在Linux中,有三种用户:
- Root 用户:也称为超级用户,对系统拥有完全的控制权限。超级用户可以不受限制的运行任何命令。Root 用户可以看做是系统管理员。
- 系统用户:系统用户是Linux运行某些程序所必须的用户,例如 mail 用户、sshd 用户等。系统用户通常为系统功能所必须的,不建议修改这些用户。
- 普通用户:一般用户都是普通用户,这些用户对系统文件的访问受限,不能执行全部Linux命令。
Linux支持用户组,用户组就是具有相同特征的用户的集合。一个组可以包含多个用户,每个用户也可以属于不同的组。用户组在Linux中扮演着重要的角色,方便管理员对用户进行集中管理。
与用户和组有关的系统文件
与用户和组有关的系统文件:
系统文件 | 说明 |
---|---|
/etc/passwd | 保存用户名和密码等信息,Linux系统中的每个用户都在/etc/passwd文件中有一个对应的记录行。这个文件对所有用户都是可读的。 |
/etc/shadow | /etc/shadow中的记录行和/etc/passwd中的相对应,他由pwconv命令根据/etc/passwd中的数据自动产生,它的格式和/etc/passwd类似,只是对密码进行了加密。并不是所有的系统都支持这个文件。 |
/etc/group | 以记录行的形式保存了用户组的所有信息。 |
来看一下/etc/passwd文件的结构:
$cat /etc/passwd root:x:0:0:Superuser:/: daemon:x:1:1:System daemons:/etc: bin:x:2:2:Owner of system commands:/bin: sys:x:3:3:Owner of system files:/usr/sys: adm:x:4:4:System accounting:/usr/adm: uucp:x:5:5:UUCP administrator:/usr/lib/uucp: auth:x:7:21:Authentication administrator:/tcb/files/auth: cron:x:9:16:Cron daemon:/usr/spool/cron: listen:x:37:4:Network daemon:/usr/net/nls: lp:x:71:18:printer administrator:/usr/spool/lp: sam:x:200:50:Sam san:/usr/sam:/bin/sh
可以看到,/etc/passwd文件中一行记录对应着一个用户,每行记录又被冒号分隔为7个字段,其格式和具体含义如下图所示:
对每个字段的说明:
字段 | 说明 |
---|---|
用户名 | 用户名是惟一的,长度根据不同的linux系统而定,一般是8位。 |
密码 | 由于系统中还有一个/etc/shadow文件用于存放加密后的口令,所以在这里这一项是“x”来表示,如果用户没有设置口令,则该项为空。如果passwd字段中的第一个字符是“*”的话,那么,就表示该账号被查封了,系统不允许持有该账号的用户登录。 |
用户ID |
系统内部根据用户ID而不是用户名来识别不同的用户,用户ID有以下几种:
|
组ID | 其实这个和用户ID差不多,用来管理群组,与/etc/group文件相关。 |
描述信息 | 这个字段几乎没有什么用,只是用来解释这个账号的意义。在不同的Linux系统中,这个字段的 格式并没有统一。在许多Linux系统中,这个字段存放的是一段任意的注释性描述文字,用做finger命令的输出。 |
用户主目录 | 用户登录系统的起始目录。用户登录系统后将首先进入该目录。root用户默认是/,普通用户是/home/username。 |
用户Shell | 用户登录系统时使用的Shell。 |
管理用户和组
下面是一些常用的管理用户和组的命令:
命令 | 说明 |
---|---|
useradd | 添加用户。 |
usermod | 修改用户信息。 |
userdel | 删除用户。 |
groupadd | 添加用户组。 |
groupmod | 修改用户组信息。 |
groupdel | 删除用户组。 |
创建用户组
添加用户时,可以将用户添加到现有的用户组,或者创建一个新的用户组。可以在 /etc/groups 文件中看到所有的用户组信息。
默认的用户组通常用来管理系统用户,不建议将普通用户添加到这些用户组。使用groupadd命令创建用户组的语法为:
groupadd [-g gid [-o]] [-r] [-f] groupname
每个选项的含义如下:
选项 | 说明 |
---|---|
-g GID | 以数字表示的用户组ID。 |
-o | 可以使用重复的组ID。 |
-r | 建立系统组,用来管理系统用户。 |
-f | 强制创建。 |
groupname | 用户组的名称。 |
如果不指定选项,系统将使用默认值。例如创建一个 developers 用户组:
$ groupadd developers
修改用户组
groupmod命令可以用来修改用户组,语法为:
$ groupmod -n new_modified_group_name old_group_name
例如,将用户组 developers_2 重命名为 developer:
$ groupmod -n developer developer_2
将developer用户组的ID改为545:
$ groupmod -g 545 developer
删除用户组
通过groupdel命令可以删除用户组。例如,删除developer组:
$ groupdel developer
groupdel 仅仅删除用户组,并不删除与之相关的文件,这些文件仍然可以被所有者访问。
添加用户
添加用户可以使用useradd命令,语法为:
useradd -d homedir -g groupname -m -s shell -u userid accountname
每个选项的含义如下:
选项 | 描述 |
---|---|
-d homedir | 指定用户主目录。 |
-g groupname | 指定用户组。 |
-m | 如果主目录不存在,就创建。 |
-s shell | 为用户指定默认Shell。 |
-u userid | 指定用户ID。 |
accountname | 用户名。 |
如果不指定任何选项,系统将使用默认值。useradd 命令将会修改 /etc/passwd、/etc/shadow、and /etc/group 三个文件,并创建用户主目录。
下面的例子将会添加用户 mcmohd,并设置主目录为 /home/mcmohd,用户组为 developers,默认 Shell 为 Korn Shell:
$ useradd -d /home/mcmohd -g developers -s /bin/ksh mcmohd
注意:添加用户前请确认 developers 用户组存在。
用户被创建后,可以使用 passwd 命令来设置密码,例如:
$ passwd mcmohd20 Changing password for user mcmohd20. New Linux password:****** Retype new UNIX password:****** passwd: all authentication tokens updated successfully.
注意:如果你是管理员,输入 $ passwd username 可以修改你所管理的用户的密码;否则只能修改你自己的密码(不需要提供username)。
修改用户
usermod 命令可以修改现有用户的信息。usermod 命令的选项和 useradd 相同,不过可以增加 -l 选项来更改用户名。
下面的例子将用户 mcmohd 的用户名修改为 mcmohd20,主目录修改为 /home/mcmohd20:
$ usermod -d /home/mcmohd20 -m -l mcmohd mcmohd20
删除用户
userdel 命令可以用来删除现有用户。userdel 是一个危险的命令,请谨慎使用。
userdel 命令仅有一个选项 -r,用来删除用户主目录和本地邮件。例如,删除用户 mcmohd20:
$ userdel -r mcmohd20
为了便于恢复被误删的用户,可以忽略 -r 选项,保留用户主目录,之后确认无误可以随时删除主目录。