基于递归学习的原则,这里把长久以来一直不清楚其作用区别的几个文件(夹)弄清楚一下:

(本文暂时不讨论相应网络配置命令工具)

环境:

以Redhat Enterprise 7.1 64-bit为主

另外会把 Utuntu 14.04 LTS 64-bit 的差异之处在注释里指出

涉及到的文件:

第一类

/etc/environment
/etc/profile /etc/profile.d/ # 这两个有很大联系,放在一起,具体见后文
/etc/bashrc # Ubuntu 14.04上是/etc/bash.bashrc
~/.bash_profile # Ubuntu 14.04上是~/.profile
~/.bashrc
~/.bash_login
~/.bash_logout

第二类

/etc/passwd
/etc/shadow
/etc/group

第三类

/etc/hostname
/etc/host.conf
/etc/resolv.conf
/etc/hosts
/etc/sysconfig/network
/etc/sysconfig/network-scripts/ifcfg-INTERFACENAME
/etc/networks # 参照 man networks
/etc/services
/etc/protocols

第四类

/etc/inittab
/etc/rc.d/
/etc/rc.d/rc
/etc/rc.d/rc.local
/etc/rc.d/rc.sysinit
/etc/rc.d/init.d/
/etc/rc0.d/ ~ /etc/rc6.d/

第五类

/etc/fstab

交互式/非交互式/登录/非登录+shell

在一切开始之前我们要先了解题目所述的这几个概念。在讲述这些概念之前,我要先提一下FHS,也就是LInux文件系统层次标准(Filesystem Hierarchy Standard)。该标准把文件系统划中的目录按照两个标准划分:静态还是动态;是否可共享。

比如下面的一个遵循FHS的文件系统划分:

共享 不可共享
静态 /usr /etc
动态 /var/mail /var/run

这里不再详细叙述FHS。类比来说,我们可以得到3种不同类型的shell:交互式登录,交互式非登录,非交互式。非交互式shell意为将shell语句写在x.sh脚本中通过bash x.sh或者./x.sh执行,所以它没有登录不登录的区分。交互式意味着你像使用Python解释器在»>后面输入命令那样与shell交互,这种情况下,登录shell意味着你的shell需要输入账号密码才可以继续后面的操作,非登录shell就是你在图形化界面中打开的一个terminal窗口,比如在Ubuntu14.04下同时按下[Ctrl] + [Alt] + [T]打开的那个东西。

xxx和xxx.d/

有时候我们会发现名为xxx的文件对应一个xxx.d/的文件夹存在。根据个人经验,有一种情况是xxx和xxx.d/下存放的都是对应程序的配置文件,其中xxx类似于主配置文件,在执行时会以某种方式将xxx.d/中的其他配置文件也加载进去。

举个例子,Ubuntu14.04 LTS的/etc/profile文件中有这样一段代码(Redhat 7.1中也有相似代码,不再列出):

