AIX - 当无法分叉时使用 ksh 内置函数释放内存

AIX - 当无法分叉时使用 ksh 内置函数释放内存

上下文:内存非常低的 AIX lpar(不可能分叉,因此只有 shell 的内置命令(cd、echo、kill)可以工作)。我可以有一个 (hmc) 控制台,但是当内存太低甚至不允许您执行“ps -ef”时,我需要一种更好的方法来开始释放 AIX 中的内存。 (我有办法,但这是一种随机杀死现有PID的方法。我需要有更多关于我可以杀死的PID的信息,所以我可以选择一个不重要的PID)

我想知道 :

  • 我怎么能看到内容仅使用 ksh 内置函数的文件数量
  • 最终目标:我可以查看什么文件的内容,仅使用内置程序,选择要杀死的pid,这样我就只杀死“普通”进程,(当我杀死足够多的PID时,我将能够“ps - ef" "netstat -rn" 等,并且“ps”仍应显示“重要”进程)

我已经知道的:

  • 我可以登录控制台(ssh user@hmc、vtmenu,选择存在 OutOfMemory 问题的 lpar,以 root 身份登录,并且在一段时间(2-5 分钟)后,出现一些关于 ksh 无法在 /etc/ 中分叉命令的抱怨配置文件中,我看到 (ksh) 提示符。

  • 现在我可以模拟“ls”来查看 /proc/PID# 目录存在什么:cd /proc ; echo * 将获得仍在运行的 PID 列表。 (通常我会看到 0、1(init),它们不会被杀死,还有一大堆其他 PID,几乎没有表明它们运行的​​进程(ksh?syncd?ls?java?)。

  • 我还可以: kill some pids here释放足够的内存(kill是ksh(或bash!)中的内置函数,因此无需分叉即可使用它),当我杀死足够多的PID时,我就可以执行其他操作ps -ef netstat -rn,允许我在从 lpar 本身重新启动服务器之前获取服务器的状态shutdown -rF(这将同步、关闭文件系统等。请注意,替代方案(从 HMC 重新启动)通常是不可能的(因为它可能会尝试分叉某些命令) ,除非您添加“--immed”,这就像直接关闭电源一样,不可取,因为它可能会导致文件系统问题,有时在重新启动 lpar 时会导致非常长的 fsck)。

  • 杀死一些 PID 并运行关闭:允许我了解正在运行的内容和需要重新启动的一些“ps -ef”想法,获取路由(以防静态路由不匹配),然后“更优雅地”关闭,保留文件系统并避免启动时冗长的 fsck。)

但我还需要你的帮助:

  • 查看一些文件的内容! (例如:为了能够看到 /var/run/*.pid 中某些 pid 文件的 pid,我会这样做:cd /var/run然后echo *pid获取 pid 文件的列表,但是随后,仅使用 ksh 的内置函数(记住:禁止分叉!)我怎样才能获取这些文件之一的内容?)。同样的技巧也可以帮助在 /proc/PID#/ ...下获取一些信息,也许还可以让我选择要杀死的正确 PID)

  • 使用上面的方法“明智地”选择 PID(或者任何你可以使用的技巧)

精度:如果您的技巧适用于此版本的 ksh 内置函数,则可获得奖励积分:

prompt# strings /usr/bin/ksh | grep '\..*\.' | grep builtin
0@(#)27  1.57.14.5  src/bos/usr/bin/ksh/builtin.c, cmdksh, bos61Z, z2013_29A2 7/5/13 00:10:52

答案1

请尝试这个:

ksh 中包含的内置函数列表:

$ ksh -c 'builtin' 

这是唯一有助于回答您的问题的内置函数:

echo kill print printf read

所以,看来“读取文件”的唯一方法就是使用read。
让我们定义几个函数(在 CLI 中复制并粘贴):

function Usage {
    echo "fileread: filename [from line] [to line]"
    exit 1
}

function fileread {
    [ "$#" -lt 1 ] && echo "please supply the name of a file" && Usage
    linestart=${2:-1}
    lineend=${3:-0}
    i=0
    while IFS=$'\n' read line; do
        i=$((i+1))
        [[ "$i" -lt "$linestart" ]] && continue
        [[ "$lineend" != 0 && "$i" -gt "$lineend" ]] && continue
        echo "$i $line"
    done <"$1"
}

然后,调用该函数(作为示例):

$ cd /var/run
$ fileread sshd.pid 10 20

相关内容