Ksh
AIX - 在無法分叉時使用 ksh 內置函式來釋放記憶體
上下文:具有非常低記憶體的 AIX lpar(不可能進行分叉,因此只有 shell 的內置函式(cd、echo、kill)可以工作)。我可以有一個 (hmc) 控制台,但我需要一種更好的方法來開始在 AIX 中釋放記憶體,當記憶體太低甚至無法執行“ps -ef”時。(我有辦法,但它是一種隨機殺死現有 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
請試試這個:
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