Commit b5dec5f3 by Natanael Copa Committed by Stéphane Graber

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: 's avatarNatanael Copa <ncopa@alpinelinux.org> Acked-by: 's avatarStéphane Graber <stgraber@ubuntu.com>
parent 600faead
#!/bin/bash #!/bin/sh
# #
# lxc: linux Container library # lxc: linux Container library
...@@ -56,16 +56,16 @@ get_parent_cgroup() ...@@ -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 ...@@ -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
for (i = 1; i<=NF; i++)
if ($i == "PID") {
pididx = i
break
}
if (pididx == "") {
print("No PID field found") > "/dev/stderr"
exit 1 exit 1
fi }
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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment