问题的提出
Linux上有很多种后台服务
,有些我们想对它充分了解,其中一个方面就是,它是怎么启动起来的?为什么启动成这个样子?我哪里配错了?
要弄清如何启动是很麻烦的,首先要弄清楚init
程序是sysv
版的,还是upstart
版的,还是systemd
版的。然后还要搜索/etc目录,看是否有相应的启动脚本/配置文件,很麻烦
解决思路
Linux的后台服务,本质上也是一组进程,如果能回溯它的父进程
,以及父进程的父进程,则可以绘制出一幅进程家谱。另外,通过每一代父进程的命令行参数
,我们还可以获悉每一级流程所用的配置文件
,从而明晰服务的整个启动流程
那么怎么获得进程家谱呢?用ps -eaf
命令
ps -eaf命令实战
相比常见的ps aux
命令,ps -eaf
最大的特点是能列出父进程的进程号,即PPID,如此,我们便能一级一级回溯,直到追溯到1号进程init
或2号进程kthreadd
下面是一次ps -eaf
的输出(有删减),用于调查后台程序PowerAnalyzer的启动流程
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 Dec14 ? 00:00:01 /sbin/init
root 2 0 0 Dec14 ? 00:00:00 [kthreadd]
root 1461 1 0 15:29 tty1 00:00:00 /bin/login -f
root 1493 1461 0 15:29 tty1 00:00:00 -bash
root 4953 1493 0 18:26 tty1 00:00:00 /bin/sh /usr/bin/startx --
root 4970 4953 0 18:26 tty1 00:00:00 xinit /etc/X11/xinit/xinitrc -- /etc/X11/xinit/xserverrc :0 -auth /tmp/serverauth.GIIE2AL203
root 4972 4970 2 18:26 tty1 00:00:00 /bin/bash /root/.xsession
root 5007 4972 0 18:26 tty1 00:00:00 /bin/sh /root/appstart.sh
root 5032 5007 26 18:26 tty1 00:00:00 ./PowerAnalyzer
解决步骤
注意看第二列PID
和第三列PPID
的级联关系,不难发现
- PowerAnalyzer的pid是5032,它的ppid是5007,所以父进程是sh appstart.sh
#!/bin/sh
./PowerAnalyzer > /dev/null
- appstart.sh的pid是5007,ppid是4972,所以它的父进程是.xsession
chmod +x ~root/appstart.sh
~root/appstart.sh
- 同理,.xsession的父进程是xinit,它从/etc/X11/xinit/xinitrc读取用户配置
#!/bin/sh
# /etc/X11/xinit/xinitrc
#
# global xinitrc file, used by all X sessions started by xinit (startx)
# invoke global X session script
. /etc/X11/Xsession
/etc/X11/Xsession
的作用是寻找并执行所有名叫.xsession
的脚本,而根据进程4972的命令行参数可知,xinit访问的必然是/root/.xsession
的内容- 同理,xinit的父进程是startx脚本,里面最终调用的是xinit,为什么startx脚本会获得执行?看下一条
- 同理,startx脚本的父进程是
交互式bash
,它没有命令行参数,那么默认行为是解析HOME目录下的.bashrc
if [ $(tty) == "/dev/tty1" ]; then # 忽略ssh登录来的pty等伪终端,确保只有本地登录能启动后台服务
ifconfig eth0 192.168.162.107
while true; do startx -- ; echo "Again [$?]..."; done
fi
- 原来,是
.bashrc
脚本里的while在循环respawn脚本startx
,再由startx
最终启动后台服务PowerAnalyzer
! - 同理,
交互式bash
的父进程是终端守护程序login
,login
收到用户root从终端tty1发来的登录请求,验证身份后,给予root一个shell——bash - 同理,login守护程序的父进程是init,到根了!
总结
很多时候系统的设计文档是匮乏的,甚至是缺失的,这时候只能通过对系统初始化过程的了解,来反推前人的设计思路,以及当时的约束条件,好为后面的重构打下基础。