mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-08-07 18:56:40 +00:00
refresh lxc-netstat
Modify the cgroup search to only use hierarchies that contain one or more subsystems. When searching, if a hierarchy contains the 'ns' subsystem, do not append '/lxc' to the parent cgroup. Change method of bind mounting /proc/<pid>/net onto /proc/net, to avoid error "cannot mount block device /proc/<pid>/net read-only". Check that user is root. Check that container name is specified before calling 'exec'. Update the help information. Print error messages and help information to stderr. Make indentation consistent. Signed-off-by: David Ward <david.ward@ll.mit.edu> Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
This commit is contained in:
parent
7ef0141356
commit
5e52afd528
@ -1,21 +1,70 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# set -ex
|
|
||||||
|
#
|
||||||
|
# lxc: linux Container library
|
||||||
|
|
||||||
|
# This library is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU Lesser General Public
|
||||||
|
# License as published by the Free Software Foundation; either
|
||||||
|
# version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
# This library is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# Lesser General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU Lesser General Public
|
||||||
|
# License along with this library; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
echo "usage: $(basename $0) --name <name> [netstat options]"
|
echo "usage: $(basename $0) --name NAME [--] [NETSTAT_OPTIONS...]" >&2
|
||||||
}
|
}
|
||||||
|
|
||||||
help() {
|
help() {
|
||||||
usage
|
usage
|
||||||
echo
|
echo >&2
|
||||||
echo "execute netstat for the specified container"
|
echo "Execute 'netstat' for the specified container." >&2
|
||||||
echo "with the added netstat options"
|
echo >&2
|
||||||
echo
|
echo " --name NAME specify the container name" >&2
|
||||||
echo "Options:"
|
echo " NETSTAT_OPTIONS netstat command options (see \`netstat --help')" >&2
|
||||||
echo "name : name of the container"
|
}
|
||||||
echo "help : this current help."
|
|
||||||
echo
|
get_parent_cgroup()
|
||||||
echo "to be executed as root."
|
{
|
||||||
|
local hierarchies hierarchy fields subsystems init_cgroup mountpoint
|
||||||
|
|
||||||
|
parent_cgroup=""
|
||||||
|
|
||||||
|
# Obtain a list of hierarchies that contain one or more subsystems
|
||||||
|
hierarchies=$(tail -n +2 /proc/cgroups | cut -f 2)
|
||||||
|
|
||||||
|
# Iterate through the list until a suitable hierarchy is found
|
||||||
|
for hierarchy in $hierarchies; do
|
||||||
|
# Obtain information about the init process in the hierarchy
|
||||||
|
fields=$(grep -E "^$hierarchy:" /proc/1/cgroup | head -n 1)
|
||||||
|
if [ -z "$fields" ]; then continue; fi
|
||||||
|
fields=${fields#*:}
|
||||||
|
|
||||||
|
# Get a comma-separated list of the hierarchy's subsystems
|
||||||
|
subsystems=${fields%:*}
|
||||||
|
|
||||||
|
# Get the cgroup of the init process in the hierarchy
|
||||||
|
init_cgroup=${fields#*:}
|
||||||
|
|
||||||
|
# Get the filesystem mountpoint of the hierarchy
|
||||||
|
mountpoint=$(grep -E "^cgroup [^ ]+ [^ ]+ ([^ ]+,)?$subsystems(,[^ ]+)? " /proc/self/mounts | cut -d ' ' -f 2)
|
||||||
|
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
|
||||||
|
break
|
||||||
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
exec=""
|
exec=""
|
||||||
@ -25,19 +74,24 @@ if [ $# -eq 0 ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for i in "$@"; do
|
while true; do
|
||||||
case $i in
|
case $1 in
|
||||||
-h|--help)
|
-h|--help)
|
||||||
help; exit 1;;
|
help; exit 1;;
|
||||||
-n|--name)
|
-n|--name)
|
||||||
name=$2; shift 2;;
|
name=$2; shift 2;;
|
||||||
--exec)
|
--exec)
|
||||||
exec="exec"; shift;;
|
exec="exec"; shift;;
|
||||||
|
--)
|
||||||
|
shift; break;;
|
||||||
|
*)
|
||||||
|
break;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ -z "$exec" ]; then
|
if [ "$(id -u)" != "0" ]; then
|
||||||
exec @BINDIR@/lxc-unshare -s MOUNT -- $0 -n $name --exec "$@"
|
echo "$(basename $0): must be run as root" >&2
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$name" ]; then
|
if [ -z "$name" ]; then
|
||||||
@ -45,51 +99,43 @@ if [ -z "$name" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ -z "$exec" ]; then
|
||||||
|
exec @BINDIR@/lxc-unshare -s MOUNT -- $0 -n $name --exec "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
lxc-info -n $name 2>&1 | grep -q 'STOPPED'
|
lxc-info -n $name 2>&1 | grep -q 'STOPPED'
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
echo "Container $name is not running"
|
echo "$(basename $0): container '$name' is not running" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cgroups=$(mount -l -t cgroup)
|
get_parent_cgroup
|
||||||
cgroup_path=""
|
if [ ! -d "$parent_cgroup" ]; then
|
||||||
|
echo "$(basename $0): no cgroup mount point found" >&2
|
||||||
for i in "$cgroups"; do
|
exit 1
|
||||||
|
|
||||||
cgroup_name=$(echo $i | awk ' { print $1 } ')
|
|
||||||
cgroup_path=$(echo $i | awk ' { print $3 } ')
|
|
||||||
|
|
||||||
if [ "$cgroup_name" == "lxc" ]; then
|
|
||||||
break;
|
|
||||||
fi
|
|
||||||
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ -z "$cgroup_path" ]; then
|
|
||||||
cgroups=`grep -m1 -E '^[^ \t]+[ \t]+[^ \t]+[ \t]+cgroup' /proc/self/mounts`
|
|
||||||
for i in "$cgroups"; do
|
|
||||||
cgroup_path=$(echo $i | awk ' { print $2 } ')
|
|
||||||
if [ -n $cgroup_path ]; then
|
|
||||||
break;
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$cgroup_path" ]; then
|
pid=$(head -1 $parent_cgroup/$name/tasks)
|
||||||
echo "no cgroup mount point found"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# the container will be in:
|
|
||||||
# ${cgroup_path}.${init_cgroup_path}."lxc".$name
|
|
||||||
init_cgroup=`cat /proc/1/cgroup | awk -F: '{ print $3 }' | head -1`
|
|
||||||
final_cgroup_path=$cgroup_path/$init_cgroup/lxc
|
|
||||||
pid=$(head -1 $final_cgroup_path/$name/tasks)
|
|
||||||
|
|
||||||
if [ -z "$pid" ]; then
|
if [ -z "$pid" ]; then
|
||||||
echo "no process found for '$name'"
|
echo "$(basename $0): no process found for '$name'" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mount -n --bind /proc/$pid/net /proc/$$/net && \
|
tmpdir=$(mktemp -d)
|
||||||
|
|
||||||
|
if [ -z "$tmpdir" -o ! -d "$tmpdir" ]; then
|
||||||
|
echo "$(basename $0): unable to create temporary directory" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Bind mount /proc/$pid/net onto /proc/net before calling 'netstat'.
|
||||||
|
# However, we can not simply bind mount on top of procfs, so we have
|
||||||
|
# to move procfs out of the way first.
|
||||||
|
mount -n --move /proc "$tmpdir" && \
|
||||||
|
mount -n -t tmpfs tmpfs /proc && \
|
||||||
|
mkdir /proc/root /proc/net && \
|
||||||
|
mount -n --move "$tmpdir" /proc/root && \
|
||||||
|
rmdir "$tmpdir" && \
|
||||||
|
mount -n --bind /proc/root/$pid/net /proc/net && \
|
||||||
exec netstat "$@"
|
exec netstat "$@"
|
||||||
|
Loading…
Reference in New Issue
Block a user