linux系统sbininit执⾏过程
对于linux的启动过程,之前⼀直都是研究到内核运⾏/sbin/init,启动第⼀个⽤户进程为⽌,因为这部分⼀直都是在内核态⼯作,所以对于学习内核还是有帮助的,当时/sbin/init之后的过程也需要明⽩,今天就总结⼀下。linux循环执行命令脚本
⾸先⼤体写⼀下内核从启动到执⾏/sbin/init的流程:
head.S ===> start_kernel ===> rest_init ===> cpu_idle和内核线程init ===》init_post ===> /sbin/init
⽽init执⾏后的⼤体流程是:
init ===> fork出 getty 按照/etc/inittab 打开相应终端 ===》exec 执⾏ login验证⽤户和密码 根据/etc/passwd ===》密码正确,设置⼀些环境变量 设置主⽬录 exec执⾏bash
getty login bash 是同⼀个进程
在⼯作中之前碰到过⼀个问题就是客户机器正常进⼊控制台后sudo su不能获取超级⽤户权限,说not in sudoer。
sudo su是使⽤普通⽤户密码来获取超级⽤户权限,但是并不是所有的普通⽤户都可以⽤sudo su来获取超级⽤户权限,具体的授权
在/etc/sudoers中。也就是说我们在获取超级⽤户权限的时候⽤sudo su,这时系统回去sudoers中查看该申请⽤户是否在列表中,如果在则该⽤户获取超级⽤户权限,此后⼀段时间该⽤户则是超级⽤户权限,时间长短也是在/etc/sudoers中定义的
这样分析也就是说客户机器上的这个⽤户没有在sudoers列表中,可以⽤adduser命令来添加到列表中,但是添加sudoers是需要超级⽤户权限的。。。这就形成了⼀个死循环!
想到的解决办法是在内核启动是参数init=/bin/bash,这样内核启动后不是执⾏init,⽽是跳过init gettty login直接执⾏bash,这样的话没有执⾏login,系统也就没有启⽤任何⼀个⽤户,这是的控制台就是超级⽤户权限,这是使⽤命令adduser将⽤户添加到sudoer中就可以了,这样该普通⽤户就可以获取超级⽤户权限了
在登录到Linux系统中之后,你会发现(使⽤”top”或”ps –ax”命令)⾃⼰终端原来的getty进程已经不到了。因为getty进程执⾏了login程序,被替换成了login进程,并且最后被替换成你的登录shell进程。
当你在”login: “提⽰符下键⼊了你的⽤户名后,getty会读取⽤户名并且去执⾏login程序,也把⽤户名
信息传给了它。因此getty进程被替换成了login进程。此时login进程会接着要求你输⼊⼝令。在⼝令检查通过后就会去执⾏/etc/passwd⽂件中对应你⽤户名项中记录的程序。通常这个程序是bash shell程序。因此原来的getty进程最终被替换成了bash进程,对应的这三个程序也就都具有相同的进程ID。
当注销登录(log out)时,则该终端上的所有进程都会被终⽌(killed),包括登录shell进程bash。因此,对于在/etc/inittab⽂件中列出的getty程序,⼀旦其被替换执⾏的bash程序被终⽌或退出,init进程就会为对应终端重新创建⼀个getty进程。
login程序则主要⽤于要求登录⽤户输⼊密码。根据⽤户输⼊的⽤户名,它从⼝令⽂件passwd中取得对应⽤户的登录项,然后调⽤getpass()以显⽰”password:”提⽰信息,读取⽤户键⼊的密码,然后使⽤加密算法对键⼊的密码进⾏加密处理,并与⼝令⽂件中该⽤户项中pw_passwd字段作⽐较。如果⽤户⼏次键⼊的密码均⽆效,则login程序会以出错码1退出执⾏,表⽰此次登录过程失败。此时⽗进程(进程init)的wait()会返回该退出进程的pid,因此会根据记录下来的信息再次创建⼀个⼦进程,并在该⼦进程中针对该终端设备再次执⾏agetty程序,重复上述过程。
login程序也可以被⽤户在运⾏过程中在shell下当作⼀个命令执⾏。此时它可以被⽤随时从⼀个⽤户切换成另⼀个⽤户。如果执⾏时没有给出参数,则login就会显⽰输⼊⽤户名的提⽰信息。如果⽤户不是超级⽤户(root),并且/etc/⽬录下存在⼀个名为nologin的⽂件,那么该⽂件中的信息就会被显⽰出来,此次登录过程也随即被终⽌。
如果在/etc/usertty⽂件中对该⽤户指定了特殊的访问限制,那么这些限制要求必须满⾜。如果是⼀个超级⽤户,那么所使⽤的登录tty设备必须是在/etc/securetty⽂件中指定的。
在所有这些条件满⾜之后,login同样也会要求⽤户输⼊密码并对其进⾏检查。如果.hushlogin存在的话,login就会执⾏⼀个“安
静”的登录过程,也即不检查是否有邮件,也不显⽰上次登录时间和motd⽂件中的信息。否则如果/var/log/lastlog⽂件存在的话,就会显⽰其中的最后登录时间。
如果⽤户键⼊的密码正确,则login就会把当前⼯作⽬录(Currend Work Directory)修改成⼝令⽂件中指定的该⽤户的起始⼯作⽬录。并把对该终端设备的访问权限修改成⽤户读/写和组写,设置进程的组ID。然后利⽤所得到的信息初始化环境变量信息,例如起始⽬录(HOME=)、使⽤的shell程序(SHELL=)、⽤户名(USER=和LOGNAME=)和系统执⾏程序的默认路径序列(PATH=)。接着显⽰/etc/motd⽂件(message-of-the-day)中的⽂本信息,并检查并显⽰该⽤户是否有邮件的信息。最后login程序改变成登录⽤户的⽤户ID并执⾏⼝令⽂件中该⽤户项中指定的shell程序,如bash或csh等。
如果⼝令⽂件/etc/passwd中该⽤户项中没有指定使⽤哪个shell程序,系统则会使⽤默认的/bin/sh程序。如果⼝令⽂件中也没有为该⽤户指定⽤户起始⽬录的话,系统就会使⽤默认的根⽬录/。有关login
程序的⼀些执⾏选项和特殊访问限制的说明,请参见Linux系统中的在线⼿册页(man 8 login)。
Shell程序是⼀个复杂的命令⾏解释程序,是当⽤户登录系统进⾏交互操作时执⾏的程序。它是⽤户与计算机进⾏交互操作的地⽅。它获取⽤户输⼊的信息,然后执⾏命令。⽤户可以在终端上向shell直接进⾏交互输⼊,也可以使⽤shell脚本⽂件向shell解释程序输⼊。在Linux系统中,⽬前常⽤的shell有:
Bourne Again Shell,/bin/bash
C shell,/bin/csh(或tcsh)
BSD shell/bin/ash(或bsh)
在登录过程中,系统(login)会从⼝令⽂件⽤户对应登录项的最后⼀个字段知道应该为⽤户执⾏哪个shell程序。
shell程序中实现了⼀个具有流控制结构的语⾔,使⽤相当⼴泛。⽬前这些shell程序都朝着与IEEE POSIX 1003.2兼容的⽅向发展,因此它们各⾃虽然各⾃有⾃⼰的特点,但基本功能已经越来越相象。本书主要介绍bash的⼯作原理和实现机制,其它⼏种shell的实现机制与之类似。
在登录过程中login开始执⾏shell时,所带参数argv[0]的第⼀个字符是’-’,表⽰该shell是作为⼀个登录shell被执⾏。此时该shell 程序会根据该字符,执⾏某些与登录过程相应的操作。登录shell会⾸先从/etc/profile⽂件以及.profile⽂件(若存在的话)读取命令并执⾏。如果在进⼊shell时设置了ENV环境变量,或者在登录shell的.profile⽂件中设置了该变量,则shell下⼀步会从该变量命名的⽂件中读去命令并执⾏。因此⽤户应该把每次登录时都要执⾏的命令放在.profile⽂件中,⽽把每次运⾏shell都要执⾏的命令放在ENV变量指定的⽂件中。设置ENV环境变量的⽅法是把下列语句放在你起始⽬录的.profile⽂件中。
ENV=$HOME/.anyfilename; export ENV
在执⾏shell时,除了⼀些指定的可选项以外,如果还指定了命令⾏参数,则shell会把第⼀个参数看作是⼀个脚本⽂件名并执⾏其中的命令,⽽其余的参数则被看作是shell的位置参数($1、$2等)。否则shell程序将从其标准输⼊中读取命令。
在执⾏shell程序时可以有很多选项,请参见Linux系统中的有关sh的在线⼿册页中的说明。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论