if [ -d /etc/profile.d ]; then
  for i in /etc/profile.d/*.sh; do
    if [ -r $i ]; then
      . $i # . is equal to [source]
    fi
  done
  unset i
fi

另一个例子,Redhat 7.1中Apache目录/etc/httpd/中有一个文件/etc/httpd/conf/httpd.conf,另有一个目录/etc/httpd/conf.d/ 在httpd.conf中有这样一段代码:

IncludeOptional conf.d/*.conf

关于第一类文件

先放上一张很好的图,图片来自参考资料中第一篇文章。

43C48BD1EE606C8E0A6E5F81438AB7

说白了它们都是些启动shell时的配置脚本。上图与具体的发行版中可能有所差异,但大体是这样。在.bash_profile文件中,的的确确有. ~/.bashrc这样的调用语句。另外按照参考资料中IBM知识库的说法,在log in后系统会先调用/etc/environment,然后再调用/etc/profile。在Redhat中脚本注释里可以看到,/etc/bashrc与/etc/profile基本上是同级各司其职的。下面是两个文件中的部分注释:

# /etc/bashrc
System wide functions and aliases
Environment stuff goes in /etc/profile

# /etc/profile
System wide environment and startup programs, for login setup
Functions and aliases go in /etc/bashrc

Redhat下的/etc/bashrc写的很有意思,它先判断当前是不是交互式shell,是就执行一些命令;再判断是不是非登录shell,又执行一些命令。Ubuntu14.04下的/etc/bash.bashrc则判断如果不是交互式shell直接返回。

那么问题来了,脚本怎么判断你是不是交互式shell呢?

通过检测 $PS1 这个环境变量,如果是非交互式,则 $PS1 为空。

那么问题来了,脚本怎么判断你是不是登录shell呢?

通过shopt -q login_shell的返回值判断。

可以测试一下,在图形化界面下打开一个终端,输入下面的,则什么都没有出现;

shopt -q login_shell && echo "hello"

输入下面的,则会打印"hello"。

! shopt -q login_shell && echo "hello"

另外,在开机时的文字版终端登录shell下结果恰好相反。

而 .bash_logout 则是在交互式登录型shell logout时执行的脚本。

那么问题来了,是谁记录了开启一个shell需要调用这些文件,以及这些文件的调用顺序呢?是谁告诉操作系统的呢?(我们暂不去探究是谁生成了这些文件,因为它们可能是系统安装时生成的)

刚开始我一直很迷茫,网上教程都说是操作系统,那么操作系统的具体体现又是谁呢?于是找了几篇研究Linux启动流程的文章,发现最后一步是login程序,登陆成功则它会运行bash并设置一些环境。所以,是谁知道要去找那些/etc/profile之类的文件?是bash?于是我下载了一个版本的bash源码,在里边grep -nr '/etc/profile',果然找到了不少结果,还有/etc/bashrc等等。所以,就是bash了!是它干的!

关于第二类文件

这三个文件至关重要。group记录系统中用户组,passwd记录用户及类型等信息,shadow记录对应密码。早期passwd和shadow存放在一个文件中,后来为了安全考虑分开放置。具体内容不再详述,因为在*nix上你可以随时打开看这些文件,并且网上关于*nix配置文件的文章中,讲这三个文件的应该是最多了。最关键的是,它们没什么难以理解的地方。需要注意的是,如果你是正常用户,不要试图通过直接修改这些文件去对用户和用户组进行修改。添加用户,删除用户,添加用户组等等都有对应的shell命令(或者叫工具更恰当一些)。

关于第三类文件

这些文件基本上都与网络通信有关。

对于/etc/hostname可以参照Redhat官方解释:

There are three classes of hostname: static, pretty, and transient.
The “static” host name is the traditional hostnam e, which can be chosen by the user, and is stored in the
/etc/hostname file. The “transient” hostname is a dynamic host name maintained by the kernel. It is
initialized to the static host name by default, whose value defaults to “localhost”. It can be changed by
DHCP or mDNS at runtime. The “pretty” hostname is a free-form UT-F8 host name for presentation to the
user.

相对来说,Redhat官方文档更加准确,所以后面能够用Redhat official doc解释的我都会摘录或复述。

/etc/hosts相当于静态IP-域名对应关系列表;

与之对应的是/etc/resolv.conf文件,其中

nameserver xxx.xxx.xxx.xxx

是对DNS服务器IP的设置。这个是动态地查询对应域名的IP。

那么到底是通过静态还是动态查询?谁先?这个由/etc/host.conf来指定。一般来说,该文件可以有下面的内容:

order  bind,hosts
multi  on
nospoof  on

第一行指定动静的顺序。上面的是先DNS解析,后采用静态列表查询的形式。

第二行指的是是否允许/etc/hosts中的主机有多个IP地址。由于hosts文件中也有我们自己的PC,而笔记本电脑一般既会有有线网卡也有无线网卡,所以可能又多个IP,所以这个地方设置为on。

第三行指的是是否允许IP欺骗攻击。这里有个小坑,网上的一般资料讲的不是很清楚,以后见到再提。

参照官方文档,/etc/sysconfig/network是对全局网络的设定,/etc/sysconfig/network-scripts/ifcfg-INTERFACENAME是针对具体网卡的设定。这也是为什么在网上一些文章中会看到GATEWAY=xxx.xxx.xxx.xxx会出现在两个配置文件中。在启动时,/etc/init.d/network读取所有的ifcfg文件,对于每一个有ONBOOT=yes字样的文件,它会检测NetworkManager是否已经开启对应设备。如果已开启,则检测下一个;如果没有,则调用ifup去根据ifcfg文件开启对应Interface。

另外,同C语言里的同名变量之间关系类似,局部配置文件与全局配置文件有底层屏蔽高层的效果。

参照man protocols,/etc/protocols是网络协议定义文件,里面记录了TCP/IP协议族的所有协议类型。文件中的每一行对应一个协议类型,它有3个字段,中间用TAB或空格分隔,分别表示“协议名称”、“协议号”和“协议别名”(注意协议号不等于端口号)。

参照man services,/etc/services提供网络服务名和它们使用的端口号及协议的对应关系。

端口号分配:

0 不使用
1---1023 系统保留,只能由root用户使用
1024---4999 由客户端程序自由分配
5000---65535 由服务器端程序自由分配

关于第四类文件

第四类文件才真真正正是我想要写这篇文章的深刻缘由,因为被它们搞晕好久了。

/etc/inittab告诉init(系统的根进程)使系统进入哪一种Runlevel,在/etc/inittab注释中我们可以看到各个不同level的含义:

0 - halt
1 - Single user mode
2 - Multiuser, without NFS
3 - Fullmultiuser mode
4 - unused
5 - X11
6 - reboot

由于Redhat装在虚拟机里,虚拟机镜像在移动硬盘里,移动硬盘又不在我身边,所以下面以CentOS6.0为例。

在CentOS 6.0中,该文件的配置语句只有一行id 3 initdefault,也就是告诉init进入runlevel 3。

So? 进入runlevel具体是什么意思?这就涉及到/etc/rc.d/这个目录了。首先要讲清楚,在/etc/rc.d/下有init.d/目录,rc0.d/ ~ rc6.d/目录,rc.local文件,rc.sysinit,还有一个Bash脚本rc,但你在/etc/下面也会找到具有这些名字的相同文件。事实上,/etc/目录下的init.d/目录,rc.local文件,rc.sysinit,rc均是指向/etc/rc.d/下同名文件的软链接。而/etc/rc0.d/ ~ rc6.d/ 中的文件又都是指向/etc/init.d/中文件的软链接(类似的,/etc/rc.d/下面的rc0.d/ ~ rc6.d/内部文件也是指向/etc/rc.d/init.d/中文件的软链接)。所以只有/etc/rc.d/是货真价实的。

另外,以rc3.d/为例,其中的文件要么以S开头,要么以K开头。以S开头代表要启动该服务,以K开头代表要停止该服务。字母后面带的数字是执行顺序。

系统初始化时会先运行/etc/rc.d/rc.sysinit,然后通过/etc/rc.d/rc脚本去执行不同的runlevel配置,然后是执行/etc/rc.d/rc.local(网文说只有runlevel 2 3 5最后会执行rc.local内容)。用户可以把自己的命令写在rc.local中实现开机执行。

关于第五类文件

/etc/fstab记录文件系统的信息,只能由root用户编辑。fsck、mount、umount等命令都利用该文件。它决定一个分区或者硬盘怎样被使用。

小结

分析*nix下的配置文件有一个比较烦的地方是发行版之间的差异。比如Debian系和Redhat系。有些文件名字不一样地存在还好,有些完全是这里有那里没有。比如在网络配置上它们差异就比较大。

我采用归类的方法,也许类别不是很严谨,但是达到了降低复杂度的目的。操作系统本来就是一个十分复杂的大型程序(组),学习一定要用巧劲。

知其然,知其所以然。Geek精神,就是探索精神,刨根问底精神,追求真相精神。递归地,不断往上问,为什么。最终,你将获得真相,和答案。

本文并没有仔细讲是谁调用这些文件,即这些文件在实际中是怎么生效的。我想在日后分析Linux启动流程时再来聊聊这些。


参考资料: