首先感谢下剑心大牛,,让本屌又学到了一点东西

上周公司新装了几个6.2的机器,出现下面的情况

ls -al /tmp

反应巨慢。

ps 进程如下

root     30259 30175  0 11:25 pts/0    00:00:00 ls --color=auto -al /tmp 
root     30571 30354  0 11:27 pts/2    00:00:00 ls --color=auto –al

strace ls -al /tmp

数据如下

poll([{fd=4, events=POLLOUT|POLLERR|POLLHUP}], 1, 30000) = 1 ([{fd=4, revents=POLLERR|POLLHUP}])
getpeername(4, 0x7fff5c40e9b0, [128])   = -1 ENOTCONN (Transport endpoint is not connected)
read(4, 0x7fff5c40e9af, 1)              = -1 ECONNREFUSED (Connection refused) 
shutdown(4, 2 /* send and receive */)   = -1 ENOTCONN (Transport endpoint is not connected)
close(4)                                = 0 
open("/etc/localtime", O_RDONLY)        = 4 
fstat(4, {st_mode=S_IFREG|0644, st_size=405, ...}) = 0 
fstat(4, {st_mode=S_IFREG|0644, st_size=405, ...}) = 0 
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f231757d000
read(4, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\3\0\0\0\3\0\0\0\0"..., 4096) = 405
lseek(4, -240, SEEK_CUR)                = 165 
read(4, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\3\0\0\0\3\0\0\0\0"..., 4096) = 240
close(4)                                = 0 
munmap(0x7f231757d000, 4096)            = 0 
socket(PF_FILE, SOCK_DGRAM|SOCK_CLOEXEC, 0) = 4 
connect(4, {sa_family=AF_FILE, path="/dev/log"}, 110) = 0 
sendto(4, "<14>Jan 14 11:34:11 ls: nss_ldap"..., 107, MSG_NOSIGNAL, NULL, 0) = 107
stat("/etc/nss_ldap.conf", {st_mode=S_IFREG|0644, st_size=9625, ...}) = 0 
geteuid()                               = 0 
stat("/etc/resolv.conf", {st_mode=S_IFREG|0644, st_size=145, ...}) = 0 
socket(PF_NETLINK, SOCK_RAW, 0)         = 5 
bind(5, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 0 
getsockname(5, {sa_family=AF_NETLINK, pid=6570, groups=00000000}, [12]) = 0 
sendto(5, "\24\0\0\0\26\0\1\3\263|\363P\0\0\0\0\0\0\0\0", 20, 0, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 20
recvmsg(5, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"0\0\0\0\24\0\2\0\263|\363P\252\31\0\0\2\10\200\376\1\0\0\0\10\0\1\0\177\0\0\1"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 108
recvmsg(5, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"@\0\0\0\24\0\2\0\263|\363P\252\31\0\0\n\200\200\376\1\0\0\0\24\0\1\0\0\0\0\0"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 128
recvmsg(5, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"\24\0\0\0\3\0\2\0\263|\363P\252\31\0\0\0\0\0\0\1\0\0\0\24\0\1\0\0\0\0\0"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 20
close(5)                                = 0 
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 5 
fcntl(5, F_SETFD, FD_CLOEXEC)           = 0 
setsockopt(5, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0 
setsockopt(5, SOL_TCP, TCP_NODELAY, [1], 4) = 0 
fcntl(5, F_GETFL)                       = 0x2 (flags O_RDWR) 
fcntl(5, F_SETFL, O_RDWR|O_NONBLOCK)    = 0 
connect(5, {sa_family=AF_INET, sin_port=htons(389), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress)
poll([{fd=5, events=POLLOUT|POLLERR|POLLHUP}], 1, 30000) = 1 ([{fd=5, revents=POLLERR|POLLHUP}])
getpeername(5, 0x7fff5c40e9b0, [128])   = -1 ENOTCONN (Transport endpoint is not connected)
read(5, 0x7fff5c40e9af, 1)              = -1 ECONNREFUSED (Connection refused) 
shutdown(5, 2 /* send and receive */)   = -1 ENOTCONN (Transport endpoint is not connected)
close(5)                                = 0 
sendto(4, "<14>Jan 14 11:34:11 ls: nss_ldap"..., 107, MSG_NOSIGNAL, NULL, 0) = 107
sendto(4, "<14>Jan 14 11:34:11 ls: nss_ldap"..., 85, MSG_NOSIGNAL, NULL, 0) = 85
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0 
rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0 
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0 
nanosleep({4, 0}, ^C <unfinished ...>

最开始认为,ls这个东西被某黑阔替换了(尼玛大多机器都有这样的情况,当时被惊着了),但是ls其他目录不会出现上述情况。

然后找其他机器来测试,

发现一个问题,只要ldap不能正常验证的都出现上述情况。

最开始以为 "对tmp执行 ls -al 命令需要验证 uid"

最后才发现是粘滞位这个问题导致的

Tmp是一个比较特殊的目录

[root@~]# ls -ld /tmp

drwxrwxrwt. 8 root root 4096 Jan 14 12:31 /tmp   注意:权限里面有一个t

寻找了相关文章,这个叫linux的粘滞位

Linux中的粘滞位

Sticky 位是一个访问权限标志位,可以用来标示文件和路径。

历史:

粘滞位是在1974年Unix的第5版中引入的,用来设置可执行文件。当可执行文件设置粘滞位之后,它能够指示操作系统在程序退出后,保留程序的代码段到swap空间。当程序再次执行时,内核只需将程序从swap搬到内存即可,这能够加速程序的执行。所以,频繁使用的程序比如编辑器能够更快的打开。目前,这种应用只是适用于HP-UX, NetBSD和UnixWare,Solaris在2005年放弃了这种应用,linux没有版本支持过这种行为。

当今使用:

当今,粘滞位最常用是应用于路径。当路径被设置粘滞位后,路径下的文件只有文件的owner, 或者root 才能够重命名、删除文件。如果没有粘滞位,任何用户,不管是不是owner, 只要有路径的写/执行权限就可以重命名、删除文件。典型的应用就是/tmp路径,粘滞位可以阻止一般用户删除/重命名其他用户的文件。这种特性首次引入是在1986年4.3BSD, 今天在现在的Unix系统中都可以找到这个特性。另外,Solaris定义了独有的行为:当粘滞位设置到非执行文件时,当访问这种文件时,内核将不会缓存。这常用于设置swap文件,用来阻止访问这些文件时冲刷掉系统缓存中更重要的数据。

Sticky bit在不同系统中的异同

HP-UX:当程序的最后一个用户退出时,阻止系统丢弃程序段swap-space image. 当下一个用户执行这个程序时,系统只需要swap in,而不需要重从磁盘新读入文件到内存,节约程序启动时间。

[...] prevents the system from abandoningthe swap-space image of the program-text portion of the file when its last userterminates. Then, when the next user of the file executes it, the text need notbe read from the file system but can simply be swapped in, thus saving time.

Linux: 当粘滞位设置到文件时,内核将会忽略。当设置路径时,路径中的文件只能够被root或者文件的owner重命名或者unlinked。

[...] the Linux kernel ignores the stickybit on files. [...] When the sticky bit is set on a directory, files in thatdirectory may only be unlinked or renamed by root or their owner.

举例:

Sticky bit 设置:

chmod 命令,可以用八进制模式1000或者它的符号t.

比如:添加粘滞位到路径/usr/local/tmp,

1.      chmod +t /usr/local/tmp

2.      chmod 1777 /usr/local/tmp

在Unix 文件系统 符号中,sticky bit t 是在最后一位。比如:在Solaris 8, /tmp路径默认有粘滞位,如下:

$ ls -ld /tmp

drwxrwxrwt   4 root     sys          485 Nov 10 06:01 /tmp

如果粘滞位设置的路径或者文件没有可执行(x)位,它的符号用T(大写的t)

# ls -l test

-rw-r--r--   1 root     other          0 Nov 10 12:57 test

# chmod +t test; ls -l test

-rw-r--r-T   1 root     other          0 Nov 10 12:57 tes

转自:http://zone.wooyun.org/content/2339