商阳剑─定位无关网络服务的启动命令过程
1 F* S s' ?+ K5 J5 ~0 c现代的Linux系统中,网络进程一般可以用以下两种方法中的任一种来启动:一是作为系统启动过程的一部分启动,二是由于响应传入的被通用的网络服务进程检测到的网络请求而启动。本节集中讨论第一种方法,后一种方法在下一节讨论。现在我们就设法确定cupsd、ntpd、portmap、rpc.statd等进程是在什么地方启动的。
$ c) N2 T; z* ]1 b: T
注意: 7 A9 m0 Y: W' A; v) s5 W
Red Hat Enterprise Linux系统,提供了一个chkconfig命令,能够确认不同服务启动的运行级别。本文将重点讨论更加通用的能够获取此信息的分布式独立机制。
: c& Y. ]& x; C
绝大多数现代Linux系统使用一种称为SysVInit的机制,以不同的运行级别来启动不同的系统服务。启动所有系统服务的命令过程集中存储在目录/etc/init.d中。各种服务与不同的运行级别相关联(运行级别一般从0至6),通过从/etc/rc0.d直至/etc/rc6.d的不同目录来确认和识别,并通过与存储在/etc/init.d的主要命令过程的符号连接而实际启动和终止。对于进入某一运行级别时所启动的服务命令过程的符号连接来说,它是以字母“s”开头的,其后跟着一系列反映命令过程启动顺序(升序)的数字。对于进入某一运行级别时所终止的服务命令过程符号连接来说,它是以字母“K”开头的,其后跟着一系列反映命令过程终止顺序(降序)的数字。这种机制称为"Sys V Init",因为这种系统启动方法最初是从AT&;amp;T System V Unix计算机上引入的。
8 O, T) U! z' d0 [$ g3 Z
要定位用于启动不同服务的命令过程,请切换到目录/etc/init.d,并列示其内容。会看到如下的信息:
! Y2 `- ~* @ X# G5 X b8 s' Y& H0 @' E1 r6 u6 b
8 m0 \: V: Y7 F, ?2 e% I% @
5 S* p" M( M: P1 I
8 `" _6 x0 P) H1 I3 I+ E0 y# f- h" ?$ h5 O9 ~- V
- f0 E2 X" R+ X, k- t4 T6 j7 F
7 }. N, t% p+ g2 l# s* m; p8 G
仔细观察此列表,容易发现用于cups、ntpd、portmap等服务的启动命令过程,因为启动命令过程的名称引起了其相关联的服务。然而,我们并不清楚哪一个命令过程与rpc.statd进程相关联。因此,可以使用grep来确定:
: W T1 N- O1 W1 i# ~& u( h& r n% g! Y! D. C
/ g9 |! m& O9 v/ O6 f, U
5 {% N2 c* Y) r; f( ?& L s
2 D/ {. E( ?4 m
因而,我们需要禁用cups、nfslock、portmap命令过程,使在重新启动系统时它们不会执行。我们还要修改ntpd命令过程使其执行不同的ntpd服务。
2 m- T! p" s6 v
系统的默认运行级别,即指出在系统启动时所启动的特定命令过程和服务集合的方法,是由包含initdefault关键字的命令行决定的,此关键字存在于/etc/inittab中。在一个Red Hat Enterprise Linux系统上,此行看起来会是如下的样子:
" Q" N# l6 D8 x, ?5 y" i) ] q
% D8 `9 Z. h6 j f3 Y2 u9 Z2 j& `
( A5 F2 X0 O0 z1 C7 c
. i& i! a2 p' [# Q! m9 S
( p- v5 F& }/ i8 D8 y+ s$ Q
! [# E4 @8 J" u n Z$ grep ':initdefault:' /etc/inittab
2 s7 |! B: G6 ?% I9 aid:5:initdefault:
! y0 B& f0 v0 L/ l$ V不同的Linux发行版本对于从2到6的运行级别赋予不同的逻辑含义,但其机制却是相同的,而无论这些服务运行在何种级别上。例如,在Ubuntu Linux 服务器上默认的运行级别是2级,如下所示:
7 z8 \+ U6 u3 [' w' x! q) y$ D' t1 G6 @" J: r2 Y
1 s, a! i4 k/ j5 Y M# P0 f, X9 @+ f
: D/ O- Q4 a. z2 S+ m
) e3 V, q; x, j7 ]1 q$ grep 'initdefault:' /etc/inittab
: ^; h3 f3 |& Kid:2:initdefault:
& g7 a" i$ D* T$ O7 A一旦了解了系统的默认运行级别,就可以转向相关目录,移除与那些不想启动的服务相关联的符号连接。在此例中,这个目录就是/etc/rc5.d,因为我们这个Red Hat Enterprise Linux 系统默认运行在级别5上。
v! P5 }/ `% a8 {# T8 ?% F
虽然这些仅是符号连接,但是清楚地了解你手动禁用了哪些服务却是个好主意,这就易于使其他系统管理员看出你对特定计算机的默认配置作了哪些改变。为了简化这一点,可以创建一个名DISABLED的目录并将符号连接移到此目录,而不是仅仅删除它们。
- h3 n( j h: i% p1 [- {+ K t8 S. }" N# H/ L
( e) m% Q8 g+ T' P
e# t" v) J/ \9 P7 y1 b$ n$ @' ^
% S; R+ A0 |+ G3 m0 X! C
# P' @7 R( Z& F+ A' D( y3 k; H# mkdir DISABLED
+ a# ~& H( s e c7 n4 j, c: @
# ls *nfslock *portmap *cups
" K+ T/ ~& \6 Z
S13portmap S14nfslock S55cups
* B [" X; }5 [8 o- C
# mv *nfslock *portmap *cups DISABLED
! w0 K4 w }4 r) l0 L+ V5 N4 N我们应该为其它的可能启动相同服务的运行级别重复这个过程。下面是一个找到完整列表的例子:
6 a8 e1 j/ K& h6 u- {2 D# D5 q
( k; p& \/ @- A" g8 N" @
7 E# Y5 |- a" H( |! u9 [/ G# J, c. g8 j; [# v
! a) K* @1 I: t) G
/ w% V- g, l4 [6 m A z
# cd /etc
0 l4 p' z2 U: |- _
# find {init,rc}.d -name "*nfslock*"
5 y9 B3 Z* y, X0 Hrc.d/init.d/nfslock
0 N7 [8 h- I9 A8 ~rc.d/rc0.d/K86nfslock
- Z: F, z5 R& Crc.d/rc5.d/K86nfslock
8 V. u# Z' d- R2 |1 h y/ c
rc.d/rc5.d/DISABLED/S14nfslock
/ h% c$ g# D) @9 T7 o5 Orc.d/rc2.d/K86nfslock
0 V: J& x5 A R( t; Lrc.d/rc1.d/K86nfslock
4 H0 B+ A( X2 w+ M# T6 U: Jrc.d/rc3.d/K86nfslock
" o4 D: s% a' M! v& f5 Jrc.d/rc5.d/S14nfslock
8 E9 K: N1 v* O9 V9 `5 Q" I
rc.d/rc4.d/K86nfslock
3 m/ X; ]. r' v0 {- xrc.d/rc5.d/S14nfslock
, J1 q9 `$ X$ M( e8 i
rc.d/rc6.d/K86nfslock
/ E4 [; o: s% L% p) j( A, z这显示出nfslock命令过程也正被调用在级别3和4上,这正是我们应该用相同的机制禁用的地方。你也可以运行同样的命令来确认cups和portmap命令过程所被调用的运行级别。
* r D& {( |8 E: i& ~如果你也运行着一个象Red Hat Enterprise Linux一样的、提供一个运行级别配置工具的系统的话,你可能也要用这种工具来禁用系统的某些服务与不同的运行级别相关联的企图。既然这样,你就可以运行这个命令以禁用在所有运行级别上的指定服务。如下例所示:
: S. w9 Q; V4 V0 M% M
+ [! e4 x( _. u4 [! m; |7 v& T6 o" `: F2 [& g8 O- g c2 G9 ~* G
2 G4 e' R/ t; [$ T0 p5 o2 v
, W2 _* f1 S i4 z
: w% |3 T" P' c" n7 r$ j* x$ N# chkconfig nfslock off
) A% Q: b# H4 a4 Q# chkconfig cups off
& t/ C j) r% Y& }) L% o& Z
# chkconfig portmap off
3 s% N8 j) w3 k. v, z8 w
其它Linux发行版本,如Ubuntu和Debian,也提供了类似的工具如BootUp Manager(BUM)
2 @) J. l7 N+ r/ g0 A+ S: g$ J中冲剑─修改系统启动行为 6 a7 X. l; k2 K: U: x! V% @
注意: ( Q6 }4 O6 N* d2 {( @ y2 p2 R5 c+ b3 K
为了安全的原因,本节使用ntpd这个网络时间协议进程,作为一个你想定期运行但并非持续运行的过程。一些网络环境需要所有参与的系统保持绝对的同步。如果是那样的话,本节这个例子也许就不太恰当了,但仍可以阐明怎样用可靠的预定过程来替换一个进程。
, F8 M! w6 l/ c; q* n9 ~正如前面所提到的那样,我们需要修改网络时间协议进程(ntpd)的行为,使你在启动系统后,它只能执行一次查询,而不能连续不断地进行,以后保持日常的同步就可以了。为了完成这点,我们可以修改/etc/init.d/ntpd命令过程,也可以修改任何关联的数据文件,还可以改变系统调用ntpd进程的方法。我们将执行后者,这稍微灵活一些。
4 u# ?$ \& E) N7 h
首先,按照上一节所阐述的方法从所有运行级别上移除ntpd命令。然后,编辑文件/etc/rc.local,这是启动过程最后一步的命令过程。在文件最后一行的前面加入一行:
* S; J9 d( H( P9 n+ f, I6 v+ U
% Y2 z+ h* h8 {. z% B. D j1 Y, B( V! T+ d( O+ k
. [/ P# F1 @. s& r' {
, h' s, N7 i! x4 |- ]- ?4 \+ c5 o4 Z; u2 M
/usr/sbin/ntpd –q
/ d4 t; g- r2 \0 \编辑之后的结果所下如示:(你的发行版本是另一种的话,可能会略有不同。)
J: m9 R9 P* d6 S, e% p% U
% G$ O) k! }4 I
6 E5 `1 |. R" }. x
# k! y C8 F/ d0 Q# I4 W
. c/ g( w- \- d4 y$ c1 Q2 ~& X! U/ Q0 c8 ~4 E9 \" Q5 K
#!/bin/sh
; V9 e4 E+ q; `6 E1 i4 c, E
#
- m/ @( g/ R" k2 i. Y$ ^& S# This script will be executed *after* all the other init scripts.
+ Y4 n% s: ^1 G; M! T9 y* E6 ?: G
# You can put your own initialization stuff in here if you don't
' W& v p& ^! s& X
# want to do the full Sys V style init stuff.
X9 |5 E' O0 y& }. S0 D+ u. C/usr/sbin/ntpd -q
" g, D: h2 D4 Rtouch /var/lock/subsys/local
O: \* L/ |7 q! s如此一来,你的系统每次启动时,都会将 /usr/sbin/ntpd –q作为启动过程的最后一个命令来执行。
9 K# x7 A) Q4 a# K下一步,我们要确保系统启动之后,系统每天运行一次这个同样的命令,这就使系统时钟不会与实际时间相差太多。为此,我们使用cron命令来使ntpd –q按照规定的时间运行,在此例中就是每天运行一次。为了实现这一点,我们执行crontab –e命令来编辑定时执行命令表并将下面一行加入到文件中:
1 T, J1 S, B( o2 t7 h1 O1 t
, Q( j/ Y2 F9 E9 ~. N9 U; t
2 m& G" N) {6 v1 C
& D5 y9 ]. Z3 G0 e+ u
( Y8 C1 T' x- c( _5 V4 [' i& u$ G& S p0 P% }
5 0 * * * echo `date`: `/usr/sbin/ntpd -q` >> /var/log/cron_ntpd.log
9 M7 }( O& `7 w3 x- K0 J
注意:此例中的所有引号均为后单引号,这样就会使其包含的命令被执行。
$ g+ P% ]1 n- z4 a# R2 b此条目会在每天午夜5分钟之后运行/usr/sbin/ntpd –q命令,并会将一个登记项添加到/var/log/cron_ntpd.log文件中,此文件由时间信息和命令的输出结果组成。我们可以监视这个
日志文件来查看有多少调整是必需的;如果必要的话,增加这个命令的频率。