几个月前,我编写了一组利用 tmux 的 bash 脚本,在 AIX 7.1 服务器上创建了一个简单的 IDE。我的一个脚本中有一个错误,有时会非常快速地生成用户进程,直到达到 ulimit 设置的限制。这种情况很少发生(大约每月一次),我已经花了几个小时追踪这个错误,但没有成功,所以我决定暂时将我的软用户进程限制设置为低于硬限制的值(例如 100 而不是 1024),这样当我的错误再次出现时,服务器上的其他用户就不会受到明显的性能影响。不幸的是,“ulimit -Su 100”似乎在 AIX 7.1 上的 bash 中不起作用,但它在 ksh 中起作用。我已执行以下解决方法:
将 ksh 设为默认 shell:
$ chsh [username] /usr/bin/ksh
将以下内容写入~/.kshrc:
ulimit -Su 100 # works in ksh, but not in bash
/bin/bash -il # start bash as an interactive login shell
exit # once bash exits, exit from ksh, too
所以现在,每次我创建 shell 时,ksh 都会设置软用户进程限制并启动 bash 作为交互式登录 shell(我仍然希望 ~/.bash_profile 获得源代码)。现在我不得不怀疑,在 ksh 中设置的用户进程限制是否仍将在 bash 子 shell 中强制执行?在顶级 bash 子 shell 中,我运行了以下命令:
$ ulimit -Sa
core file size (blocks, -c) unlimited
data seg size (kbytes, -d) unlimited
file size (blocks, -f) unlimited
max memory size (kbytes, -m) unlimited
open files (-n) unlimited
pipe size (512 bytes, -p) 64
stack size (kbytes, -s) unlimited
cpu time (seconds, -t) unlimited
max user processes (-u) 1024
virtual memory (kbytes, -v) unlimited
可以看到,用户进程限制设置为1024。
我主要关心的另一个问题是知道 ksh 中设置的限制是否包括在 bash 子 shell 中的 tmux 会话中创建的进程。
其他细节:每当我在 tmux 中创建新窗格时,我都相当确定会调用 ksh、获取 ~/.kshrc 并启动 bash,就像正常情况一样。我相信情况确实如此,因为每个新创建的 tmux 窗格的标题都是“ksh”(tmux 窗格的默认标题是前台当前进程的名称),但我看到的却是 bash 提示符而不是 ksh 提示符。
这已经说得有点太多了,所以我想我会省略进一步的细节,除非我要求这样做。
编辑 1:奇怪的行为
看看当我尝试使用“ulimit -Su”(无参数)获取用户进程限制时发生的情况,使用和不使用 truss 时:
$ truss ulimit -Su 2>| truss.out
100
$ ulimit -Su
1024
也许我使用的工具不对,但这看起来很奇怪。这些命令是在 tmux 中运行的。
编辑2:附加信息
这些命令是从常规 bash 提示符运行的——没有子 shell 或 tmux。
$ truss ksh -c "ulimit -Su 100" 2>&1 | grep limit
getrlimit64(9, 0x2FF1B988) = 0
setrlimit64(9, 0x2FF1B988) = 0
$ truss bash -c "ulimit -Su 100" 2>&1 | grep limit
appulimit(1005, 0) = 0x2001C000
bash: line 0: ulimit: max user processes: cannot modify limit: A system call received a parameter that is not valid.
答案1
资源限制简介
类 Unix 系统中的资源限制由getrlimit()
和setrlimit()
系统调用控制。这些限制是针对每个进程配置的,并在生成新进程时继承(例如由fork()
)。这意味着,如果您想从 shell 设置限制,则必须将命令内置到 shell 中(而不是作为子进程执行)。实际上,这ulimit
是许多 shell 中的内置命令,包括ksh
和bash
。
观察到的行为
的“内置”性质解释了和ulimit
中的不同行为。ksh
bash
用户进程数限制 ( ulimit -u
) 由 syscall 设置setrlimit(RLIMIT_NPROC, ...)
。旧版本的 AIX 不支持 RLIMIT_NPROC。<1>AIX 6.1 中添加了此支持<2 节 5.4.4 实施的变更>因此ulimit
中的ksh
使用setrlimit64()
正确。bash
可能编译为与旧版本的 AIX 兼容,无法控制此限制。
结论
您可以使用ulimit
内置的 from ksh
,所有子进程都将继承配置的限制。除非明确调用,否则 shell 和进程通常与强制执行和保持资源限制无关setrlimit()
。
选择
在 AIX 中,还有一种替代方案,它也可以在旧版本的 AIX 中使用:
chdev -l sys0 -a maxuproc=100