[lxc-devel] [PATCH] lxc-ps: use posix shell and awk instead of bash
Stéphane Graber
stgraber at ubuntu.com
Wed Jan 2 18:00:10 UTC 2013
On 12/26/2012 04:31 PM, Natanael Copa wrote:
> 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 at alpinelinux.org>
Looks good. Pushed.
Acked-by: Stéphane Graber <stgraber at ubuntu.com>
> ---
> 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
>
--
Stéphane Graber
Ubuntu developer
http://www.ubuntu.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 899 bytes
Desc: OpenPGP digital signature
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20130102/6a3c1623/attachment.pgp>
More information about the lxc-devel
mailing list