lxc-ps: use posix shell and awk instead of bash

Use awk to parse the output pf 'ps' and the tasks files for the
containers.

Use awk fields to find PID column rather than assume that the PID field
is exactly 5 chars wide and has a leading space ' PID'. This works as
long as the PID field is before the command or other field that include
spaces. This also makes it work with busybox 'ps'.

Signed-off-by: Natanael Copa <ncopa@alpinelinux.org>
Acked-by: Stéphane Graber <stgraber@ubuntu.com>
This commit is contained in:
Natanael Copa 2012-12-26 22:31:56 +01:00 committed by Stéphane Graber
parent 600faead38
commit b5dec5f30b

View File

@ -1,4 +1,4 @@
#!/bin/bash #!/bin/sh
# #
# lxc: linux Container library # lxc: linux Container library
@ -56,16 +56,16 @@ get_parent_cgroup()
init_cgroup=${fields#*:} init_cgroup=${fields#*:}
# Get the filesystem mountpoint of the hierarchy # Get the filesystem mountpoint of the hierarchy
mountpoint=$(grep -E "^cgroup [^ ]+ [^ ]+ ([^ ]+,)?$subsystems(,[^ ]+)? " /proc/self/mounts | cut -d ' ' -f 2) mountpoint=$(awk -v subsysregex="(^|,)$subsystems(,|\$)" \
'$3 == "cgroup" && $4 ~ subsysregex {print $2}' /proc/self/mounts)
if [ -z "$mountpoint" ]; then continue; fi if [ -z "$mountpoint" ]; then continue; fi
# Return the absolute path to the containers' parent cgroup # Return the absolute path to the containers' parent cgroup
# (do not append '/lxc' if the hierarchy contains the 'ns' subsystem) # (do not append '/lxc' if the hierarchy contains the 'ns' subsystem)
if [[ ",$subsystems," == *,ns,* ]]; then case ",$subsystems," in
parent_cgroup="${mountpoint}${init_cgroup%/}" *,ns,*) parent_cgroup="${mountpoint}${init_cgroup%/}";;
else *) parent_cgroup="${mountpoint}${init_cgroup%/}/lxc";;
parent_cgroup="${mountpoint}${init_cgroup%/}/lxc" esac
fi
break break
done done
} }
@ -97,46 +97,62 @@ if [ ! -d "$parent_cgroup" ]; then
exit 1 exit 1
fi fi
declare -a container_of_pid
container_field_width=9
IFS=","
if [ -z "$containers" ]; then if [ -z "$containers" ]; then
containers=( $(find $parent_cgroup -mindepth 1 -maxdepth 1 -type d -printf "%f," 2>/dev/null) ) containers="$(find $parent_cgroup -mindepth 1 -maxdepth 1 -type d 2>/dev/null | sed 's:.*/::')"
else
containers=( $containers )
fi fi
declare -i pid container_field_width=9
IFS=$'\n' tasks_files=
for container in ${containers[@]}; do for container in ${containers}; do
if [ "${#container}" -gt "$container_field_width" ]; then if [ "${#container}" -gt "$container_field_width" ]; then
container_field_width=${#container} container_field_width=${#container}
fi fi
if [ -f "$parent_cgroup/$container/tasks" ]; then if [ -f "$parent_cgroup/$container/tasks" ]; then
while read pid; do tasks_files="$tasks_files $parent_cgroup/$container/tasks"
container_of_pid[$pid]=$container
done < "$parent_cgroup/$container/tasks"
fi fi
done done
declare -i line_pid_end_position # first file is stdin, the rest are the container tasks
while read line; do ps "$@" | awk -v container_field_width="$container_field_width" '
if [ -z "$line_pid_end_position" ]; then # first line is PS header
if [[ "$line" != *" PID"* ]]; then NR == 1 {
echo "$(basename $0): no PID column found in \`ps' output" >&2 # find pid field index
exit 1 for (i = 1; i<=NF; i++)
fi if ($i == "PID") {
pididx = i
break
}
if (pididx == "") {
print("No PID field found") > "/dev/stderr"
exit 1
}
header = $0
next
}
buffer=${line%" PID"*} # store lines from ps with pid as index
let line_pid_end_position=${#buffer}+4 NR == FNR {
printf "%-${container_field_width}s %s\n" "CONTAINER" "$line" ps[$pididx] = $0
continue next
fi }
buffer=${line:0:$line_pid_end_position} # find container name from filename on first line
pid=${buffer##* } FNR == 1 {
if [ "$list_container_processes" -eq "0" -o ! -z "${container_of_pid[pid]}" ]; then container = FILENAME
printf "%-${container_field_width}s %s\n" "${container_of_pid[pid]}" "$line" sub(/\/tasks/, "", container)
fi sub(/.*\//, "", container)
done < <(ps "$@") }
# container tasks
{
container_of_pid[$0] = container
}
END {
printf("%-" container_field_width "s %s\n", "CONTAINER", header)
for (pid in container_of_pid)
printf("%-" container_field_width "s %s\n", container_of_pid[pid], ps[pid])
}
' - $tasks_files