级别: 初级
郑彦兴国防科大计算机学院
2002 年 9 月 15 日
开
机自动登录linux,并自动运行X
window应用程序,有其特殊的应用背景,如基于linux平台的监控系统,linux启动后不需要身份验证,而直接运行监控程序等等。本文以
Redhat7.2为平台,结合linux启动过程,介绍了如何避免身份验证自动登录,并直接进入X window自动运行应用程序。
linux
在启动过程的最后阶段(具体启动步骤略),init 会根据
/etc/inittab文件的最后一行x:5:respawn:/etc/X11/prefdm
-nodaemon运行/etc/X11/prefdm脚本,(Red hat 7.2缺省时是这样的)。prefdm脚本的主要任务是完成X
window的启动,可以有几种启动X window的方法,都包含在prefdm脚本中,几种主要方法有:
- 运行xdm启动X window;
- 运行gdm,进入gnome桌面环境;
- 运行kdm进入kde桌面环境;
- 自动登录进入linux;
prefdm脚本框架大致如下:
#!/bin/sh PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin . /etc/profile.d/lang.sh # 第一步:查看是否为自动登录 if [ -f /etc/sysconfig/autologin -a -x /usr/sbin/autologin ]; then if /usr/sbin/autologin; then exit 0 fi fi
# 第二步:如果不是自动登录方式,就会在/etc/sysconfig/desktop中搜寻用户偏爱的登录方式 ...... # 可以是kdm、gdm以及xdm,并运行相应的kdm、gdm以及xdm。 ......
|
在/etc/X11/prefdm脚本中,是否实现自动登录有一个条件测试开关,事实上,可以在这里注释掉测试开关,直接执行启动X window的操作。
自动登录实质上就是绕过身份验证,直接启动X window。X window的启动可以由xinit来完成。
- Xinit
用来启动X
window系统服务器以及系统上的第一个客户程序,可以通过为xinit传递命令行参数的形式指定要启动的服务器及客户程序。如果不传递参数给
xinit,它将在用户的根目录下寻找并运行 .xinitrc脚本来启动客户程序;在用户的根目录下寻找并运行
.xserverrc脚本来启动服务器。如果xinit在用户的根目录下找不到.xinitrc、.xserverrc,xinit将使用缺省的X
:0。
- 实际上,用startx来启动X更为方便。对于运行单一会话的X window
系统,startx提供了更为良好的用户接口。同样,startx首先在用户的根目录下寻找
.xinitrc及.xserverrc脚本,如果找不到这两个脚本,startx将使用/etc/X11/xinit/xinitrc以及
/etc/X11/xinit/xserverrc脚本。
startx脚本的最基本框架是:
- a、 寻找.xinitrc,如果没有则使用xinitrc;
- b、 寻找.xserverrc,如果没有则使用xserverrc;
- c、 根据找到的脚本确定xinit的参数;
由此可看出,startx在不需要传递任何参数的情况下,可以完成启动X的任务,因此,可以如下修改/etc/X11/prefdm脚本来实现自动登录:
#!/bin/sh PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin . /etc/profile.d/lang.sh # 第一步:查看是否为自动登录 #if [ -f /etc/sysconfig/autologin -a -x /usr/sbin/autologin ]; then #注释掉上边的条件测试,直接运行startx if /usr/X11R6/bin/startx; then exit 0 fi #fi
|
当然,应确保/etc/inittab中的启动级别为5。
重
新启动系统,会发现系统不验证用户身份,直接进入X
window,此时的用户身份为root。但是,如果原来root有自己的桌面、默认shell时,上述方法启动X不一定保证还能拥有原来的设置。为了在
启动X后,在避免验证身份的同时,又不改变用户原来的设置,那么在运行startx之前,还有工作要做。
观察原来/etc/X11/prefdm脚本的自动登录部分:
...... # 第一步:查看是否为自动登录 if [ -f /etc/sysconfig/autologin -a -x /usr/sbin/autologin ]; then if /usr/sbin/autologin; then exit 0 fi fi ......
|
不难看出,脚本中保留了自动登录的接口:一个可执行文件/usr/sbin/autologin以及一个配置文件/etc/sysconfig/autologin。
1、/etc/sysconfig/autologin配置文件的实现:
#config for autologin USER=root EXEC=/usr/X11R6/bin/startx 说明,USER指定自动登录时的用户名;EXEC指定启动X要运行的程序。
|
2、/usr/sbin/autologin可执行文件的实现:
/********************* **** autologin.c **** *********************/ #include #include #include #include #include #include #include
int main(int argc, char **argv) { struct stat st; FILE *f; char *cfg; struct passwd *pw; uid_t uid; gid_t gid; char *dir, *shell; char *user=NULL; char *cmd=NULL;
user="root"; /*为了能说明问题又保持程序简洁,这里默认登录用户为root,实际上, 登陆用户名应该从/etc/sysconfig/autologin中得到, 程序实现时要注意过滤掉/etc/sysconfig/autologin中的无效用户名*/ cmd="/usr/X11R6/bin/startx"; /*同样,这里直接指定启动X window的程序,实际上,该程序应该从/etc/sysconfig/autologin中得到*/
pw = getpwnam(user); //getpwnam返回包含用户信息的passwd结构(该结构在pwd.h中定义)。 if(pw) { uid=pw->pw_uid; gid=pw->pw_gid; dir=strdup(pw->pw_dir); shell=strdup(pw->pw_shell); } //获得用户相关信息 else { printf("ERROR: No such user %s!\n", user); return 1; }
chown("/dev/console", uid, gid); chown("/dev/tty", uid, gid); //为控制台和终端设置用户ID及组ID //下面是设置用户相关ID setregid(gid, gid); setegid(gid); setgid(gid); setreuid(uid, uid); seteuid(uid); setuid(uid);
setenv("HOME", dir, 1); setenv("SHELL", shell, 1); setenv("USER", user, 1); setenv("LOGNAME", user, 1); //设置用户相关环境变量
chdir(dir); //切换到用户根目录 user=NULL;
execvp(cmd, argv); /*在配置完用户的相关信息后,执行启动X window操作。注意这里默认执行/usr/X11R6/bin/startx */ printf("ERROR: Couldn't exec %s: %s\n", cmd, strerror(errno)); return 2; }
|
运行gcc -o autologin autologin.c,拷贝autologin可执行文件到/usr/sbin/autologin,拷贝autologin配置文件到/etc/sysconfig/autologin。
重新启动系统,会直接进入X window并保留用户原来所有的风格。
如
果不需要自动登录的配置文件/etc/sysconfig/autologin,所有的操作都在/usr/sbin/autologin以默认的方式实现
(比如,默认登录身份为root,默认执行操作为/usr/X11R6/bin/startx等),那么,/etc/X11/prefdm脚本的自动登录
部分可简化如下:
...... # 第一步:查看是否为自动登录 if /usr/sbin/autologin; then exit 0 fi //第二步 ...... ......
|
即在脚本中去掉条件测试开关,直接执行/usr/sbin/autologin,这时,只需要拷贝autologin可执行文件到/usr/sbin/autologin,不再需要拷贝autologin配置文件到/etc/sysconfig/autologin。
- 如果重新启动后系统进入了kde,而用户需要进入gnome,只需运行switchdesk gnome在重新启动系统即可,以后每次启动时会自动进入gnome;反之亦然。
- 一
般系统自动登录的目的是启动X window 后自动运行某个X
window程序。如果系统默认的启动级别为3,那么如果要在系统启动后自动运行某些应用程序,只需要在某些脚本中加入相应命令即可,不再详述。在X
window启动后自动运行应用程序要复杂一些,幸好,kde和gnome都为此留下了自动启动接口。如果在kde桌面环境下自动启动应用程序,只需要把
应用程序名字加入/root/.kde/Autostart/目录下即可(这里注意不同用户的根目录可能不同,如用户zyx的根目录可能为
/home/zyx)。如果在gnome桌面环境下自动启动应用程序,只需把应用程序的名字加入/主菜单/程序/设置/会话/会话特性及启动程序的
startup programs属性页中即可。
|
| | 郑彦兴,男,现攻读国防科大计算机学院网络方向博士学位。您可以通过电子邮件
和他联系。
|
from: http://www-128.ibm.com/developerworks/cn/linux/l-tip-prompt/tip20/index.html
如何自动登录linux(续) | |
| 级别: 初级 郑彦兴, 现攻读国防科大计算机学院博士学位
2003 年 6 月 01 日 在”
如何自动登录linux”中,以redhat 7.2操作系统平台为背景,阐述了如何实现自动登录X
window(系统启动级别为5),并自动运行指定的应用程序。本文以redhat
8.0操作系统平台为背景,阐述如何实现启动级别为3时的自动登录,及自动运行相应程序,并简要介绍了如何在redhat 8.0下自动登录X
window(系统启动级别为5),并自动运行指定的应用程序。
启动级别为3时自动登录的实现涉及两个软件包:mingetty-1.00-3.src.rpm软件包及util-linux-2.11r-10.src.rpm软件包。
对于启动级别为3的自动登录的实现,仍然需要考察/etc/inittab脚本,
3:123:respawn:/sbin/mingetty tty3
|
因此,如果想在启动
级别3的情况下实现自动登录,必须要了解mingetty的功能,甚至要修改mingetty的代码。用命令rpm -qf
/sbin/mingetty 可知redhat
8.0版本的mingetty包含在mingetty-1.00-3.src.rpm软件包中,下载该软件包,安装源代码,缺省情况下,代码会安装在
/usr/src/redhat/下,我们关心的只是mingetty.c源文件。mingetty.c约有五百行代码,主要实现如下功能:
- 打开指定的tty(由参数指定);
- 提示用户登录(login:);
- 获得登录用户名;
- 把用户登录名作为参数,调用/bin/login。
我们所关心的部分实质上只有以下三行:
... ... 438 while ((logname = get_logname ()) == 0); //mingetty.c文件438行 439 execl (_PATH_LOGIN, _PATH_LOGIN, "--", logname, NULL); 440 error ("%s: can't exec " _PATH_LOGIN ": %s", tty, sys_errlist[errno]); ... ...
|
第一行的功能是输出login提示,并获得用户输入的登录用户名,登录用户名由logname返回。因此,可作如下修改
... ... 438 // while ((logname = get_logname ()) == 0); //注释掉本行,不再提示login: 439 logname = "root"; //添加本行代码 440 execl (_PATH_LOGIN, _PATH_LOGIN, "--", logname, NULL); 441 error ("%s: can't exec " _PATH_LOGIN ": %s", tty, sys_errlist[errno]); ... ...
|
注意,这里假定用户以超级用户身份登录。
第二行以用户登录名为参数,调用/bin/login程序,进一步实现登录。因此,要想实现自动登录,还应该了解/bin/login的功能,必要时还应修改其源代码。
第三行为出错处理。
采
用同样的方法,查看/bin/login所属软件包(redhad8.0版本的login包含在util-linux-2.11r-10.src.rpm
软件包中),下载并安装util-linux-2.11r-10.src.rpm,login可执行文件有几个源文件编译而成,我们最关心的是
login.c源文件(大约1500行的代码)。下面简要分析一下login要实现的功能,并对相应部分作必要的修改。
Login程序主要可以分为以下几个主要部分:
- Login首先检查登录者是否为超级用户,如果不是超级用户,并且存在/etc/nologin文件,则输出该文件内容,并中止登录过程;主要由checknologin()实现;
- 如果登录用户是超级用户,那么login必须在/etc/securetty/中指定的tty列表中实现登录,否则将导致登录失败。同样可以不指定/etc/securetty文件,此时,超级用户可以在任何tty上登录。
- 经过前两步测试后,login接下来将提示输入登录密码(由getpass()调用完成,有兴趣的读者可参考其手册页面),并进行验证,如果密码不对,则提示重新登录。
- 顺利经过密码验证后,login还将检查是否存在.hushlogin文件,如果该文件存在,则执行一次"quiet"登录(所谓的quiet登录指的是,登录时不再提示邮件mail,不再显示最后一次登录时间,不输出任何消息。启动级别为3时,正常情况下输出这些信息)
- login
接下来设置登录tty的用户ID和组ID,并设置相应的环境变量,包括HOME、PATH、SHELL、TERM、LOGNAME等。对于普通用户来说,
PATH缺省被设置成/usr/local/bin: /bin/usr/bin:;对于超级用户来说,PATH被设置成/sbin: /bin:
/usr/sbin: /usr/bin:
- login的最后一步是为用户启动shell。如果在/etc/passwd中没有为用户指定shell,那么将使用/bin/sh,如果在/etc/passwd中没有给出当前工作目录,则使用"/"。
至此,一个完整的登录过程就结束了。
从
以上对login源程序分析过程中可发现,如果要实现自动登录,应该在第三步做文章,设法绕过提示输入密码以及对密码进行验证这一过程。实际上很简单,
login源程序对是否要求输入密码设置了一个开关控制passwd_req,缺省情况下,其值为1(passwd_req =
1),即要求输入密码进行身份验证。把该行代码改为(passwd_req = 0)后,问题就解决了。即对源文件作如下修改即可:
... ... 402 fflag = hflag = pflag = 0; //login.c文件402行 403 //passwd_req = 1 //缺省时,要求进行密码验证,注释掉本行 404 passwd_req = 0 //添加本行 ... ...
|
修改后,可以直接使用util-linux-2.11r-10.src.rpm提供的Makefile进行重新编译,也可以自己对其编译:
gcc -o login login.c setproctitle.c checktty.c xstrncpy.c -Wall -lcrypt注意包含后面的编译选项-lcrypt,否则会出问题。
|
有了新版的mingetty及login后,拷贝mingetty到/sbin/目录,拷贝login到/bin目录,并将/etc/inittab中的启动级别设置为3,再重新引导系统即可(读者可以自己写一个脚本实现上述过程)。
如果读者对mingetty或login代码的其他部分感兴趣,可以反复修改login.c或mingetty.c的源代码,测试一下代码的功能,这里要注意的是,在拷贝新版mingetty和login之前,
一定要把原来的mingetty和login备份,同时还要准备系统引导盘(有系统安装盘亦可,这样读者有机会键入linux rescue),在测试新版程序前更应如此,如果对代码修改稍有不当,系统将不能正常启动。
如果不想再作进一步的代码测试,只是按本文给出的方法进行代码修改,在系统启动上不会出现什么问题。
在实现了启动级别3时的自动登录后,自动运行应用程序非常简单,把应用程序添加在/etc/rc.d/rc.local脚本中既可。(读者可以尝试一下把startx加入脚本中,看一看效果如何。在某种意义上,又增加了一种自动登录X window的方法)
在"如何实现自动登录linux"中,主要以redhat 7.2平台为背景进行阐述的,其中的自动登录部分可以直接用于redhat 8.0中,不需要任何修改。
但
是,登录后自动运行应用程序的接口在redhat
8.0中有所不同,主要是登录gnome后,自动运行应用程序的接口有所改变:首先点击面板上的GNOME帮助(那个红色的小帽子),然后选择/其它/首
选项/Sessions,在Session对话框的启动程序属性页中添加要启动的程序即可。
对于登录kde后,自动运行程序的接口没有改变。
本文同"如何实现自动登录linux"一文,基本上解决了如何实现自动登录Linux,并自动运行相应应用程序的问题。对于两个最常见的启动级别(3、5),都给出了各自的方法。
在
系统初始化到mingetty及login这一阶段,内核实际上已经完成了引导过程,已经到了系统初始化的最高阶段,与内核没什么关系了。此时,主要是
/sbin/init根据/etc/inittab的内容而相机行事。读者可通过(man 8 init)或者(man 5
inittab)了解更多东西。
在对文中提到的软件包修改时,请遵守GNU General Public License(GPL)相关标准,另外,替换login通常被视为黑客行为,应当谨慎行事。
- login手册页面
- mingetty-1.00-3.src.rpm,在redhat 8.0的发行版本的源代码中,包含该软件包;
- util-linux-2.11r-10.src.rpm,
可在
处下载,注意下载源代码包(..src.rpm)
|
| |
郑彦兴,男,现攻读国防科大计算机学院博士学位。您可以通过电子邮件
和他联系
|
|
from: http://www-128.ibm.com/developerworks/cn/linux/l-tip-prompt/tip20/index2.html
阅读(3693) | 评论(0) | 转发(0) |