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 <nc...@alpinelinux.org>
---
 src/lxc/lxc-ps.in | 92 ++++++++++++++++++++++++++++++++-----------------------
 1 file changed, 54 insertions(+), 38 deletions(-)

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


------------------------------------------------------------------------------
Master Java SE, Java EE, Eclipse, Spring, Hibernate, JavaScript, jQuery
and much more. Keep your Java skills current with LearnJavaNow -
200+ hours of step-by-step video tutorials by Java experts.
SALE $49.99 this month only -- learn more at:
http://p.sf.net/sfu/learnmore_122612 
_______________________________________________
Lxc-devel mailing list
Lxc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/lxc-devel

Reply via email to