[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