标签:
杂谈 |
分类: solaris |
su是一个用于用户切换的系统命令,但是su在shell中却不能使用。为了证实shell的可行性,这里我们使用shell实现一个telnet登陆。
注:本测试使用的shell全部为korn shell,OS是solaris 9
test.sh代码如下:
#!/bin/ksh
INFILE="file.in"
OUTFILE="file.out"
rm $INFILE
rm $OUTFILE
mknod $INFILE p
touch $OUTFILE
# file description 7 for out and 8 for in
exec 7<>$OUTFILE
exec 8<>$INFILE
telnet 172.28.122.50 <&8 >&7 2>&1 &
sleep 1 #sleep是为了响应延时
echo "ipu" >> $INFILE
###将用户名定向输入管道文件,也就是作为telnet命令的输入
sleep 1
echo "ipu" >> $INFILE
###密码
sleep 1
echo "whoami" >> $INFILE
shell执行结束之后查看输出内容:
more file.out
Trying 172.28.122.50...
Connected to 172.28.122.50 (172.28.122.50).
Escape character is '^]'.
SunOS 5.9
login: ipu
Password:
Last login: Wed Dec 5
15:40:01 from 172.28.122.170
Sun Microsystems Inc. SunOS
5.9 Generic May 2002
You have mail.
Sun20:ipu@/opt/ipu$ whoami
ipu
Sun20:ipu@/opt/ipu$
从输出结果来看,我们的shell正常实现了一个telnet登陆,其原理对telent进程的输入和输出进行了重定向,通过管道文件作为telnet的输入。
好,那么我们根据这个原理也实现一次su命令。
korn shell代码如下:
#!/bin/ksh
INFILE="file.in"
OUTFILE="file.out"
rm $INFILE
rm $OUTFILE
mknod $INFILE p
touch $OUTFILE
# file description 7 for out and 8 for in
exec 7<>$OUTFILE
####一个普通文件用于存放命令输出
exec 8<>$INFILE
####一个管道文件作为标准输入
su <&8 >&7 2>&1 &
###切换到root用户
sleep 1
echo "800" >>$INFILE
sleep 1
echo "whoami" >>$INFILE
shell结束后当前的terminal对输入的命令无法现实,但是可以感觉到命令输入了,并且可以执行。比如输入more file.out,在terminal上看不到输入的上述命令,但是可以看到file.out文件的内容。
内容如下:
Password:
su: Sorry
从结果来看,登陆失败。
为什么会出现上面的问题呢?好,我们可以从几个方面来检查。
在solaris9环境下:
查看/var/adm/sulog文件,内容如下:
SU 12/05 12:42 - pts/8 ipu-root
sulog是一个专门记录su命令的log,具体格式如下
SU命令 日期 时间 执行结果 终端 当前user-切换后的user
其中执行结果"+"表示成功,"-"表示失败。
从上面的sulog我们可以看出,我们执行的su命令失败了。那么为什么失败了呢?我们再看看/var/adm/message文件:
Dec 5 12:42:22 Sun120
su: [ID 810491 auth.crit] 'su root' failed for ipu
on /dev/pts/8
这里同样提示了su root失败,但是没有写明失败原因。
/var/log/syslog中并没有对此问题的任何提示信息。
那么message中的[ID 810491 auth.crit]是什么意思呢?这是su命令没有通过PAM(Pluggable Authentication Modules 可插拨认证模块)认证提示的错误。我们可以直接在命令行输入su命令,可以su 一个不存在的用户或者输错password,我们可以看到message中都会提示这个错误,说明su命令没有通过其PAM认证。
从上面所能得到的错误无法确定我们当前的错误究竟在哪里,但是从现象来看,应该不是简单的程序错误,而是su命令机制不是一个普通的进程,随后的测试应该可以证明我的看法。
我们知道,我们连接到一个服务器的时候,我们使用的terminal(以下简称tm1)实现其连接的一个tty进程。而su命令不是一个简单的进程,其应该是要求输入应该是一个tty,而不是一个管道可以模拟其输入的。我们可以通过如下测试验证这样的想法:
我们在一个terminal确定自己的tty:
Sun20:ipu@/opt/ipu$ who am i
ipu
pts/7 Dec 5
18:05 (172.28.122.51)
其中pts/7就是我们的tty。
我们在具体看看这个pts/7(7是一个link)具体连接哪个进程:
Sun20:ipu@/dev/pts$ ls -l 7
lrwxrwxrwx 1 root
root 28
Dec 7 2006 7 ->
../../devices/pseudo/pts@0:7
注:tty的路径视具体OS确定,unix、linux和solaris之间略有区别。
这样就确定了pts/7指向的是/devices/pseudo/pts@0:7(字符文件)
说明我们使用当前的tm1时,所有的输入其实都是通过/devices/pseudo/pts@0:7(其是字符文件)来实现的。
然后我们在另一个terminal(以下简称tm2)使用重定向的方式向这个文件写入信息。
Sun20:ipu@/devices/pseudo$ ls >> pts@0:7
这时我们看到当前执行命令的tm2没有现实任何结果,而tm1则把tm2的/devices/pseudo目录下的内容全部输出了。
在tm2如下操作:
Sun20:ipu@/devices/pseudo$ echo "ls" >> pts@0:7
tm1现实“ls”两个字符。
从上面的测试可以证明,一个terminal的输入是通过tty实现的。
从以上测试和我的猜想基本可以确定su命令的输入是无法使用管道来实现的。
后来想到部门还有redhat的linux,所以索性在上面测试了以下,结果验证了我的想法,同样的shell,在linux中输入信息:
standard in must be a tty
哈哈,证明了我的想法是对了,su命令要求是tty作为输入,管道是不行的。
从这几次遇到的问题及其在solaris和linux上测试的情况看,linux比solaris提示的错误信息要详细,以后遇到问题了可以现在linux上测试一下,可能便于尽早确定问题。
注:本测试使用的shell全部为korn shell,OS是solaris 9
test.sh代码如下:
#!/bin/ksh
INFILE="file.in"
OUTFILE="file.out"
rm $INFILE
rm $OUTFILE
mknod $INFILE p
touch $OUTFILE
# file description 7 for out and 8 for in
exec 7<>$OUTFILE
exec 8<>$INFILE
telnet 172.28.122.50 <&8 >&7 2>&1 &
sleep 1
echo "ipu" >> $INFILE
sleep 1
echo "ipu" >> $INFILE
sleep 1
echo "whoami" >> $INFILE
shell执行结束之后查看输出内容:
more file.out
Trying 172.28.122.50...
Connected to 172.28.122.50 (172.28.122.50).
Escape character is '^]'.
SunOS 5.9
login: ipu
Password:
Last login: Wed Dec
Sun Microsystems Inc.
You have mail.
Sun20:ipu@/opt/ipu$ whoami
ipu
Sun20:ipu@/opt/ipu$
从输出结果来看,我们的shell正常实现了一个telnet登陆,其原理对telent进程的输入和输出进行了重定向,通过管道文件作为telnet的输入。
好,那么我们根据这个原理也实现一次su命令。
korn shell代码如下:
#!/bin/ksh
INFILE="file.in"
OUTFILE="file.out"
rm $INFILE
rm $OUTFILE
mknod $INFILE p
touch $OUTFILE
# file description 7 for out and 8 for in
exec 7<>$OUTFILE
exec 8<>$INFILE
su <&8 >&7 2>&1 &
sleep 1
echo "800" >>$INFILE
sleep 1
echo "whoami" >>$INFILE
shell结束后当前的terminal对输入的命令无法现实,但是可以感觉到命令输入了,并且可以执行。比如输入more file.out,在terminal上看不到输入的上述命令,但是可以看到file.out文件的内容。
内容如下:
Password:
su: Sorry
从结果来看,登陆失败。
为什么会出现上面的问题呢?好,我们可以从几个方面来检查。
在solaris9环境下:
查看/var/adm/sulog文件,内容如下:
SU 12/05 12:42 - pts/8 ipu-root
sulog是一个专门记录su命令的log,具体格式如下
SU命令 日期 时间 执行结果 终端 当前user-切换后的user
其中执行结果"+"表示成功,"-"表示失败。
从上面的sulog我们可以看出,我们执行的su命令失败了。那么为什么失败了呢?我们再看看/var/adm/message文件:
Dec
这里同样提示了su root失败,但是没有写明失败原因。
/var/log/syslog中并没有对此问题的任何提示信息。
那么message中的[ID 810491 auth.crit]是什么意思呢?这是su命令没有通过PAM(Pluggable Authentication Modules 可插拨认证模块)认证提示的错误。我们可以直接在命令行输入su命令,可以su 一个不存在的用户或者输错password,我们可以看到message中都会提示这个错误,说明su命令没有通过其PAM认证。
从上面所能得到的错误无法确定我们当前的错误究竟在哪里,但是从现象来看,应该不是简单的程序错误,而是su命令机制不是一个普通的进程,随后的测试应该可以证明我的看法。
我们知道,我们连接到一个服务器的时候,我们使用的terminal(以下简称tm1)实现其连接的一个tty进程。而su命令不是一个简单的进程,其应该是要求输入应该是一个tty,而不是一个管道可以模拟其输入的。我们可以通过如下测试验证这样的想法:
我们在一个terminal确定自己的tty:
Sun20:ipu@/opt/ipu$ who am i
ipu
其中pts/7就是我们的tty。
我们在具体看看这个pts/7(7是一个link)具体连接哪个进程:
Sun20:ipu@/dev/pts$ ls -l 7
lrwxrwxrwx
注:tty的路径视具体OS确定,unix、linux和solaris之间略有区别。
这样就确定了pts/7指向的是/devices/pseudo/pts@0:7(字符文件)
说明我们使用当前的tm1时,所有的输入其实都是通过/devices/pseudo/pts@0:7(其是字符文件)来实现的。
然后我们在另一个terminal(以下简称tm2)使用重定向的方式向这个文件写入信息。
Sun20:ipu@/devices/pseudo$ ls >> pts@0:7
这时我们看到当前执行命令的tm2没有现实任何结果,而tm1则把tm2的/devices/pseudo目录下的内容全部输出了。
在tm2如下操作:
Sun20:ipu@/devices/pseudo$ echo "ls" >> pts@0:7
tm1现实“ls”两个字符。
从上面的测试可以证明,一个terminal的输入是通过tty实现的。
从以上测试和我的猜想基本可以确定su命令的输入是无法使用管道来实现的。
后来想到部门还有redhat的linux,所以索性在上面测试了以下,结果验证了我的想法,同样的shell,在linux中输入信息:
standard in must be a tty
哈哈,证明了我的想法是对了,su命令要求是tty作为输入,管道是不行的。
从这几次遇到的问题及其在solaris和linux上测试的情况看,linux比solaris提示的错误信息要详细,以后遇到问题了可以现在linux上测试一下,可能便于尽早确定问题。