2011-09-14

constructing process tree from the ps -ef result

#! /usr/bin/awk -f

# Usage:
# ps -ef | ./proctree.awk
# ps -f > proclist.txt; ./proctree.awk proclist.txt

BEGIN { pid_col = 2; ppid_col = 3 }

# find the field number for PID and PPID column
/PID +PPID/ {
for (i=1; i < NF; i++) {
if ($i == "PID") {
pid_col = i ; ppid_col = i + 1
print; break
}
}
next
}

{
processes[$pid_col] = $0
children[$ppid_col] = children[$ppid_col] "," $pid_col
if ($ppid_col == 0 || $ppid_col == 1) child_of_swapper_init = child_of_swapper_init "," $pid_col
}

END {
if (0 in processes) {
print processes[0]
split(substr(children[0], 2), child_of_swapper, ",")
for (pid in child_of_swapper) {
if (pid != 1) print processes[pid]
}
}

if (1 in processes) {
print_tree(1, 0)
} else {
## find the top processes.
for (pid in children) {
if (pid in processes) continue
origins = origins "," pid
}

split(substr(origins, 2), top_procs, ",")
for (pid in top_procs) {
print_tree(top_procs[pid], 0)
}
}
}

function print_tree(pid, depth, myfmt, mypid, mychld)
{
if (index(child_of_swapper_init, pid)) depth = 0

if (depth == 0) {
if (pid in processes) {
print processes[pid]
} else {
depth = -1
}
} else {
myfmt = sprintf("%%%is%%s", 3 * depth)
printf(myfmt "\n", " ", processes[pid])
}

split(substr(children[pid], 2), mychld, ",")
for (mypid in mychld) {
print_tree(mychld[mypid], depth + 1)
}
}

#__end__

2011-09-05

How to generate cyclic numbers in ksh

Sometimes, I need to generate limited number of temporary files in loop like below.

while :
do
ps -elf > /tmp/ps.log.$cyclic_number_here
done


Generating cyclic number is an easy job. For example, next function does that.

#! /usr/bin/ksh
GEN_CYCLIC_CALL_COUNT=1
gen_cyclic_number()
{
typeset -i max=$1 mod

((max < 1)) && print 0 && return

((mod = GEN_CYCLIC_CALL_COUNT % max))
if ((mod == 0)); then
((GEN_CYCLIC_CALL_COUNT = max + 1))
print -- $max
else
((GEN_CYCLIC_CALL_COUNT += 1))
print -- $mod
fi
}
But this function will not output the correct numbers when used in command subsititution because it's executed in a subshell.

Correct and easier way is to use proper arithmetic expressions as arithmetic expansion is done in the shell, not in a subshell.

typeset -i i=-1
while :
do
ps -elf > /tmp/ps.log.$((i = (i += 1) % 3)) # generates ps.log.0, ps.log.1, ps.log.2
done


What you need is just 0 and 1, even simpler solution is here.
typeset -i i=1
while :
do
ps -elf > /tmp/ps.log.$((i ^= 1))
done

2011-06-27

Could not access remote file "/usr/local/bin/sstep" in software item

* Problem
In installing depot file using swinstall command in HP-UX, it can fail with next error even though all the installation is done in localhost.

ERROR: Could not access remote file "/usr/local/bin/sstep" in
software item
"tusc.tusc-RUN,r=8.0,a=HP-UX_B.11.31_64,v=:/usr/local" due to
an internal error on the remote system.
ERROR: Failed installing fileset "tusc.tusc-RUN,r=8.0". Check the
above output for details.
* Retry number 1 of 1 for loading files for fileset
"tusc.tusc-RUN,r=8.0".
* Installing fileset "tusc.tusc-RUN,r=8.0" (1 of 1).
ERROR: Could not access remote file "/usr/local/bin/sstep" in
software item
"tusc.tusc-RUN,r=8.0,a=HP-UX_B.11.31_64,v=:/usr/local" due to
an internal error on the remote system.
ERROR: Failed installing fileset "tusc.tusc-RUN,r=8.0". Check the
above output for details.

* Solution
Check if your /etc/hosts file has error, correct it if so.

For example, if your hosts file is like below

127.0.0.1 loopback localhost myhostname
10.10.10.1 myhostname

Change it to

127.0.0.1 loopback localhost
10.10.10.1 myhostname

Then restart the swagentd using "swagentd -r" command.

And run the swinstall again.
For example; swinstall -s $PWD/tusc-8.0-ia64-11.31.depot \*